flikkui 0.2.0-beta.2 → 0.2.0-beta.4
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/components/ai/PromptInput/PromptInput.js +23 -15
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.d.ts +27 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.js +62 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.d.ts +10 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +12 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.types.d.ts +53 -0
- package/dist/components/ai/PromptSuggestions/index.d.ts +4 -2
- package/dist/components/ai/index.d.ts +2 -12
- package/dist/components/charts/ActivityRings/ActivityRings.js +70 -58
- package/dist/components/charts/ActivityRings/ActivityRings.theme.js +0 -1
- package/dist/components/charts/ActivityRings/ActivityRings.types.d.ts +17 -0
- package/dist/components/charts/BarChart/BarChart.js +8 -4
- package/dist/components/charts/BarChart/BarChart.types.d.ts +14 -0
- package/dist/components/charts/DonutChart/DonutChart.js +11 -8
- package/dist/components/charts/DonutChart/DonutChart.theme.d.ts +3 -0
- package/dist/components/charts/DonutChart/DonutChart.theme.js +5 -4
- package/dist/components/charts/DonutChart/donut-utils.d.ts +5 -0
- package/dist/components/charts/DonutChart/donut-utils.js +26 -1
- package/dist/components/charts/Heatmap/Heatmap.theme.js +2 -2
- package/dist/components/charts/shared/ChartAxis/XAxis.d.ts +2 -2
- package/dist/components/charts/shared/ChartAxis/XAxis.js +4 -4
- package/dist/components/charts/shared/ChartAxis/YAxis.d.ts +2 -2
- package/dist/components/charts/shared/ChartAxis/YAxis.js +8 -7
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +1 -1
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +2 -2
- package/dist/components/charts/theme/chart.theme.d.ts +1 -1
- package/dist/components/charts/theme/chart.theme.js +39 -39
- package/dist/components/core/Accordion/Accordion.d.ts +1 -1
- package/dist/components/core/Accordion/Accordion.js +2 -2
- package/dist/components/core/Accordion/Accordion.types.d.ts +8 -0
- package/dist/components/core/Badge/Badge.js +11 -15
- package/dist/components/core/Badge/Badge.theme.js +7 -21
- package/dist/components/core/Badge/Badge.types.d.ts +9 -1
- package/dist/components/core/Button/Button.js +2 -2
- package/dist/components/core/Button/Button.theme.js +1 -1
- package/dist/components/core/Button/Button.types.d.ts +8 -0
- package/dist/components/core/Card/Card.js +8 -2
- package/dist/components/core/Card/Card.theme.js +1 -1
- package/dist/components/core/Card/Card.types.d.ts +24 -1
- package/dist/components/core/Drawer/Drawer.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.js +10 -40
- package/dist/components/core/Drawer/Drawer.theme.js +2 -1
- package/dist/components/core/Drawer/Drawer.types.d.ts +8 -0
- package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/core/Dropdown/Dropdown.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.types.d.ts +8 -0
- package/dist/components/core/Metric/Metric.d.ts +1 -1
- package/dist/components/core/Metric/Metric.js +9 -5
- package/dist/components/core/Metric/Metric.theme.d.ts +1 -1
- package/dist/components/core/Metric/Metric.theme.js +38 -28
- package/dist/components/core/Metric/Metric.types.d.ts +27 -8
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +17 -40
- package/dist/components/core/Modal/Modal.theme.js +8 -3
- package/dist/components/core/Modal/Modal.types.d.ts +18 -0
- package/dist/components/core/Modal/index.d.ts +1 -1
- package/dist/components/core/Notification/Notification.js +2 -0
- package/dist/components/core/Pill/Pill.d.ts +6 -11
- package/dist/components/core/Pill/Pill.theme.d.ts +2 -2
- package/dist/components/core/Pill/Pill.types.d.ts +9 -22
- package/dist/components/core/Pill/index.d.ts +1 -1
- package/dist/components/core/Popover/Popover.d.ts +1 -1
- package/dist/components/core/Popover/Popover.js +2 -2
- package/dist/components/core/Popover/Popover.types.d.ts +8 -0
- package/dist/components/core/Progress/Progress.d.ts +28 -0
- package/dist/components/core/Progress/Progress.js +114 -0
- package/dist/components/core/Progress/Progress.theme.d.ts +5 -0
- package/dist/components/core/Progress/Progress.theme.js +33 -0
- package/dist/components/core/Progress/Progress.types.d.ts +92 -0
- package/dist/components/core/Progress/index.d.ts +2 -0
- package/dist/components/core/Tabs/Tabs.js +2 -2
- package/dist/components/core/Tabs/Tabs.types.d.ts +8 -0
- package/dist/components/core/Tag/Tag.animations.d.ts +3 -0
- package/dist/components/core/Tag/Tag.animations.js +31 -0
- package/dist/components/core/Tag/Tag.d.ts +14 -0
- package/dist/components/core/Tag/Tag.js +45 -0
- package/dist/components/core/Tag/Tag.theme.d.ts +2 -0
- package/dist/components/core/Tag/Tag.theme.js +21 -0
- package/dist/components/core/Tag/Tag.types.d.ts +40 -0
- package/dist/components/core/Tag/index.d.ts +3 -0
- package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.js +3 -3
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/Tooltip/Tooltip.types.d.ts +17 -0
- package/dist/components/core/index.d.ts +2 -1
- package/dist/components/core/index.js +3 -2
- package/dist/components/effects/CustomCursor/CustomCursor.d.ts +0 -13
- package/dist/components/effects/CustomCursor/CustomCursor.js +26 -2
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +12 -1
- package/dist/components/effects/CustomCursor/CustomCursor.types.d.ts +14 -1
- package/dist/components/forms/Combobox/Combobox.d.ts +25 -0
- package/dist/components/forms/Combobox/Combobox.js +412 -0
- package/dist/components/forms/Combobox/Combobox.theme.d.ts +6 -0
- package/dist/components/forms/Combobox/Combobox.theme.js +60 -0
- package/dist/components/forms/Combobox/Combobox.types.d.ts +111 -0
- package/dist/components/forms/Combobox/index.d.ts +3 -0
- package/dist/components/forms/FileUpload/FileUpload.js +2 -0
- package/dist/components/forms/Input/Input.js +25 -28
- package/dist/components/forms/Input/inputMasks.d.ts +15 -0
- package/dist/components/forms/Input/inputMasks.js +72 -1
- package/dist/components/forms/InputTag/InputTag.d.ts +40 -0
- package/dist/components/forms/InputTag/InputTag.js +491 -0
- package/dist/components/forms/InputTag/InputTag.theme.d.ts +2 -0
- package/dist/components/forms/InputTag/InputTag.theme.js +16 -0
- package/dist/components/forms/InputTag/InputTag.types.d.ts +107 -0
- package/dist/components/forms/InputTag/index.d.ts +3 -0
- package/dist/components/forms/Select/Select.d.ts +101 -2
- package/dist/components/forms/Select/Select.js +128 -132
- package/dist/components/forms/Select/Select.theme.js +10 -14
- package/dist/components/forms/Select/Select.types.d.ts +6 -2
- package/dist/components/forms/Select/index.d.ts +7 -4
- package/dist/components/forms/Select/useSelectState.d.ts +66 -0
- package/dist/components/forms/Select/useSelectState.js +134 -0
- package/dist/components/forms/SelectExpand/SelectExpand.animations.d.ts +20 -0
- package/dist/components/forms/SelectExpand/SelectExpand.animations.js +74 -0
- package/dist/components/forms/SelectExpand/SelectExpand.d.ts +9 -0
- package/dist/components/forms/SelectExpand/SelectExpand.js +223 -0
- package/dist/components/forms/SelectExpand/SelectExpand.theme.d.ts +5 -0
- package/dist/components/forms/SelectExpand/SelectExpand.theme.js +74 -0
- package/dist/components/forms/SelectExpand/SelectExpand.types.d.ts +126 -0
- package/dist/components/forms/SelectExpand/index.d.ts +4 -0
- package/dist/components/forms/Switch/Switch.js +3 -3
- package/dist/components/forms/Switch/Switch.theme.d.ts +1 -1
- package/dist/components/forms/Switch/Switch.theme.js +2 -2
- package/dist/components/forms/TimePicker/TimePicker.animations.d.ts +0 -46
- package/dist/components/forms/TimePicker/TimePicker.d.ts +15 -6
- package/dist/components/forms/TimePicker/TimePicker.js +285 -124
- package/dist/components/forms/TimePicker/TimePicker.theme.d.ts +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +39 -22
- package/dist/components/forms/TimePicker/TimePicker.types.d.ts +88 -34
- package/dist/components/forms/TimePicker/TimePickerContent.d.ts +7 -10
- package/dist/components/forms/TimePicker/TimePickerContent.js +149 -16
- package/dist/components/forms/TimePicker/TimePickerTrigger.d.ts +3 -3
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +22 -19
- package/dist/components/forms/TimePicker/WheelColumn.d.ts +14 -0
- package/dist/components/forms/TimePicker/WheelColumn.js +90 -0
- package/dist/components/forms/TimePicker/index.d.ts +4 -1
- package/dist/components/forms/TimePicker/useWheelPicker.d.ts +37 -0
- package/dist/components/forms/TimePicker/useWheelPicker.js +138 -0
- package/dist/components/forms/forms.theme.d.ts +14 -0
- package/dist/components/forms/forms.theme.js +31 -0
- package/dist/components/forms/index.d.ts +9 -3
- package/dist/components/forms/index.js +73 -2
- package/dist/hooks/index.d.ts +0 -4
- package/dist/icons/Icon.d.ts +7 -0
- package/dist/icons/Icon.js +6 -2
- package/dist/index.js +12 -16
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/optimisticErrors.js +1 -70
- package/package.json +1 -1
- package/dist/components/ai/EditingIndicator/EditingIndicator.animations.d.ts +0 -31
- package/dist/components/ai/EditingIndicator/EditingIndicator.animations.js +0 -115
- package/dist/components/ai/EditingIndicator/EditingIndicator.d.ts +0 -35
- package/dist/components/ai/EditingIndicator/EditingIndicator.js +0 -94
- package/dist/components/ai/EditingIndicator/EditingIndicator.theme.d.ts +0 -2
- package/dist/components/ai/EditingIndicator/EditingIndicator.theme.js +0 -13
- package/dist/components/ai/EditingIndicator/EditingIndicator.types.d.ts +0 -54
- package/dist/components/ai/EditingIndicator/index.d.ts +0 -9
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.d.ts +0 -3
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.js +0 -126
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.d.ts +0 -2
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.js +0 -8
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.types.d.ts +0 -45
- package/dist/components/ai/GenerativeRenderer/index.d.ts +0 -3
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.d.ts +0 -17
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.js +0 -56
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.d.ts +0 -38
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.js +0 -110
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.d.ts +0 -2
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.js +0 -13
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.types.d.ts +0 -53
- package/dist/components/ai/PresenceIndicator/index.d.ts +0 -8
- package/dist/components/ai/PresenceProvider/PresenceContext.d.ts +0 -24
- package/dist/components/ai/PresenceProvider/PresenceContext.js +0 -34
- package/dist/components/ai/PresenceProvider/PresenceProvider.d.ts +0 -32
- package/dist/components/ai/PresenceProvider/PresenceProvider.js +0 -321
- package/dist/components/ai/PresenceProvider/PresenceProvider.types.d.ts +0 -140
- package/dist/components/ai/PresenceProvider/adapters/MockAdapter.d.ts +0 -102
- package/dist/components/ai/PresenceProvider/adapters/MockAdapter.js +0 -331
- package/dist/components/ai/PresenceProvider/adapters/PresenceAdapter.d.ts +0 -93
- package/dist/components/ai/PresenceProvider/adapters/SupabaseAdapter.d.ts +0 -134
- package/dist/components/ai/PresenceProvider/adapters/WebSocketAdapter.d.ts +0 -149
- package/dist/components/ai/PresenceProvider/adapters/index.d.ts +0 -11
- package/dist/components/ai/PresenceProvider/index.d.ts +0 -10
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.d.ts +0 -27
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.js +0 -61
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.types.d.ts +0 -65
- package/dist/components/ai/VersionSlider/VersionSlider.d.ts +0 -3
- package/dist/components/ai/VersionSlider/VersionSlider.js +0 -97
- package/dist/components/ai/VersionSlider/VersionSlider.theme.d.ts +0 -2
- package/dist/components/ai/VersionSlider/VersionSlider.theme.js +0 -18
- package/dist/components/ai/VersionSlider/VersionSlider.types.d.ts +0 -77
- package/dist/components/ai/VersionSlider/index.d.ts +0 -3
- package/dist/components/core/Pill/Pill.animations.js +0 -25
- package/dist/components/core/Pill/Pill.js +0 -145
- package/dist/components/core/Pill/Pill.theme.js +0 -65
- package/dist/components/core/RetryBoundary/RetryBoundary.d.ts +0 -35
- package/dist/components/core/RetryBoundary/RetryBoundary.js +0 -154
- package/dist/components/core/RetryBoundary/RetryBoundary.theme.d.ts +0 -2
- package/dist/components/core/RetryBoundary/RetryBoundary.theme.js +0 -7
- package/dist/components/core/RetryBoundary/RetryBoundary.types.d.ts +0 -51
- package/dist/components/core/RetryBoundary/index.d.ts +0 -3
- package/dist/components/forms/OptimisticForm/OptimisticForm.d.ts +0 -33
- package/dist/components/forms/OptimisticForm/OptimisticForm.js +0 -87
- package/dist/components/forms/OptimisticForm/OptimisticForm.theme.d.ts +0 -2
- package/dist/components/forms/OptimisticForm/OptimisticForm.theme.js +0 -8
- package/dist/components/forms/OptimisticForm/OptimisticForm.types.d.ts +0 -74
- package/dist/components/forms/OptimisticForm/index.d.ts +0 -3
- package/dist/hooks/useOptimisticMutation.d.ts +0 -109
- package/dist/hooks/useOptimisticMutation.js +0 -171
- package/dist/hooks/usePresence.d.ts +0 -88
- package/dist/utils/presenceUtils.d.ts +0 -66
- package/dist/utils/presenceUtils.js +0 -107
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import React__default, { Component, useState, useEffect } from 'react';
|
|
2
|
-
import { XMarkIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
|
|
3
|
-
import { Button } from '../Button/Button.js';
|
|
4
|
-
import { shouldRetry, calculateRetryDelay } from '../../../utils/retryUtils.js';
|
|
5
|
-
import { normalizeError } from '../../../utils/streamingErrors.js';
|
|
6
|
-
import { retryBoundaryTheme } from './RetryBoundary.theme.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* RetryBoundary Component
|
|
10
|
-
* Error boundary with exponential backoff retry
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* Default fallback UI component
|
|
14
|
-
*/
|
|
15
|
-
const DefaultFallback = ({ error, attempt, maxAttempts, retryIn, retry, reset, }) => {
|
|
16
|
-
const theme = retryBoundaryTheme;
|
|
17
|
-
const hasMoreRetries = attempt < maxAttempts;
|
|
18
|
-
return (React__default.createElement("div", { className: theme.container },
|
|
19
|
-
React__default.createElement("div", { className: "flex flex-col items-start gap-2 text-[var(--color-danger)]" },
|
|
20
|
-
React__default.createElement("div", { className: "text-2xl rounded-full p-3 mb-3 w-fit glass-effect shadow-xl shadow-black/5" },
|
|
21
|
-
React__default.createElement(XMarkIcon, { className: "size-5" })),
|
|
22
|
-
React__default.createElement("span", { className: "text-base font-semibold" }, "Something went wrong")),
|
|
23
|
-
React__default.createElement("p", { className: theme.errorMessage }, error.message),
|
|
24
|
-
retryIn > 0 && hasMoreRetries && (React__default.createElement("p", { className: theme.countdown },
|
|
25
|
-
"Retrying in ",
|
|
26
|
-
retryIn,
|
|
27
|
-
"s... (Attempt ",
|
|
28
|
-
attempt + 1,
|
|
29
|
-
" of ",
|
|
30
|
-
maxAttempts,
|
|
31
|
-
")")),
|
|
32
|
-
React__default.createElement("div", { className: "flex items-center gap-2 mt-6" },
|
|
33
|
-
hasMoreRetries ? (React__default.createElement(Button, { onClick: retry, size: "sm", variant: "filled", color: "dark" },
|
|
34
|
-
React__default.createElement(ArrowPathIcon, { className: "size-4" }),
|
|
35
|
-
"Retry Now")) : (React__default.createElement("p", { className: "text-xs text-[var(--color-text-muted)]" }, "Max retries reached")),
|
|
36
|
-
React__default.createElement(Button, { onClick: reset, size: "sm", color: "neutral" }, "Dismiss"))));
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Wrapper component to handle retry countdown and state
|
|
40
|
-
*/
|
|
41
|
-
const RetryFallbackWrapper = ({ error, attempt, maxAttempts, retryDelay, onRetry, onReset, fallback, className, }) => {
|
|
42
|
-
const [countdown, setCountdown] = useState(Math.ceil(retryDelay / 1000));
|
|
43
|
-
const hasMoreRetries = attempt < maxAttempts;
|
|
44
|
-
// Countdown timer
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
if (!hasMoreRetries || retryDelay === 0)
|
|
47
|
-
return;
|
|
48
|
-
setCountdown(Math.ceil(retryDelay / 1000));
|
|
49
|
-
const interval = setInterval(() => {
|
|
50
|
-
setCountdown((prev) => {
|
|
51
|
-
if (prev <= 1) {
|
|
52
|
-
clearInterval(interval);
|
|
53
|
-
onRetry();
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
return prev - 1;
|
|
57
|
-
});
|
|
58
|
-
}, 1000);
|
|
59
|
-
return () => clearInterval(interval);
|
|
60
|
-
}, [retryDelay, hasMoreRetries, onRetry]);
|
|
61
|
-
const fallbackProps = {
|
|
62
|
-
error,
|
|
63
|
-
attempt,
|
|
64
|
-
maxAttempts,
|
|
65
|
-
retryIn: countdown,
|
|
66
|
-
retry: onRetry,
|
|
67
|
-
reset: onReset,
|
|
68
|
-
};
|
|
69
|
-
// Custom fallback
|
|
70
|
-
if (fallback) {
|
|
71
|
-
if (typeof fallback === "function") {
|
|
72
|
-
return React__default.createElement("div", { className: className }, fallback(fallbackProps));
|
|
73
|
-
}
|
|
74
|
-
return React__default.createElement("div", { className: className }, fallback);
|
|
75
|
-
}
|
|
76
|
-
// Default fallback
|
|
77
|
-
return (React__default.createElement("div", { className: className },
|
|
78
|
-
React__default.createElement(DefaultFallback, { ...fallbackProps })));
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* RetryBoundary - Error boundary with exponential backoff retry
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* <RetryBoundary
|
|
85
|
-
* retry={{ maxAttempts: 3, initialDelay: 1000 }}
|
|
86
|
-
* onMaxRetriesReached={(error) => logError(error)}
|
|
87
|
-
* >
|
|
88
|
-
* <AsyncComponent />
|
|
89
|
-
* </RetryBoundary>
|
|
90
|
-
*/
|
|
91
|
-
class RetryBoundary extends Component {
|
|
92
|
-
constructor(props) {
|
|
93
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
94
|
-
super(props);
|
|
95
|
-
this.handleRetry = () => {
|
|
96
|
-
const { onRetry } = this.props;
|
|
97
|
-
const newAttempt = this.state.attempt + 1;
|
|
98
|
-
onRetry === null || onRetry === void 0 ? void 0 : onRetry(newAttempt);
|
|
99
|
-
this.setState({
|
|
100
|
-
error: null,
|
|
101
|
-
attempt: newAttempt,
|
|
102
|
-
retryDelay: 0,
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
this.handleReset = () => {
|
|
106
|
-
this.setState({
|
|
107
|
-
error: null,
|
|
108
|
-
attempt: 0,
|
|
109
|
-
retryDelay: 0,
|
|
110
|
-
});
|
|
111
|
-
};
|
|
112
|
-
this.state = {
|
|
113
|
-
error: null,
|
|
114
|
-
attempt: 0,
|
|
115
|
-
retryDelay: 0,
|
|
116
|
-
};
|
|
117
|
-
this.retryConfig = {
|
|
118
|
-
maxAttempts: (_b = (_a = props.retry) === null || _a === void 0 ? void 0 : _a.maxAttempts) !== null && _b !== void 0 ? _b : 3,
|
|
119
|
-
initialDelay: (_d = (_c = props.retry) === null || _c === void 0 ? void 0 : _c.initialDelay) !== null && _d !== void 0 ? _d : 1000,
|
|
120
|
-
backoffMultiplier: (_f = (_e = props.retry) === null || _e === void 0 ? void 0 : _e.backoffMultiplier) !== null && _f !== void 0 ? _f : 2,
|
|
121
|
-
maxDelay: (_h = (_g = props.retry) === null || _g === void 0 ? void 0 : _g.maxDelay) !== null && _h !== void 0 ? _h : 10000,
|
|
122
|
-
shouldRetry: (_j = props.retry) === null || _j === void 0 ? void 0 : _j.shouldRetry,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
static getDerivedStateFromError(error) {
|
|
126
|
-
return { error };
|
|
127
|
-
}
|
|
128
|
-
componentDidCatch(error, errorInfo) {
|
|
129
|
-
const { attempt } = this.state;
|
|
130
|
-
const { onError, onMaxRetriesReached } = this.props;
|
|
131
|
-
// Normalize error for retry check
|
|
132
|
-
const streamingError = normalizeError(error);
|
|
133
|
-
const canRetry = shouldRetry(streamingError, attempt, this.retryConfig);
|
|
134
|
-
onError === null || onError === void 0 ? void 0 : onError(error, attempt);
|
|
135
|
-
if (canRetry) {
|
|
136
|
-
const delay = calculateRetryDelay(attempt, this.retryConfig);
|
|
137
|
-
this.setState({ retryDelay: delay });
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
onMaxRetriesReached === null || onMaxRetriesReached === void 0 ? void 0 : onMaxRetriesReached(error);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
render() {
|
|
144
|
-
var _a;
|
|
145
|
-
const { children, fallback, className } = this.props;
|
|
146
|
-
const { error, attempt, retryDelay } = this.state;
|
|
147
|
-
if (error) {
|
|
148
|
-
return (React__default.createElement(RetryFallbackWrapper, { error: error, attempt: attempt, maxAttempts: (_a = this.retryConfig.maxAttempts) !== null && _a !== void 0 ? _a : 3, retryDelay: retryDelay, onRetry: this.handleRetry, onReset: this.handleReset, fallback: fallback, className: className }));
|
|
149
|
-
}
|
|
150
|
-
return children;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export { RetryBoundary };
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
const retryBoundaryTheme = {
|
|
2
|
-
container: "flex flex-col items-start justify-center p-6 rounded-[var(--form-rounded)] bg-[var(--color-danger-50)]/50 border border-[var(--color-danger-100)]",
|
|
3
|
-
errorMessage: "text-sm text-[var(--color-text-secondary)] text-center max-w-md mt-1",
|
|
4
|
-
countdown: "text-xs text-[var(--color-text-muted)] tabular-nums mt-3",
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export { retryBoundaryTheme };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { RetryConfig } from "../../../utils/retryUtils";
|
|
2
|
-
/**
|
|
3
|
-
* Props for custom retry fallback render function
|
|
4
|
-
*/
|
|
5
|
-
export interface RetryFallbackProps {
|
|
6
|
-
/** The error that was caught */
|
|
7
|
-
error: Error;
|
|
8
|
-
/** Current retry attempt (0-indexed) */
|
|
9
|
-
attempt: number;
|
|
10
|
-
/** Maximum retry attempts */
|
|
11
|
-
maxAttempts: number;
|
|
12
|
-
/** Seconds until auto-retry (0 if not auto-retrying) */
|
|
13
|
-
retryIn: number;
|
|
14
|
-
/** Manually trigger a retry */
|
|
15
|
-
retry: () => void;
|
|
16
|
-
/** Reset error state completely */
|
|
17
|
-
reset: () => void;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Props for RetryBoundary component
|
|
21
|
-
*/
|
|
22
|
-
export interface RetryBoundaryProps {
|
|
23
|
-
/** Content to render when no error */
|
|
24
|
-
children: React.ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* Custom fallback UI or render function
|
|
27
|
-
* If not provided, uses default retry UI
|
|
28
|
-
*/
|
|
29
|
-
fallback?: React.ReactNode | ((props: RetryFallbackProps) => React.ReactNode);
|
|
30
|
-
/** Retry configuration */
|
|
31
|
-
retry?: RetryConfig;
|
|
32
|
-
/** Called when an error is caught */
|
|
33
|
-
onError?: (error: Error, attempt: number) => void;
|
|
34
|
-
/** Called when a retry is triggered */
|
|
35
|
-
onRetry?: (attempt: number) => void;
|
|
36
|
-
/** Called when max retries is reached */
|
|
37
|
-
onMaxRetriesReached?: (error: Error) => void;
|
|
38
|
-
/** Additional class names */
|
|
39
|
-
className?: string;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Theme configuration for RetryBoundary
|
|
43
|
-
*/
|
|
44
|
-
export interface RetryBoundaryTheme {
|
|
45
|
-
/** Container styles */
|
|
46
|
-
container?: string;
|
|
47
|
-
/** Error message styles */
|
|
48
|
-
errorMessage?: string;
|
|
49
|
-
/** Retry countdown styles */
|
|
50
|
-
countdown?: string;
|
|
51
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OptimisticForm Component
|
|
3
|
-
* Form wrapper with optimistic updates and auto-rollback
|
|
4
|
-
*/
|
|
5
|
-
import React from "react";
|
|
6
|
-
import type { OptimisticFormProps } from "./OptimisticForm.types";
|
|
7
|
-
/**
|
|
8
|
-
* OptimisticForm - Form wrapper with optimistic updates and auto-rollback
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* // Basic usage
|
|
12
|
-
* <OptimisticForm
|
|
13
|
-
* onSubmit={async (data) => api.createUser(data)}
|
|
14
|
-
* onOptimisticUpdate={(data) => addUserToList({ ...data, id: 'temp', isPending: true })}
|
|
15
|
-
* onSuccess={(response) => updateUserInList(response)}
|
|
16
|
-
* onError={() => removeUserFromList('temp')}
|
|
17
|
-
* >
|
|
18
|
-
* <Input name="name" />
|
|
19
|
-
* <Button type="submit">Create User</Button>
|
|
20
|
-
* </OptimisticForm>
|
|
21
|
-
*
|
|
22
|
-
* // With render prop for dynamic UI
|
|
23
|
-
* <OptimisticForm onSubmit={handleSubmit}>
|
|
24
|
-
* {({ isPending, isError, error }) => (
|
|
25
|
-
* <>
|
|
26
|
-
* <Input name="email" disabled={isPending} />
|
|
27
|
-
* {isError && <Alert variant="error">{error?.message}</Alert>}
|
|
28
|
-
* <Button type="submit" loading={isPending}>Submit</Button>
|
|
29
|
-
* </>
|
|
30
|
-
* )}
|
|
31
|
-
* </OptimisticForm>
|
|
32
|
-
*/
|
|
33
|
-
export declare function OptimisticForm<TData, TFormData extends Record<string, unknown>>({ onSubmit, onOptimisticUpdate, onSuccess, onError, onRollback, retry, offlineQueue, resetOnSuccess, children, className, id, disabled, }: OptimisticFormProps<TData, TFormData>): React.ReactElement;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import React__default, { useRef, useCallback } from 'react';
|
|
2
|
-
import { cn } from '../../../utils/cn.js';
|
|
3
|
-
import { useOptimisticMutation } from '../../../hooks/useOptimisticMutation.js';
|
|
4
|
-
import { optimisticFormTheme } from './OptimisticForm.theme.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* OptimisticForm Component
|
|
8
|
-
* Form wrapper with optimistic updates and auto-rollback
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* OptimisticForm - Form wrapper with optimistic updates and auto-rollback
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* // Basic usage
|
|
15
|
-
* <OptimisticForm
|
|
16
|
-
* onSubmit={async (data) => api.createUser(data)}
|
|
17
|
-
* onOptimisticUpdate={(data) => addUserToList({ ...data, id: 'temp', isPending: true })}
|
|
18
|
-
* onSuccess={(response) => updateUserInList(response)}
|
|
19
|
-
* onError={() => removeUserFromList('temp')}
|
|
20
|
-
* >
|
|
21
|
-
* <Input name="name" />
|
|
22
|
-
* <Button type="submit">Create User</Button>
|
|
23
|
-
* </OptimisticForm>
|
|
24
|
-
*
|
|
25
|
-
* // With render prop for dynamic UI
|
|
26
|
-
* <OptimisticForm onSubmit={handleSubmit}>
|
|
27
|
-
* {({ isPending, isError, error }) => (
|
|
28
|
-
* <>
|
|
29
|
-
* <Input name="email" disabled={isPending} />
|
|
30
|
-
* {isError && <Alert variant="error">{error?.message}</Alert>}
|
|
31
|
-
* <Button type="submit" loading={isPending}>Submit</Button>
|
|
32
|
-
* </>
|
|
33
|
-
* )}
|
|
34
|
-
* </OptimisticForm>
|
|
35
|
-
*/
|
|
36
|
-
function OptimisticForm({ onSubmit, onOptimisticUpdate, onSuccess, onError, onRollback, retry, offlineQueue = false, resetOnSuccess = false, children, className, id, disabled = false, }) {
|
|
37
|
-
const theme = optimisticFormTheme;
|
|
38
|
-
const formRef = useRef(null);
|
|
39
|
-
// Use optimistic mutation hook
|
|
40
|
-
const { mutate, status, error, isOptimistic, isRolledBack, isQueued } = useOptimisticMutation(onSubmit, {
|
|
41
|
-
onMutate: (data) => data, // Pass form data as context
|
|
42
|
-
onOptimisticUpdate: onOptimisticUpdate
|
|
43
|
-
? (data, _context) => onOptimisticUpdate(data)
|
|
44
|
-
: undefined,
|
|
45
|
-
onSuccess: (response, formData, _context) => {
|
|
46
|
-
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(response, formData);
|
|
47
|
-
// Reset form if configured
|
|
48
|
-
if (resetOnSuccess && formRef.current) {
|
|
49
|
-
formRef.current.reset();
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
onError: (err, formData, _context) => {
|
|
53
|
-
onError === null || onError === void 0 ? void 0 : onError(err, formData);
|
|
54
|
-
onRollback === null || onRollback === void 0 ? void 0 : onRollback(formData);
|
|
55
|
-
},
|
|
56
|
-
retry,
|
|
57
|
-
offlineQueue,
|
|
58
|
-
});
|
|
59
|
-
// Handle form submission
|
|
60
|
-
const handleSubmit = useCallback((event) => {
|
|
61
|
-
event.preventDefault();
|
|
62
|
-
if (disabled)
|
|
63
|
-
return;
|
|
64
|
-
const formElement = event.currentTarget;
|
|
65
|
-
const formData = new FormData(formElement);
|
|
66
|
-
// Convert FormData to object
|
|
67
|
-
const data = Object.fromEntries(formData.entries());
|
|
68
|
-
mutate(data);
|
|
69
|
-
}, [mutate, disabled]);
|
|
70
|
-
// Create form state for render prop
|
|
71
|
-
const formState = {
|
|
72
|
-
status,
|
|
73
|
-
isPending: status === "pending",
|
|
74
|
-
isOptimistic,
|
|
75
|
-
isSuccess: status === "success",
|
|
76
|
-
isError: status === "error",
|
|
77
|
-
isRolledBack,
|
|
78
|
-
isQueued,
|
|
79
|
-
error,
|
|
80
|
-
submittedData: null, // We don't track this currently
|
|
81
|
-
};
|
|
82
|
-
// Determine children to render
|
|
83
|
-
const content = typeof children === "function" ? children(formState) : children;
|
|
84
|
-
return (React__default.createElement("form", { ref: formRef, id: id, onSubmit: handleSubmit, className: cn(theme.base, status === "pending" && theme.pending, status === "error" && theme.error, status === "success" && theme.success, className), "aria-busy": status === "pending", "aria-disabled": disabled }, content));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export { OptimisticForm };
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { RetryConfig } from "../../../utils/retryUtils";
|
|
2
|
-
import type { OptimisticError } from "../../../utils/optimisticErrors";
|
|
3
|
-
/**
|
|
4
|
-
* Form submission status
|
|
5
|
-
*/
|
|
6
|
-
export type OptimisticFormStatus = "idle" | "pending" | "success" | "error";
|
|
7
|
-
/**
|
|
8
|
-
* State passed to render prop children
|
|
9
|
-
*/
|
|
10
|
-
export interface OptimisticFormState<TFormData = unknown> {
|
|
11
|
-
/** Current form status */
|
|
12
|
-
status: OptimisticFormStatus;
|
|
13
|
-
/** True when form is submitting */
|
|
14
|
-
isPending: boolean;
|
|
15
|
-
/** True when showing optimistic state */
|
|
16
|
-
isOptimistic: boolean;
|
|
17
|
-
/** True when submission succeeded */
|
|
18
|
-
isSuccess: boolean;
|
|
19
|
-
/** True when submission failed */
|
|
20
|
-
isError: boolean;
|
|
21
|
-
/** True when rollback occurred */
|
|
22
|
-
isRolledBack: boolean;
|
|
23
|
-
/** True when queued for offline */
|
|
24
|
-
isQueued: boolean;
|
|
25
|
-
/** Error if submission failed */
|
|
26
|
-
error: OptimisticError | null;
|
|
27
|
-
/** Last submitted form data */
|
|
28
|
-
submittedData: TFormData | null;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Props for OptimisticForm component
|
|
32
|
-
*/
|
|
33
|
-
export interface OptimisticFormProps<TData, TFormData> {
|
|
34
|
-
/** Form submission handler - returns server response */
|
|
35
|
-
onSubmit: (data: TFormData) => Promise<TData>;
|
|
36
|
-
/** Called immediately to apply optimistic update */
|
|
37
|
-
onOptimisticUpdate?: (data: TFormData) => void;
|
|
38
|
-
/** Called on successful submission */
|
|
39
|
-
onSuccess?: (response: TData, formData: TFormData) => void;
|
|
40
|
-
/** Called when submission fails */
|
|
41
|
-
onError?: (error: OptimisticError, formData: TFormData) => void;
|
|
42
|
-
/** Called when rollback is executed */
|
|
43
|
-
onRollback?: (formData: TFormData) => void;
|
|
44
|
-
/** Retry configuration */
|
|
45
|
-
retry?: RetryConfig;
|
|
46
|
-
/** Queue submissions when offline */
|
|
47
|
-
offlineQueue?: boolean;
|
|
48
|
-
/** Reset form on successful submission */
|
|
49
|
-
resetOnSuccess?: boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Form content - can be static or render prop
|
|
52
|
-
* Render prop receives current form state
|
|
53
|
-
*/
|
|
54
|
-
children: React.ReactNode | ((state: OptimisticFormState<TFormData>) => React.ReactNode);
|
|
55
|
-
/** Additional class names for form element */
|
|
56
|
-
className?: string;
|
|
57
|
-
/** Form ID */
|
|
58
|
-
id?: string;
|
|
59
|
-
/** Whether the form is disabled */
|
|
60
|
-
disabled?: boolean;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Theme configuration for OptimisticForm
|
|
64
|
-
*/
|
|
65
|
-
export interface OptimisticFormTheme {
|
|
66
|
-
/** Base form styles */
|
|
67
|
-
base?: string;
|
|
68
|
-
/** Styles when submitting */
|
|
69
|
-
pending?: string;
|
|
70
|
-
/** Styles when error */
|
|
71
|
-
error?: string;
|
|
72
|
-
/** Styles when success */
|
|
73
|
-
success?: string;
|
|
74
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useOptimisticMutation Hook
|
|
3
|
-
* Provides instant UI updates with automatic rollback on error
|
|
4
|
-
*/
|
|
5
|
-
import { OptimisticError } from "../utils/optimisticErrors";
|
|
6
|
-
import { type RetryConfig } from "../utils/retryUtils";
|
|
7
|
-
import { type ActionQueue, type AddActionOptions } from "../utils/actionQueue";
|
|
8
|
-
/**
|
|
9
|
-
* Mutation state
|
|
10
|
-
*/
|
|
11
|
-
export type MutationStatus = "idle" | "pending" | "success" | "error";
|
|
12
|
-
/**
|
|
13
|
-
* Options for useOptimisticMutation hook
|
|
14
|
-
*/
|
|
15
|
-
export interface OptimisticMutationOptions<TData, TVariables, TContext = unknown> {
|
|
16
|
-
/**
|
|
17
|
-
* Called before mutation - return context for rollback
|
|
18
|
-
* Context is passed to onSuccess, onError, and onSettled
|
|
19
|
-
*/
|
|
20
|
-
onMutate?: (variables: TVariables) => TContext | Promise<TContext>;
|
|
21
|
-
/**
|
|
22
|
-
* Apply optimistic update immediately
|
|
23
|
-
* Called synchronously before the mutation starts
|
|
24
|
-
*/
|
|
25
|
-
onOptimisticUpdate?: (variables: TVariables, context: TContext) => void;
|
|
26
|
-
/**
|
|
27
|
-
* Called on success - replace optimistic data with real data
|
|
28
|
-
*/
|
|
29
|
-
onSuccess?: (data: TData, variables: TVariables, context: TContext) => void;
|
|
30
|
-
/**
|
|
31
|
-
* Called on error - rollback optimistic update
|
|
32
|
-
* Use context to restore previous state
|
|
33
|
-
*/
|
|
34
|
-
onError?: (error: OptimisticError, variables: TVariables, context: TContext) => void;
|
|
35
|
-
/**
|
|
36
|
-
* Called after success or error (cleanup)
|
|
37
|
-
*/
|
|
38
|
-
onSettled?: (data: TData | undefined, error: OptimisticError | null, variables: TVariables, context: TContext) => void;
|
|
39
|
-
/**
|
|
40
|
-
* Retry configuration for failed mutations
|
|
41
|
-
*/
|
|
42
|
-
retry?: RetryConfig;
|
|
43
|
-
/**
|
|
44
|
-
* Queue mutation when offline instead of failing immediately
|
|
45
|
-
*/
|
|
46
|
-
offlineQueue?: boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Custom action queue instance (defaults to global queue)
|
|
49
|
-
*/
|
|
50
|
-
actionQueue?: ActionQueue;
|
|
51
|
-
/**
|
|
52
|
-
* Options for queued action (label, description)
|
|
53
|
-
*/
|
|
54
|
-
queueOptions?: Omit<AddActionOptions, "maxRetries">;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Return value from useOptimisticMutation hook
|
|
58
|
-
*/
|
|
59
|
-
export interface OptimisticMutationReturn<TData, TVariables> {
|
|
60
|
-
/** Trigger the mutation */
|
|
61
|
-
mutate: (variables: TVariables) => void;
|
|
62
|
-
/** Trigger the mutation and return a Promise */
|
|
63
|
-
mutateAsync: (variables: TVariables) => Promise<TData>;
|
|
64
|
-
/** Response data from the last successful mutation */
|
|
65
|
-
data: TData | undefined;
|
|
66
|
-
/** Error from the last failed mutation */
|
|
67
|
-
error: OptimisticError | null;
|
|
68
|
-
/** Current mutation status */
|
|
69
|
-
status: MutationStatus;
|
|
70
|
-
/** True when no mutation is in progress or completed */
|
|
71
|
-
isIdle: boolean;
|
|
72
|
-
/** True when mutation is in progress */
|
|
73
|
-
isPending: boolean;
|
|
74
|
-
/** True when showing optimistic data (mutation in progress) */
|
|
75
|
-
isOptimistic: boolean;
|
|
76
|
-
/** True when mutation completed successfully */
|
|
77
|
-
isSuccess: boolean;
|
|
78
|
-
/** True when mutation failed */
|
|
79
|
-
isError: boolean;
|
|
80
|
-
/** True when error occurred and rollback was applied */
|
|
81
|
-
isRolledBack: boolean;
|
|
82
|
-
/** True when mutation was queued for offline processing */
|
|
83
|
-
isQueued: boolean;
|
|
84
|
-
/** Reset the mutation state */
|
|
85
|
-
reset: () => void;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Hook for optimistic UI mutations with automatic rollback
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* const { mutate, isOptimistic, isPending } = useOptimisticMutation(
|
|
92
|
-
* async (data) => api.createMessage(data),
|
|
93
|
-
* {
|
|
94
|
-
* onOptimisticUpdate: (newMessage) => {
|
|
95
|
-
* setMessages(prev => [...prev, { ...newMessage, id: 'temp-id', isPending: true }]);
|
|
96
|
-
* },
|
|
97
|
-
* onSuccess: (response) => {
|
|
98
|
-
* setMessages(prev => prev.map(m =>
|
|
99
|
-
* m.id === 'temp-id' ? { ...response, isPending: false } : m
|
|
100
|
-
* ));
|
|
101
|
-
* },
|
|
102
|
-
* onError: (error) => {
|
|
103
|
-
* setMessages(prev => prev.filter(m => m.id !== 'temp-id'));
|
|
104
|
-
* toast.error('Failed to send message');
|
|
105
|
-
* }
|
|
106
|
-
* }
|
|
107
|
-
* );
|
|
108
|
-
*/
|
|
109
|
-
export declare function useOptimisticMutation<TData, TVariables, TContext = unknown>(mutationFn: (variables: TVariables) => Promise<TData>, options?: OptimisticMutationOptions<TData, TVariables, TContext>): OptimisticMutationReturn<TData, TVariables>;
|