@dreamtree-org/twreact-ui 1.1.11 → 1.1.13

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 CHANGED
@@ -4326,7 +4326,7 @@ function ActionMenu(_ref) {
4326
4326
  }
4327
4327
  }, /*#__PURE__*/React__default.createElement("div", {
4328
4328
  className: "p-1"
4329
- }, actions.length === 0 ? /*#__PURE__*/React__default.createElement("div", {
4329
+ }, !Array.isArray(actions) || actions.length === 0 ? /*#__PURE__*/React__default.createElement("div", {
4330
4330
  className: "px-3 py-2 text-sm text-gray-500"
4331
4331
  }, "No actions") : actions.map(function (action) {
4332
4332
  return /*#__PURE__*/React__default.createElement("div", {
@@ -4394,14 +4394,15 @@ function TableRow(_ref) {
4394
4394
  rowIndex: globalIndex
4395
4395
  }) : "";
4396
4396
  var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4397
- var stripeBg = stripedRows && !isSelected ? theme.stripedColors[globalIndex % theme.stripedColors.length] : undefined;
4397
+ var stripeColors = theme === null || theme === void 0 ? void 0 : theme.stripedColors;
4398
+ var stripeBg = stripedRows && !isSelected && Array.isArray(stripeColors) && stripeColors.length > 0 ? stripeColors[globalIndex % stripeColors.length] : undefined;
4398
4399
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, {
4399
4400
  key: key
4400
4401
  }, /*#__PURE__*/React__default.createElement("tr", {
4401
4402
  style: stripeBg ? {
4402
4403
  backgroundColor: stripeBg
4403
4404
  } : undefined,
4404
- className: cn$1(["hover:" + theme.rowHover], {
4405
+ className: cn$1(theme !== null && theme !== void 0 && theme.rowHover ? ["hover:" + theme.rowHover] : [], {
4405
4406
  "cursor-pointer": !!onRowClick,
4406
4407
  "bg-primary-50": isSelected
4407
4408
  }, safeExtraRowClass),
@@ -4527,7 +4528,7 @@ function MobileCard(_ref) {
4527
4528
  rowIndex: globalIndex
4528
4529
  }) : "";
4529
4530
  var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4530
- var stripeBg = stripedRows && !isSelected ? stripedColors[globalIndex % stripedColors.length] : undefined;
4531
+ var stripeBg = stripedRows && !isSelected && Array.isArray(stripedColors) && stripedColors.length > 0 ? stripedColors[globalIndex % stripedColors.length] : undefined;
4531
4532
  return /*#__PURE__*/React__default.createElement("div", {
4532
4533
  key: key,
4533
4534
  style: stripeBg ? {
@@ -4834,10 +4835,11 @@ var Table = function Table(_ref) {
4834
4835
  });
4835
4836
  }, [columnsState]);
4836
4837
  var sortedData = useMemo(function () {
4837
- if (serverSide || !sortConfig.key) return tableData;
4838
+ var data = Array.isArray(tableData) ? tableData : [];
4839
+ if (serverSide || !sortConfig.key) return data;
4838
4840
  var key = sortConfig.key,
4839
4841
  direction = sortConfig.direction;
4840
- return _toConsumableArray$1(tableData).sort(function (a, b) {
4842
+ return _toConsumableArray$1(data).sort(function (a, b) {
4841
4843
  var av = a === null || a === void 0 ? void 0 : a[key];
4842
4844
  var bv = b === null || b === void 0 ? void 0 : b[key];
4843
4845
  if (av == null || bv == null) return 0;
@@ -4848,19 +4850,21 @@ var Table = function Table(_ref) {
4848
4850
  });
4849
4851
  }, [tableData, sortConfig, serverSide]);
4850
4852
  var filteredData = useMemo(function () {
4851
- if (serverSide || !filterable || !Object.keys(filters).length) return sortedData;
4853
+ var data = Array.isArray(sortedData) ? sortedData : [];
4854
+ if (serverSide || !filterable || !Object.keys(filters || {}).length) return data;
4852
4855
  var q = (filters.global || "").toLowerCase();
4853
- return sortedData.filter(function (row) {
4856
+ return data.filter(function (row) {
4854
4857
  return Object.values(row || {}).some(function (v) {
4855
4858
  return String(v).toLowerCase().includes(q);
4856
4859
  });
4857
4860
  });
4858
4861
  }, [sortedData, filters, filterable, serverSide]);
4859
4862
  var _useMemo = useMemo(function () {
4863
+ var data = Array.isArray(filteredData) ? filteredData : [];
4860
4864
  var start = pagination ? (currentPage - 1) * limit : 0;
4861
- var end = pagination ? start + limit : filteredData.length;
4862
- var paginated = !pagination || serverSide ? filteredData : filteredData.slice(start, start + limit);
4863
- var pages = !pagination ? 1 : serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
4865
+ var end = pagination ? start + limit : data.length;
4866
+ var paginated = !pagination || serverSide ? data : data.slice(start, start + limit);
4867
+ var pages = !pagination ? 1 : serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(data.length / limit));
4864
4868
  return {
4865
4869
  startIndex: start,
4866
4870
  endIndex: end,
@@ -5054,18 +5058,21 @@ var Table = function Table(_ref) {
5054
5058
  setSearchInput(filters.global || "");
5055
5059
  }, [filters.global]);
5056
5060
 
5057
- // Shared props for row components
5061
+ // Shared props for row components (MobileCard expects stripedColors array)
5062
+ var safeTheme = theme || DEFAULT_THEME;
5063
+ var stripedColorsArray = Array.isArray(safeTheme.stripedColors) ? safeTheme.stripedColors : DEFAULT_THEME.stripedColors;
5058
5064
  var rowSharedProps = {
5059
5065
  selectedRows: selectedRows,
5060
5066
  expandedRows: expandedRows,
5061
5067
  rowClass: rowClass,
5062
5068
  stripedRows: stripedRows,
5063
- theme: theme,
5069
+ theme: safeTheme,
5070
+ stripedColors: stripedColorsArray,
5064
5071
  onRowClick: onRowClick,
5065
5072
  hasDetails: hasDetails,
5066
5073
  showSerial: showSerial,
5067
5074
  selectable: selectable,
5068
- visibleColumns: visibleColumns,
5075
+ visibleColumns: Array.isArray(visibleColumns) ? visibleColumns : [],
5069
5076
  cellClass: cellClass,
5070
5077
  withAction: withAction,
5071
5078
  DetailsComponent: DetailsComponent,
@@ -15953,9 +15960,19 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
15953
15960
  _ref$autoStart = _ref.autoStart,
15954
15961
  autoStart = _ref$autoStart === void 0 ? false : _ref$autoStart,
15955
15962
  _ref$disabled = _ref.disabled,
15956
- disabled = _ref$disabled === void 0 ? false : _ref$disabled;
15963
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
15964
+ _ref$maxAlternatives = _ref.maxAlternatives,
15965
+ maxAlternatives = _ref$maxAlternatives === void 0 ? 1 : _ref$maxAlternatives,
15966
+ _ref$grammars = _ref.grammars,
15967
+ grammars = _ref$grammars === void 0 ? null : _ref$grammars,
15968
+ _ref$timeout = _ref.timeout,
15969
+ timeout = _ref$timeout === void 0 ? null : _ref$timeout,
15970
+ _ref$clearOnStop = _ref.clearOnStop,
15971
+ clearOnStop = _ref$clearOnStop === void 0 ? false : _ref$clearOnStop;
15957
15972
  var recognitionRef = useRef(null);
15958
15973
  var finalTranscriptRef = useRef("");
15974
+ var timeoutRef = useRef(null);
15975
+ var isMountedRef = useRef(true);
15959
15976
  var _useState = useState(false),
15960
15977
  _useState2 = _slicedToArray(_useState, 2),
15961
15978
  _isListening = _useState2[0],
@@ -15964,34 +15981,48 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
15964
15981
  _useState4 = _slicedToArray(_useState3, 2),
15965
15982
  _isSupported = _useState4[0],
15966
15983
  setIsSupported = _useState4[1];
15984
+ var _useState5 = useState(null),
15985
+ _useState6 = _slicedToArray(_useState5, 2),
15986
+ error = _useState6[0],
15987
+ setError = _useState6[1];
15988
+
15989
+ // Check browser support
15967
15990
  useEffect(function () {
15968
- if (!("webkitSpeechRecognition" in window) && !("SpeechRecognition" in window)) {
15969
- setIsSupported(false);
15970
- } else {
15971
- setIsSupported(true);
15991
+ var supported = "webkitSpeechRecognition" in window || "SpeechRecognition" in window;
15992
+ setIsSupported(supported);
15993
+ if (!supported) {
15994
+ var err = new Error("Speech recognition not supported in this browser");
15995
+ setError(err);
15996
+ onError(err);
15972
15997
  }
15973
- }, []);
15974
- useEffect(function () {
15975
- if (autoStart && _isSupported) {
15976
- startListening();
15998
+ }, [onError]);
15999
+
16000
+ // Clear timeout helper
16001
+ var clearInactivityTimeout = useCallback(function () {
16002
+ if (timeoutRef.current) {
16003
+ clearTimeout(timeoutRef.current);
16004
+ timeoutRef.current = null;
15977
16005
  }
15978
- return function () {
15979
- if (recognitionRef.current) {
15980
- try {
15981
- recognitionRef.current.onresult = null;
15982
- recognitionRef.current.onerror = null;
15983
- recognitionRef.current.onend = null;
15984
- recognitionRef.current.onstart = null;
15985
- recognitionRef.current.stop();
15986
- } catch (e) {}
16006
+ }, []);
16007
+
16008
+ // Reset inactivity timeout
16009
+ var resetInactivityTimeout = useCallback(function () {
16010
+ if (!timeout) return;
16011
+ clearInactivityTimeout();
16012
+ timeoutRef.current = setTimeout(function () {
16013
+ if (recognitionRef.current && _isListening) {
16014
+ stopListening();
15987
16015
  }
15988
- };
15989
- }, [autoStart, _isSupported]);
15990
- function initializeRecognition() {
16016
+ }, timeout);
16017
+ }, [timeout, _isListening]);
16018
+
16019
+ // Initialize recognition
16020
+ var initializeRecognition = useCallback(function () {
15991
16021
  if (recognitionRef.current) return recognitionRef.current;
15992
16022
  var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
15993
16023
  if (!SpeechRecognition) {
15994
16024
  var err = new Error("SpeechRecognition API not available");
16025
+ setError(err);
15995
16026
  onError(err);
15996
16027
  return null;
15997
16028
  }
@@ -15999,12 +16030,21 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
15999
16030
  recognition.continuous = !!continuous;
16000
16031
  recognition.interimResults = !!interimResults;
16001
16032
  recognition.lang = lang;
16033
+ recognition.maxAlternatives = maxAlternatives;
16034
+ if (grammars) {
16035
+ recognition.grammars = grammars;
16036
+ }
16002
16037
  recognition.onstart = function () {
16038
+ if (!isMountedRef.current) return;
16003
16039
  finalTranscriptRef.current = finalTranscriptRef.current || "";
16004
16040
  setIsListening(true);
16041
+ setError(null);
16042
+ resetInactivityTimeout();
16005
16043
  onStart();
16006
16044
  };
16007
16045
  recognition.onresult = function (event) {
16046
+ if (!isMountedRef.current) return;
16047
+ resetInactivityTimeout();
16008
16048
  var interim = "";
16009
16049
  var finalPart = "";
16010
16050
  for (var i = event.resultIndex; i < event.results.length; i++) {
@@ -16024,21 +16064,48 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
16024
16064
  }
16025
16065
  };
16026
16066
  recognition.onerror = function (event) {
16027
- var err = event && event.error ? new Error(event.error) : new Error("Speech recognition error");
16028
- onError(err);
16067
+ if (!isMountedRef.current) return;
16068
+ clearInactivityTimeout();
16069
+ var errorMessage = (event === null || event === void 0 ? void 0 : event.error) || "Speech recognition error";
16070
+ var err = new Error(errorMessage);
16071
+ setError(err);
16029
16072
  setIsListening(false);
16073
+ onError(err);
16074
+
16075
+ // Handle specific errors
16076
+ if (errorMessage === "not-allowed" || errorMessage === "service-not-allowed") {
16077
+ console.warn("Microphone permission denied");
16078
+ } else if (errorMessage === "no-speech") {
16079
+ console.warn("No speech detected");
16080
+ } else if (errorMessage === "aborted") {
16081
+ console.warn("Speech recognition aborted");
16082
+ }
16030
16083
  };
16031
16084
  recognition.onend = function () {
16085
+ if (!isMountedRef.current) return;
16086
+ clearInactivityTimeout();
16032
16087
  setIsListening(false);
16088
+ var finalText = (finalTranscriptRef.current || "").trim();
16089
+ onSpeechComplete(finalText);
16033
16090
  onStop();
16034
- onSpeechComplete((finalTranscriptRef.current || "").trim());
16091
+ if (clearOnStop) {
16092
+ finalTranscriptRef.current = "";
16093
+ }
16035
16094
  };
16036
16095
  recognitionRef.current = recognition;
16037
16096
  return recognition;
16038
- }
16039
- function startListening() {
16097
+ }, [continuous, interimResults, lang, maxAlternatives, grammars, onStart, onSpeaking, onSpeechComplete, onError, onStop, clearOnStop, resetInactivityTimeout, clearInactivityTimeout]);
16098
+
16099
+ // Start listening
16100
+ var startListening = useCallback(function () {
16040
16101
  if (!_isSupported) {
16041
- onError(new Error("Speech recognition not supported in this browser"));
16102
+ var err = new Error("Speech recognition not supported in this browser");
16103
+ setError(err);
16104
+ onError(err);
16105
+ return;
16106
+ }
16107
+ if (_isListening) {
16108
+ console.warn("Already listening");
16042
16109
  return;
16043
16110
  }
16044
16111
  try {
@@ -16046,24 +16113,68 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
16046
16113
  if (!rec) return;
16047
16114
  rec.start();
16048
16115
  } catch (err) {
16116
+ var _err$message;
16117
+ // Handle "already started" error
16118
+ if ((_err$message = err.message) !== null && _err$message !== void 0 && _err$message.includes("already started")) {
16119
+ console.warn("Recognition already in progress");
16120
+ return;
16121
+ }
16122
+ setError(err);
16049
16123
  onError(err);
16050
16124
  }
16051
- }
16052
- function stopListening() {
16125
+ }, [_isSupported, _isListening, initializeRecognition, onError]);
16126
+
16127
+ // Stop listening
16128
+ var stopListening = useCallback(function () {
16053
16129
  if (recognitionRef.current) {
16054
16130
  try {
16131
+ clearInactivityTimeout();
16055
16132
  recognitionRef.current.stop();
16056
- } catch (e) {}
16133
+ } catch (err) {
16134
+ console.error("Error stopping recognition:", err);
16135
+ }
16057
16136
  }
16058
- }
16059
- function toggleListening() {
16137
+ }, [clearInactivityTimeout]);
16138
+
16139
+ // Toggle listening
16140
+ var toggleListening = useCallback(function () {
16060
16141
  if (disabled) return;
16061
16142
  if (_isListening) {
16062
16143
  stopListening();
16063
16144
  } else {
16064
16145
  startListening();
16065
16146
  }
16066
- }
16147
+ }, [disabled, _isListening, startListening, stopListening]);
16148
+
16149
+ // Auto-start effect
16150
+ useEffect(function () {
16151
+ if (autoStart && _isSupported && !disabled) {
16152
+ startListening();
16153
+ }
16154
+ }, [autoStart, _isSupported, disabled, startListening]);
16155
+
16156
+ // Cleanup on unmount
16157
+ useEffect(function () {
16158
+ isMountedRef.current = true;
16159
+ return function () {
16160
+ isMountedRef.current = false;
16161
+ clearInactivityTimeout();
16162
+ if (recognitionRef.current) {
16163
+ try {
16164
+ recognitionRef.current.onresult = null;
16165
+ recognitionRef.current.onerror = null;
16166
+ recognitionRef.current.onend = null;
16167
+ recognitionRef.current.onstart = null;
16168
+ recognitionRef.current.stop();
16169
+ } catch (err) {
16170
+ console.error("Cleanup error:", err);
16171
+ }
16172
+ recognitionRef.current = null;
16173
+ }
16174
+ };
16175
+ }, [clearInactivityTimeout]);
16176
+
16177
+ // Imperative handle
16067
16178
  useImperativeHandle(ref, function () {
16068
16179
  return {
16069
16180
  start: startListening,
@@ -16080,26 +16191,39 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
16080
16191
  },
16081
16192
  clearTranscript: function clearTranscript() {
16082
16193
  finalTranscriptRef.current = "";
16194
+ },
16195
+ getError: function getError() {
16196
+ return error;
16083
16197
  }
16084
16198
  };
16085
- }, [_isListening, _isSupported]);
16199
+ }, [_isListening, _isSupported, error, startListening, stopListening, toggleListening]);
16200
+
16201
+ // Custom button renderer
16086
16202
  if (renderButton && typeof renderButton === "function") {
16087
16203
  return renderButton({
16088
16204
  isListening: _isListening,
16089
16205
  isSupported: _isSupported,
16206
+ error: error,
16090
16207
  start: startListening,
16091
16208
  stop: stopListening,
16092
16209
  toggle: toggleListening,
16093
- disabled: disabled
16210
+ disabled: disabled || !_isSupported
16094
16211
  });
16095
16212
  }
16213
+
16214
+ // Default button
16096
16215
  return /*#__PURE__*/React__default.createElement("button", {
16097
16216
  type: "button",
16098
16217
  "aria-pressed": _isListening,
16218
+ "aria-label": _isListening ? "Stop listening" : "Start listening",
16099
16219
  onClick: toggleListening,
16100
- disabled: disabled || !_isSupported
16101
- }, _isListening ? "Stop" : "Start");
16220
+ disabled: disabled || !_isSupported,
16221
+ style: {
16222
+ cursor: disabled || !_isSupported ? "not-allowed" : "pointer"
16223
+ }
16224
+ }, _isListening ? "🎤 Stop" : "🎤 Start");
16102
16225
  });
16226
+ SpeechToText.displayName = "SpeechToText";
16103
16227
 
16104
16228
  var TextToSpeech = function TextToSpeech(_ref) {
16105
16229
  var _ref$text = _ref.text,
package/dist/index.js CHANGED
@@ -4346,7 +4346,7 @@ function ActionMenu(_ref) {
4346
4346
  }
4347
4347
  }, /*#__PURE__*/React.createElement("div", {
4348
4348
  className: "p-1"
4349
- }, actions.length === 0 ? /*#__PURE__*/React.createElement("div", {
4349
+ }, !Array.isArray(actions) || actions.length === 0 ? /*#__PURE__*/React.createElement("div", {
4350
4350
  className: "px-3 py-2 text-sm text-gray-500"
4351
4351
  }, "No actions") : actions.map(function (action) {
4352
4352
  return /*#__PURE__*/React.createElement("div", {
@@ -4414,14 +4414,15 @@ function TableRow(_ref) {
4414
4414
  rowIndex: globalIndex
4415
4415
  }) : "";
4416
4416
  var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4417
- var stripeBg = stripedRows && !isSelected ? theme.stripedColors[globalIndex % theme.stripedColors.length] : undefined;
4417
+ var stripeColors = theme === null || theme === void 0 ? void 0 : theme.stripedColors;
4418
+ var stripeBg = stripedRows && !isSelected && Array.isArray(stripeColors) && stripeColors.length > 0 ? stripeColors[globalIndex % stripeColors.length] : undefined;
4418
4419
  return /*#__PURE__*/React.createElement(React.Fragment, {
4419
4420
  key: key
4420
4421
  }, /*#__PURE__*/React.createElement("tr", {
4421
4422
  style: stripeBg ? {
4422
4423
  backgroundColor: stripeBg
4423
4424
  } : undefined,
4424
- className: cn$1(["hover:" + theme.rowHover], {
4425
+ className: cn$1(theme !== null && theme !== void 0 && theme.rowHover ? ["hover:" + theme.rowHover] : [], {
4425
4426
  "cursor-pointer": !!onRowClick,
4426
4427
  "bg-primary-50": isSelected
4427
4428
  }, safeExtraRowClass),
@@ -4547,7 +4548,7 @@ function MobileCard(_ref) {
4547
4548
  rowIndex: globalIndex
4548
4549
  }) : "";
4549
4550
  var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4550
- var stripeBg = stripedRows && !isSelected ? stripedColors[globalIndex % stripedColors.length] : undefined;
4551
+ var stripeBg = stripedRows && !isSelected && Array.isArray(stripedColors) && stripedColors.length > 0 ? stripedColors[globalIndex % stripedColors.length] : undefined;
4551
4552
  return /*#__PURE__*/React.createElement("div", {
4552
4553
  key: key,
4553
4554
  style: stripeBg ? {
@@ -4854,10 +4855,11 @@ var Table = function Table(_ref) {
4854
4855
  });
4855
4856
  }, [columnsState]);
4856
4857
  var sortedData = React.useMemo(function () {
4857
- if (serverSide || !sortConfig.key) return tableData;
4858
+ var data = Array.isArray(tableData) ? tableData : [];
4859
+ if (serverSide || !sortConfig.key) return data;
4858
4860
  var key = sortConfig.key,
4859
4861
  direction = sortConfig.direction;
4860
- return _toConsumableArray$1(tableData).sort(function (a, b) {
4862
+ return _toConsumableArray$1(data).sort(function (a, b) {
4861
4863
  var av = a === null || a === void 0 ? void 0 : a[key];
4862
4864
  var bv = b === null || b === void 0 ? void 0 : b[key];
4863
4865
  if (av == null || bv == null) return 0;
@@ -4868,19 +4870,21 @@ var Table = function Table(_ref) {
4868
4870
  });
4869
4871
  }, [tableData, sortConfig, serverSide]);
4870
4872
  var filteredData = React.useMemo(function () {
4871
- if (serverSide || !filterable || !Object.keys(filters).length) return sortedData;
4873
+ var data = Array.isArray(sortedData) ? sortedData : [];
4874
+ if (serverSide || !filterable || !Object.keys(filters || {}).length) return data;
4872
4875
  var q = (filters.global || "").toLowerCase();
4873
- return sortedData.filter(function (row) {
4876
+ return data.filter(function (row) {
4874
4877
  return Object.values(row || {}).some(function (v) {
4875
4878
  return String(v).toLowerCase().includes(q);
4876
4879
  });
4877
4880
  });
4878
4881
  }, [sortedData, filters, filterable, serverSide]);
4879
4882
  var _useMemo = React.useMemo(function () {
4883
+ var data = Array.isArray(filteredData) ? filteredData : [];
4880
4884
  var start = pagination ? (currentPage - 1) * limit : 0;
4881
- var end = pagination ? start + limit : filteredData.length;
4882
- var paginated = !pagination || serverSide ? filteredData : filteredData.slice(start, start + limit);
4883
- var pages = !pagination ? 1 : serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
4885
+ var end = pagination ? start + limit : data.length;
4886
+ var paginated = !pagination || serverSide ? data : data.slice(start, start + limit);
4887
+ var pages = !pagination ? 1 : serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(data.length / limit));
4884
4888
  return {
4885
4889
  startIndex: start,
4886
4890
  endIndex: end,
@@ -5074,18 +5078,21 @@ var Table = function Table(_ref) {
5074
5078
  setSearchInput(filters.global || "");
5075
5079
  }, [filters.global]);
5076
5080
 
5077
- // Shared props for row components
5081
+ // Shared props for row components (MobileCard expects stripedColors array)
5082
+ var safeTheme = theme || DEFAULT_THEME;
5083
+ var stripedColorsArray = Array.isArray(safeTheme.stripedColors) ? safeTheme.stripedColors : DEFAULT_THEME.stripedColors;
5078
5084
  var rowSharedProps = {
5079
5085
  selectedRows: selectedRows,
5080
5086
  expandedRows: expandedRows,
5081
5087
  rowClass: rowClass,
5082
5088
  stripedRows: stripedRows,
5083
- theme: theme,
5089
+ theme: safeTheme,
5090
+ stripedColors: stripedColorsArray,
5084
5091
  onRowClick: onRowClick,
5085
5092
  hasDetails: hasDetails,
5086
5093
  showSerial: showSerial,
5087
5094
  selectable: selectable,
5088
- visibleColumns: visibleColumns,
5095
+ visibleColumns: Array.isArray(visibleColumns) ? visibleColumns : [],
5089
5096
  cellClass: cellClass,
5090
5097
  withAction: withAction,
5091
5098
  DetailsComponent: DetailsComponent,
@@ -15973,9 +15980,19 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
15973
15980
  _ref$autoStart = _ref.autoStart,
15974
15981
  autoStart = _ref$autoStart === void 0 ? false : _ref$autoStart,
15975
15982
  _ref$disabled = _ref.disabled,
15976
- disabled = _ref$disabled === void 0 ? false : _ref$disabled;
15983
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
15984
+ _ref$maxAlternatives = _ref.maxAlternatives,
15985
+ maxAlternatives = _ref$maxAlternatives === void 0 ? 1 : _ref$maxAlternatives,
15986
+ _ref$grammars = _ref.grammars,
15987
+ grammars = _ref$grammars === void 0 ? null : _ref$grammars,
15988
+ _ref$timeout = _ref.timeout,
15989
+ timeout = _ref$timeout === void 0 ? null : _ref$timeout,
15990
+ _ref$clearOnStop = _ref.clearOnStop,
15991
+ clearOnStop = _ref$clearOnStop === void 0 ? false : _ref$clearOnStop;
15977
15992
  var recognitionRef = React.useRef(null);
15978
15993
  var finalTranscriptRef = React.useRef("");
15994
+ var timeoutRef = React.useRef(null);
15995
+ var isMountedRef = React.useRef(true);
15979
15996
  var _useState = React.useState(false),
15980
15997
  _useState2 = _slicedToArray(_useState, 2),
15981
15998
  _isListening = _useState2[0],
@@ -15984,34 +16001,48 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
15984
16001
  _useState4 = _slicedToArray(_useState3, 2),
15985
16002
  _isSupported = _useState4[0],
15986
16003
  setIsSupported = _useState4[1];
16004
+ var _useState5 = React.useState(null),
16005
+ _useState6 = _slicedToArray(_useState5, 2),
16006
+ error = _useState6[0],
16007
+ setError = _useState6[1];
16008
+
16009
+ // Check browser support
15987
16010
  React.useEffect(function () {
15988
- if (!("webkitSpeechRecognition" in window) && !("SpeechRecognition" in window)) {
15989
- setIsSupported(false);
15990
- } else {
15991
- setIsSupported(true);
16011
+ var supported = "webkitSpeechRecognition" in window || "SpeechRecognition" in window;
16012
+ setIsSupported(supported);
16013
+ if (!supported) {
16014
+ var err = new Error("Speech recognition not supported in this browser");
16015
+ setError(err);
16016
+ onError(err);
15992
16017
  }
15993
- }, []);
15994
- React.useEffect(function () {
15995
- if (autoStart && _isSupported) {
15996
- startListening();
16018
+ }, [onError]);
16019
+
16020
+ // Clear timeout helper
16021
+ var clearInactivityTimeout = React.useCallback(function () {
16022
+ if (timeoutRef.current) {
16023
+ clearTimeout(timeoutRef.current);
16024
+ timeoutRef.current = null;
15997
16025
  }
15998
- return function () {
15999
- if (recognitionRef.current) {
16000
- try {
16001
- recognitionRef.current.onresult = null;
16002
- recognitionRef.current.onerror = null;
16003
- recognitionRef.current.onend = null;
16004
- recognitionRef.current.onstart = null;
16005
- recognitionRef.current.stop();
16006
- } catch (e) {}
16026
+ }, []);
16027
+
16028
+ // Reset inactivity timeout
16029
+ var resetInactivityTimeout = React.useCallback(function () {
16030
+ if (!timeout) return;
16031
+ clearInactivityTimeout();
16032
+ timeoutRef.current = setTimeout(function () {
16033
+ if (recognitionRef.current && _isListening) {
16034
+ stopListening();
16007
16035
  }
16008
- };
16009
- }, [autoStart, _isSupported]);
16010
- function initializeRecognition() {
16036
+ }, timeout);
16037
+ }, [timeout, _isListening]);
16038
+
16039
+ // Initialize recognition
16040
+ var initializeRecognition = React.useCallback(function () {
16011
16041
  if (recognitionRef.current) return recognitionRef.current;
16012
16042
  var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
16013
16043
  if (!SpeechRecognition) {
16014
16044
  var err = new Error("SpeechRecognition API not available");
16045
+ setError(err);
16015
16046
  onError(err);
16016
16047
  return null;
16017
16048
  }
@@ -16019,12 +16050,21 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
16019
16050
  recognition.continuous = !!continuous;
16020
16051
  recognition.interimResults = !!interimResults;
16021
16052
  recognition.lang = lang;
16053
+ recognition.maxAlternatives = maxAlternatives;
16054
+ if (grammars) {
16055
+ recognition.grammars = grammars;
16056
+ }
16022
16057
  recognition.onstart = function () {
16058
+ if (!isMountedRef.current) return;
16023
16059
  finalTranscriptRef.current = finalTranscriptRef.current || "";
16024
16060
  setIsListening(true);
16061
+ setError(null);
16062
+ resetInactivityTimeout();
16025
16063
  onStart();
16026
16064
  };
16027
16065
  recognition.onresult = function (event) {
16066
+ if (!isMountedRef.current) return;
16067
+ resetInactivityTimeout();
16028
16068
  var interim = "";
16029
16069
  var finalPart = "";
16030
16070
  for (var i = event.resultIndex; i < event.results.length; i++) {
@@ -16044,21 +16084,48 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
16044
16084
  }
16045
16085
  };
16046
16086
  recognition.onerror = function (event) {
16047
- var err = event && event.error ? new Error(event.error) : new Error("Speech recognition error");
16048
- onError(err);
16087
+ if (!isMountedRef.current) return;
16088
+ clearInactivityTimeout();
16089
+ var errorMessage = (event === null || event === void 0 ? void 0 : event.error) || "Speech recognition error";
16090
+ var err = new Error(errorMessage);
16091
+ setError(err);
16049
16092
  setIsListening(false);
16093
+ onError(err);
16094
+
16095
+ // Handle specific errors
16096
+ if (errorMessage === "not-allowed" || errorMessage === "service-not-allowed") {
16097
+ console.warn("Microphone permission denied");
16098
+ } else if (errorMessage === "no-speech") {
16099
+ console.warn("No speech detected");
16100
+ } else if (errorMessage === "aborted") {
16101
+ console.warn("Speech recognition aborted");
16102
+ }
16050
16103
  };
16051
16104
  recognition.onend = function () {
16105
+ if (!isMountedRef.current) return;
16106
+ clearInactivityTimeout();
16052
16107
  setIsListening(false);
16108
+ var finalText = (finalTranscriptRef.current || "").trim();
16109
+ onSpeechComplete(finalText);
16053
16110
  onStop();
16054
- onSpeechComplete((finalTranscriptRef.current || "").trim());
16111
+ if (clearOnStop) {
16112
+ finalTranscriptRef.current = "";
16113
+ }
16055
16114
  };
16056
16115
  recognitionRef.current = recognition;
16057
16116
  return recognition;
16058
- }
16059
- function startListening() {
16117
+ }, [continuous, interimResults, lang, maxAlternatives, grammars, onStart, onSpeaking, onSpeechComplete, onError, onStop, clearOnStop, resetInactivityTimeout, clearInactivityTimeout]);
16118
+
16119
+ // Start listening
16120
+ var startListening = React.useCallback(function () {
16060
16121
  if (!_isSupported) {
16061
- onError(new Error("Speech recognition not supported in this browser"));
16122
+ var err = new Error("Speech recognition not supported in this browser");
16123
+ setError(err);
16124
+ onError(err);
16125
+ return;
16126
+ }
16127
+ if (_isListening) {
16128
+ console.warn("Already listening");
16062
16129
  return;
16063
16130
  }
16064
16131
  try {
@@ -16066,24 +16133,68 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
16066
16133
  if (!rec) return;
16067
16134
  rec.start();
16068
16135
  } catch (err) {
16136
+ var _err$message;
16137
+ // Handle "already started" error
16138
+ if ((_err$message = err.message) !== null && _err$message !== void 0 && _err$message.includes("already started")) {
16139
+ console.warn("Recognition already in progress");
16140
+ return;
16141
+ }
16142
+ setError(err);
16069
16143
  onError(err);
16070
16144
  }
16071
- }
16072
- function stopListening() {
16145
+ }, [_isSupported, _isListening, initializeRecognition, onError]);
16146
+
16147
+ // Stop listening
16148
+ var stopListening = React.useCallback(function () {
16073
16149
  if (recognitionRef.current) {
16074
16150
  try {
16151
+ clearInactivityTimeout();
16075
16152
  recognitionRef.current.stop();
16076
- } catch (e) {}
16153
+ } catch (err) {
16154
+ console.error("Error stopping recognition:", err);
16155
+ }
16077
16156
  }
16078
- }
16079
- function toggleListening() {
16157
+ }, [clearInactivityTimeout]);
16158
+
16159
+ // Toggle listening
16160
+ var toggleListening = React.useCallback(function () {
16080
16161
  if (disabled) return;
16081
16162
  if (_isListening) {
16082
16163
  stopListening();
16083
16164
  } else {
16084
16165
  startListening();
16085
16166
  }
16086
- }
16167
+ }, [disabled, _isListening, startListening, stopListening]);
16168
+
16169
+ // Auto-start effect
16170
+ React.useEffect(function () {
16171
+ if (autoStart && _isSupported && !disabled) {
16172
+ startListening();
16173
+ }
16174
+ }, [autoStart, _isSupported, disabled, startListening]);
16175
+
16176
+ // Cleanup on unmount
16177
+ React.useEffect(function () {
16178
+ isMountedRef.current = true;
16179
+ return function () {
16180
+ isMountedRef.current = false;
16181
+ clearInactivityTimeout();
16182
+ if (recognitionRef.current) {
16183
+ try {
16184
+ recognitionRef.current.onresult = null;
16185
+ recognitionRef.current.onerror = null;
16186
+ recognitionRef.current.onend = null;
16187
+ recognitionRef.current.onstart = null;
16188
+ recognitionRef.current.stop();
16189
+ } catch (err) {
16190
+ console.error("Cleanup error:", err);
16191
+ }
16192
+ recognitionRef.current = null;
16193
+ }
16194
+ };
16195
+ }, [clearInactivityTimeout]);
16196
+
16197
+ // Imperative handle
16087
16198
  React.useImperativeHandle(ref, function () {
16088
16199
  return {
16089
16200
  start: startListening,
@@ -16100,26 +16211,39 @@ var SpeechToText = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
16100
16211
  },
16101
16212
  clearTranscript: function clearTranscript() {
16102
16213
  finalTranscriptRef.current = "";
16214
+ },
16215
+ getError: function getError() {
16216
+ return error;
16103
16217
  }
16104
16218
  };
16105
- }, [_isListening, _isSupported]);
16219
+ }, [_isListening, _isSupported, error, startListening, stopListening, toggleListening]);
16220
+
16221
+ // Custom button renderer
16106
16222
  if (renderButton && typeof renderButton === "function") {
16107
16223
  return renderButton({
16108
16224
  isListening: _isListening,
16109
16225
  isSupported: _isSupported,
16226
+ error: error,
16110
16227
  start: startListening,
16111
16228
  stop: stopListening,
16112
16229
  toggle: toggleListening,
16113
- disabled: disabled
16230
+ disabled: disabled || !_isSupported
16114
16231
  });
16115
16232
  }
16233
+
16234
+ // Default button
16116
16235
  return /*#__PURE__*/React.createElement("button", {
16117
16236
  type: "button",
16118
16237
  "aria-pressed": _isListening,
16238
+ "aria-label": _isListening ? "Stop listening" : "Start listening",
16119
16239
  onClick: toggleListening,
16120
- disabled: disabled || !_isSupported
16121
- }, _isListening ? "Stop" : "Start");
16240
+ disabled: disabled || !_isSupported,
16241
+ style: {
16242
+ cursor: disabled || !_isSupported ? "not-allowed" : "pointer"
16243
+ }
16244
+ }, _isListening ? "🎤 Stop" : "🎤 Start");
16122
16245
  });
16246
+ SpeechToText.displayName = "SpeechToText";
16123
16247
 
16124
16248
  var TextToSpeech = function TextToSpeech(_ref) {
16125
16249
  var _ref$text = _ref.text,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreamtree-org/twreact-ui",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "A comprehensive React + Tailwind components library for building modern web apps",
5
5
  "author": {
6
6
  "name": "Partha Preetham Krishna",