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,14 +1,13 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from "react";
|
|
2
2
|
/**
|
|
3
3
|
* TimePicker component props
|
|
4
|
-
* @property {string} value - The selected time value in "HH:mm"
|
|
4
|
+
* @property {string} value - The selected time value in "HH:mm" format
|
|
5
5
|
* @property {string} defaultValue - Default time value for uncontrolled mode
|
|
6
6
|
* @property {function} onChange - Callback fired when time value changes
|
|
7
7
|
* @property {TimeFormat} format - Display format: 12-hour or 24-hour
|
|
8
8
|
* @property {number} step - Step interval for minutes (1, 5, 10, 15, 30)
|
|
9
9
|
* @property {string} minTime - Minimum selectable time in "HH:mm" format
|
|
10
10
|
* @property {string} maxTime - Maximum selectable time in "HH:mm" format
|
|
11
|
-
* @property {boolean} showSeconds - Whether to show seconds selector
|
|
12
11
|
* @property {boolean} disabled - Whether the component is disabled
|
|
13
12
|
* @property {string} placeholder - Placeholder text for the input
|
|
14
13
|
* @property {TimePickerSize} size - Size variant of the component
|
|
@@ -19,8 +18,8 @@ import React from 'react';
|
|
|
19
18
|
* @property {React.ReactNode} iconStart - Icon to display at the start (left side)
|
|
20
19
|
* @property {React.ReactNode} iconEnd - Icon to display at the end (right side)
|
|
21
20
|
*/
|
|
22
|
-
export interface TimePickerProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>,
|
|
23
|
-
/** The selected time value in "HH:mm"
|
|
21
|
+
export interface TimePickerProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "onChange" | "value" | "defaultValue"> {
|
|
22
|
+
/** The selected time value in "HH:mm" format */
|
|
24
23
|
value?: string;
|
|
25
24
|
/** Default time value for uncontrolled mode */
|
|
26
25
|
defaultValue?: string;
|
|
@@ -34,8 +33,6 @@ export interface TimePickerProps extends Omit<React.InputHTMLAttributes<HTMLInpu
|
|
|
34
33
|
minTime?: string;
|
|
35
34
|
/** Maximum selectable time in "HH:mm" format */
|
|
36
35
|
maxTime?: string;
|
|
37
|
-
/** Whether to show seconds selector */
|
|
38
|
-
showSeconds?: boolean;
|
|
39
36
|
/** Whether the component is disabled */
|
|
40
37
|
disabled?: boolean;
|
|
41
38
|
/** Placeholder text for the input */
|
|
@@ -66,23 +63,23 @@ export interface TimePickerProps extends Omit<React.InputHTMLAttributes<HTMLInpu
|
|
|
66
63
|
/**
|
|
67
64
|
* Time display format options
|
|
68
65
|
*/
|
|
69
|
-
export type TimeFormat =
|
|
66
|
+
export type TimeFormat = "12h" | "24h";
|
|
70
67
|
/**
|
|
71
68
|
* Size variants for TimePicker
|
|
72
69
|
*/
|
|
73
|
-
export type TimePickerSize =
|
|
70
|
+
export type TimePickerSize = "sm" | "md" | "lg";
|
|
74
71
|
/**
|
|
75
72
|
* State variants for TimePicker
|
|
76
73
|
*/
|
|
77
|
-
export type TimePickerState =
|
|
74
|
+
export type TimePickerState = "default" | "disabled" | "invalid";
|
|
78
75
|
/**
|
|
79
76
|
* Time picker mode for internal selector state
|
|
80
77
|
*/
|
|
81
|
-
export type TimePickerMode =
|
|
78
|
+
export type TimePickerMode = "hour" | "minute" | "period";
|
|
82
79
|
/**
|
|
83
80
|
* Time period for 12-hour format
|
|
84
81
|
*/
|
|
85
|
-
export type TimePeriod =
|
|
82
|
+
export type TimePeriod = "AM" | "PM";
|
|
86
83
|
/**
|
|
87
84
|
* Parsed time object for internal use
|
|
88
85
|
*/
|
|
@@ -92,6 +89,25 @@ export interface ParsedTime {
|
|
|
92
89
|
second?: number;
|
|
93
90
|
period?: TimePeriod;
|
|
94
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* WheelColumn component props for iOS-style scroll wheel
|
|
94
|
+
*/
|
|
95
|
+
export interface WheelColumnProps {
|
|
96
|
+
/** Header label for the column */
|
|
97
|
+
label?: string;
|
|
98
|
+
/** Array of options to display */
|
|
99
|
+
options: (number | string)[];
|
|
100
|
+
/** Currently selected value */
|
|
101
|
+
value: number | string;
|
|
102
|
+
/** Callback when value changes */
|
|
103
|
+
onChange: (value: number | string) => void;
|
|
104
|
+
/** Height of each item in pixels (default: 40) */
|
|
105
|
+
itemHeight?: number;
|
|
106
|
+
/** Number of visible items (default: 5, should be odd) */
|
|
107
|
+
visibleItems?: number;
|
|
108
|
+
/** Theme overrides */
|
|
109
|
+
theme?: Partial<TimePickerThemeOverrides>;
|
|
110
|
+
}
|
|
95
111
|
/**
|
|
96
112
|
* Theme overrides for the TimePicker component
|
|
97
113
|
* Follows Select/DatePicker pattern with trigger-based styling
|
|
@@ -117,31 +133,42 @@ export interface TimePickerThemeOverrides {
|
|
|
117
133
|
iconStartPadding?: string;
|
|
118
134
|
/** End icon padding */
|
|
119
135
|
iconEndPadding?: string;
|
|
136
|
+
/** Placeholder text style */
|
|
137
|
+
placeholderTextStyle?: string;
|
|
138
|
+
/** Selected value text style */
|
|
139
|
+
valueTextStyle?: string;
|
|
120
140
|
/** Clear button style */
|
|
121
141
|
clearButtonStyle?: string;
|
|
122
142
|
/** Dropdown container style */
|
|
123
143
|
dropdownStyle?: string;
|
|
124
144
|
/** Dropdown size variants */
|
|
125
145
|
dropdownSizes?: Partial<Record<TimePickerSize, string>>;
|
|
126
|
-
/** Time selector container style */
|
|
127
|
-
selectorContainerStyle?: string;
|
|
128
|
-
/** Selector column style */
|
|
129
|
-
selectorColumnStyle?: string;
|
|
130
|
-
/** Selector column header container style */
|
|
131
|
-
selectorHeaderStyle?: string;
|
|
132
|
-
/** Selector column header label style */
|
|
133
|
-
selectorHeaderLabelStyle?: string;
|
|
134
|
-
/** Selector item style (use data-[selected=true] and data-[disabled=true]) */
|
|
135
|
-
selectorItemStyle?: string;
|
|
136
|
-
/** Selector item size variants */
|
|
137
|
-
selectorItemSizes?: Partial<Record<TimePickerSize, string>>;
|
|
138
146
|
/** Helper text style */
|
|
139
147
|
helperTextStyle?: string;
|
|
140
148
|
/** Helper text state variants */
|
|
141
149
|
helperTextStates?: Partial<Record<TimePickerState, string>>;
|
|
150
|
+
/** Wheel columns container style */
|
|
151
|
+
wheelContainerStyle?: string;
|
|
152
|
+
/** Individual wheel column style */
|
|
153
|
+
wheelColumnStyle?: string;
|
|
154
|
+
/** Wheel column header label style */
|
|
155
|
+
wheelHeaderStyle?: string;
|
|
156
|
+
/** Center highlight row style */
|
|
157
|
+
wheelHighlightStyle?: string;
|
|
158
|
+
/** Wheel item style */
|
|
159
|
+
wheelItemStyle?: string;
|
|
160
|
+
/** Wheel item active (selected) style */
|
|
161
|
+
wheelItemActiveStyle?: string;
|
|
162
|
+
/** Footer container style */
|
|
163
|
+
footerStyle?: string;
|
|
164
|
+
/** Inner input element style */
|
|
165
|
+
inputStyle?: string;
|
|
166
|
+
/** AM/PM period toggle button style */
|
|
167
|
+
periodToggleStyle?: string;
|
|
142
168
|
}
|
|
143
169
|
/**
|
|
144
170
|
* TimePickerTrigger component props
|
|
171
|
+
* Input-oriented trigger for combobox-style masked time entry
|
|
145
172
|
*/
|
|
146
173
|
export interface TimePickerTriggerProps {
|
|
147
174
|
/** Element ID */
|
|
@@ -164,14 +191,22 @@ export interface TimePickerTriggerProps {
|
|
|
164
191
|
iconEnd?: React.ReactNode;
|
|
165
192
|
/** Additional className */
|
|
166
193
|
className?: string;
|
|
167
|
-
/**
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
|
|
194
|
+
/** Masked display value for the input */
|
|
195
|
+
inputValue: string;
|
|
196
|
+
/** Masked input change handler */
|
|
197
|
+
onInputChange: (value: string) => void;
|
|
198
|
+
/** Focus handler that opens dropdown */
|
|
199
|
+
onInputFocus: () => void;
|
|
200
|
+
/** Keyboard handler for the input */
|
|
201
|
+
onInputKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
202
|
+
/** Time format — needed for AM/PM toggle rendering */
|
|
203
|
+
format: TimeFormat;
|
|
204
|
+
/** Current AM/PM value (12h only) */
|
|
205
|
+
period?: TimePeriod;
|
|
206
|
+
/** Toggle AM/PM handler (12h only) */
|
|
207
|
+
onPeriodToggle?: () => void;
|
|
208
|
+
/** Input placeholder */
|
|
209
|
+
placeholder: string;
|
|
175
210
|
}
|
|
176
211
|
/**
|
|
177
212
|
* Internal time selector props
|
|
@@ -183,8 +218,6 @@ export interface TimeSelectorProps {
|
|
|
183
218
|
format: TimeFormat;
|
|
184
219
|
/** Minute step interval */
|
|
185
220
|
step: number;
|
|
186
|
-
/** Whether to show seconds */
|
|
187
|
-
showSeconds: boolean;
|
|
188
221
|
/** Minimum time constraint */
|
|
189
222
|
minTime?: string;
|
|
190
223
|
/** Maximum time constraint */
|
|
@@ -201,3 +234,24 @@ export interface TimeValidationResult {
|
|
|
201
234
|
isValid: boolean;
|
|
202
235
|
error?: string;
|
|
203
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* TimePickerContent component props
|
|
239
|
+
*/
|
|
240
|
+
export interface TimePickerContentProps {
|
|
241
|
+
/** Whether the dropdown is open */
|
|
242
|
+
isOpen: boolean;
|
|
243
|
+
/** Callback when Cancel is clicked */
|
|
244
|
+
onCancel: () => void;
|
|
245
|
+
/** Callback when Save is clicked */
|
|
246
|
+
onSave: () => void;
|
|
247
|
+
/** Use portal for rendering */
|
|
248
|
+
portal?: boolean;
|
|
249
|
+
/** Dropdown placement */
|
|
250
|
+
placement?: "bottom-start" | "bottom-end" | "top-start" | "top-end";
|
|
251
|
+
/** Offset from trigger */
|
|
252
|
+
offset?: number;
|
|
253
|
+
/** Content children (wheel columns) */
|
|
254
|
+
children?: React.ReactNode;
|
|
255
|
+
/** Ref to the dropdown element (for portal-aware click-outside detection) */
|
|
256
|
+
dropdownRef?: React.RefObject<HTMLDivElement | null>;
|
|
257
|
+
}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { TimePickerContentProps } from "./TimePicker.types";
|
|
2
3
|
/**
|
|
3
4
|
* TimePickerContent Component - contains the time selector dropdown
|
|
4
5
|
* Uses portal positioning like Select and DatePicker components
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Title header "Select time"
|
|
9
|
+
* - Wheel column children (passed as children)
|
|
10
|
+
* - Footer with Cancel and Save buttons
|
|
5
11
|
*/
|
|
6
|
-
interface TimePickerContentProps {
|
|
7
|
-
isOpen: boolean;
|
|
8
|
-
onClose?: () => void;
|
|
9
|
-
portal?: boolean;
|
|
10
|
-
placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
|
|
11
|
-
offset?: number;
|
|
12
|
-
children?: React.ReactNode;
|
|
13
|
-
}
|
|
14
12
|
export declare const TimePickerContent: React.FC<TimePickerContentProps>;
|
|
15
|
-
export {};
|
|
@@ -1,18 +1,126 @@
|
|
|
1
|
-
import React__default, { useContext, useCallback } from 'react';
|
|
1
|
+
import React__default, { useContext, useCallback, useState, useEffect } from 'react';
|
|
2
2
|
import { AnimatePresence, motion } from 'motion/react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
import { TimePickerContext } from './TimePicker.js';
|
|
6
6
|
import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
|
|
7
7
|
import { createDropdownAnimations } from '../Select/Select.animations.js';
|
|
8
|
+
import '../../core/Accordion/Accordion.js';
|
|
9
|
+
import '../../core/AlertDialog/AlertDialog.js';
|
|
10
|
+
import '../../core/Avatar/Avatar.js';
|
|
11
|
+
import '../../core/AvatarGroup/AvatarGroup.js';
|
|
12
|
+
import '../../core/Badge/Badge.js';
|
|
13
|
+
import '../../core/Breadcrumbs/Breadcrumbs.js';
|
|
14
|
+
import '../../core/Breadcrumbs/Breadcrumbs.theme.js';
|
|
15
|
+
import { Button } from '../../core/Button/Button.js';
|
|
16
|
+
import '../../core/ButtonGroup/ButtonGroup.js';
|
|
17
|
+
import '../../core/ButtonGroup/ButtonGroupSeparator.js';
|
|
18
|
+
import '../../core/ButtonGroup/ButtonGroupText.js';
|
|
19
|
+
import '@heroicons/react/24/outline';
|
|
20
|
+
import '../Select/Select.js';
|
|
21
|
+
import '../Select/Select.theme.js';
|
|
22
|
+
import '../../core/Calendar/CalendarMini/CalendarMini.js';
|
|
23
|
+
import '../../core/Card/Card.js';
|
|
24
|
+
import '../../core/CardStack/CardStack.js';
|
|
25
|
+
import '../../core/Carousel/Carousel.js';
|
|
26
|
+
import '../../core/Kbd/Kbd.js';
|
|
27
|
+
import '../../effects/Overlay/Overlay.js';
|
|
28
|
+
import '../../core/Divider/Divider.js';
|
|
29
|
+
import '../../core/Drawer/Drawer.js';
|
|
30
|
+
import '../../core/Dropdown/Dropdown.js';
|
|
31
|
+
import '../../core/Dropdown/DropdownTrigger.js';
|
|
32
|
+
import '../../core/Dropdown/DropdownMenu.js';
|
|
33
|
+
import '../../core/Dropdown/DropdownItem.js';
|
|
34
|
+
import '../../core/Dropdown/DropdownSection.js';
|
|
35
|
+
import '../../core/Dropdown/DropdownSeparator.js';
|
|
36
|
+
import '../../core/Link/Link.js';
|
|
37
|
+
import '../../core/Loader/Loader.js';
|
|
38
|
+
import '../../core/Modal/Modal.js';
|
|
39
|
+
import '../../core/Pagination/Pagination.js';
|
|
40
|
+
import '../../core/Popover/Popover.js';
|
|
41
|
+
import '../../core/Popover/PopoverContext.js';
|
|
42
|
+
import '../../core/Progress/Progress.js';
|
|
43
|
+
import '../../core/ProgressiveBlur/ProgressiveBlur.js';
|
|
44
|
+
import '../../core/Segmented/Segmented.js';
|
|
45
|
+
import '../../core/Skeleton/Skeleton.js';
|
|
46
|
+
import '../../core/SlidingNumber/SlidingNumber.js';
|
|
47
|
+
import '../../core/Stepper/Stepper.js';
|
|
48
|
+
import '../../core/Tabs/Tabs.js';
|
|
49
|
+
import '../../core/Tabs/TabsList.js';
|
|
50
|
+
import '../../core/Tabs/TabsTrigger.js';
|
|
51
|
+
import '../../core/Tabs/TabsContent.js';
|
|
52
|
+
import '../../core/Tabs/TabsContext.js';
|
|
53
|
+
import '../../core/Tooltip/Tooltip.js';
|
|
54
|
+
import '../../core/Tooltip/Tooltip.animations.js';
|
|
55
|
+
import '../../core/Tree/Tree.js';
|
|
56
|
+
import '../../core/Tag/Tag.js';
|
|
57
|
+
import '../../core/Alert/Alert.js';
|
|
58
|
+
import '../../core/Toast/Toast.js';
|
|
59
|
+
import '../../core/Toast/ToastProvider.js';
|
|
60
|
+
import '../../core/Notification/Notification.js';
|
|
61
|
+
import '@heroicons/react/24/solid';
|
|
62
|
+
import '../../core/Message/Message.js';
|
|
63
|
+
import '../../core/Message/TypeWriter.js';
|
|
64
|
+
import '../../core/Empty/Empty.js';
|
|
65
|
+
import '../../core/Table/index.js';
|
|
66
|
+
import '../../core/DragDrop/DragDrop.js';
|
|
67
|
+
import '../../core/Sortable/Sortable.js';
|
|
68
|
+
import '../../core/NavItem/NavItem.js';
|
|
69
|
+
import '../../core/Sidebar/Sidebar.js';
|
|
70
|
+
import '../../core/Sidebar/SidebarHeader.js';
|
|
71
|
+
import '../../core/Sidebar/SidebarContent.js';
|
|
72
|
+
import '../../core/Sidebar/SidebarFooter.js';
|
|
73
|
+
import '../../core/Sidebar/SidebarNav.js';
|
|
74
|
+
import '../../core/Sidebar/SidebarNavGroup.js';
|
|
75
|
+
import '../../core/Sidebar/SidebarToggle.js';
|
|
76
|
+
import '../../core/Sidebar/SidebarContext.js';
|
|
8
77
|
|
|
9
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Hook to detect dark mode state from document
|
|
80
|
+
*/
|
|
81
|
+
const useDarkMode = () => {
|
|
82
|
+
const [isDark, setIsDark] = useState(false);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (typeof document === "undefined")
|
|
85
|
+
return;
|
|
86
|
+
const checkDarkMode = () => {
|
|
87
|
+
const hasDarkClass = document.documentElement.classList.contains("dark") ||
|
|
88
|
+
document.body.classList.contains("dark") ||
|
|
89
|
+
document.querySelector(".dark") !== null;
|
|
90
|
+
setIsDark(hasDarkClass);
|
|
91
|
+
};
|
|
92
|
+
checkDarkMode();
|
|
93
|
+
const observer = new MutationObserver(checkDarkMode);
|
|
94
|
+
observer.observe(document.documentElement, {
|
|
95
|
+
attributes: true,
|
|
96
|
+
attributeFilter: ["class"],
|
|
97
|
+
});
|
|
98
|
+
observer.observe(document.body, {
|
|
99
|
+
attributes: true,
|
|
100
|
+
attributeFilter: ["class"],
|
|
101
|
+
});
|
|
102
|
+
return () => observer.disconnect();
|
|
103
|
+
}, []);
|
|
104
|
+
return isDark;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* TimePickerContent Component - contains the time selector dropdown
|
|
108
|
+
* Uses portal positioning like Select and DatePicker components
|
|
109
|
+
*
|
|
110
|
+
* Features:
|
|
111
|
+
* - Title header "Select time"
|
|
112
|
+
* - Wheel column children (passed as children)
|
|
113
|
+
* - Footer with Cancel and Save buttons
|
|
114
|
+
*/
|
|
115
|
+
const TimePickerContent = ({ isOpen, onCancel, onSave, portal = true, placement = "bottom-start", offset = 4, children, dropdownRef, }) => {
|
|
10
116
|
var _a, _b;
|
|
11
117
|
const context = useContext(TimePickerContext);
|
|
12
118
|
if (!context) {
|
|
13
|
-
throw new Error(
|
|
119
|
+
throw new Error("TimePickerContent must be used within a TimePicker");
|
|
14
120
|
}
|
|
15
121
|
const { theme, triggerRef, size } = context;
|
|
122
|
+
// Detect dark mode for portal content
|
|
123
|
+
const isDarkMode = useDarkMode();
|
|
16
124
|
// Use enhanced dropdown positioning hook with direction-aware animations
|
|
17
125
|
// Pass trigger width so dropdown matches trigger size
|
|
18
126
|
const triggerWidth = ((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0;
|
|
@@ -25,24 +133,49 @@ const TimePickerContent = ({ isOpen, onClose, portal = true, placement = 'bottom
|
|
|
25
133
|
});
|
|
26
134
|
// Create direction-aware animations based on actual placement
|
|
27
135
|
const animations = createDropdownAnimations(isFlipped);
|
|
28
|
-
// Combine refs
|
|
136
|
+
// Combine refs (including dropdownRef for portal-aware click-outside)
|
|
29
137
|
const combinedRef = useCallback((el) => {
|
|
30
|
-
if (contentRef &&
|
|
138
|
+
if (contentRef &&
|
|
139
|
+
typeof contentRef === "object" &&
|
|
140
|
+
"current" in contentRef) {
|
|
31
141
|
contentRef.current = el;
|
|
32
142
|
}
|
|
33
|
-
|
|
143
|
+
if (dropdownRef &&
|
|
144
|
+
typeof dropdownRef === "object" &&
|
|
145
|
+
"current" in dropdownRef) {
|
|
146
|
+
dropdownRef.current =
|
|
147
|
+
el;
|
|
148
|
+
}
|
|
149
|
+
}, [contentRef, dropdownRef]);
|
|
150
|
+
// Handle keyboard shortcuts
|
|
151
|
+
const handleKeyDown = useCallback((e) => {
|
|
152
|
+
if (e.key === "Escape") {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
onCancel();
|
|
155
|
+
}
|
|
156
|
+
else if (e.key === "Enter") {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
onSave();
|
|
159
|
+
}
|
|
160
|
+
}, [onCancel, onSave]);
|
|
34
161
|
const contentElement = (React__default.createElement(AnimatePresence, { mode: "wait" }, isOpen && (React__default.createElement(motion.div, { ref: combinedRef, className: cn(theme.dropdownStyle, (_b = theme.dropdownSizes) === null || _b === void 0 ? void 0 : _b[size]), style: {
|
|
35
162
|
...cssVariables,
|
|
36
|
-
overscrollBehavior:
|
|
37
|
-
...(portal
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
163
|
+
overscrollBehavior: "contain",
|
|
164
|
+
...(portal
|
|
165
|
+
? {
|
|
166
|
+
top: `${position.top}px`,
|
|
167
|
+
left: `${position.left}px`,
|
|
168
|
+
minWidth: `${position.width}px`,
|
|
169
|
+
}
|
|
170
|
+
: {}),
|
|
171
|
+
}, variants: animations, initial: "initial", animate: "visible", exit: "exit", onKeyDown: handleKeyDown, role: "dialog", "aria-modal": "true", "aria-label": "Select time" },
|
|
172
|
+
React__default.createElement("div", { className: cn(theme.wheelContainerStyle), style: { height: 200 } }, children),
|
|
173
|
+
React__default.createElement("div", { className: cn(theme.footerStyle) },
|
|
174
|
+
React__default.createElement(Button, { size: "sm", variant: "outline", color: "neutral", onClick: onCancel, "aria-label": "Cancel time selection", className: "flex-1" }, "Cancel"),
|
|
175
|
+
React__default.createElement(Button, { size: "sm", onClick: onSave, "aria-label": "Save selected time", className: "flex-1" }, "Save"))))));
|
|
176
|
+
// Use portal if enabled and client-side - wrap with dark class for dark mode support
|
|
177
|
+
return portal && typeof document !== "undefined"
|
|
178
|
+
? createPortal(React__default.createElement("div", { className: isDarkMode ? "dark" : undefined }, contentElement), document.body)
|
|
46
179
|
: contentElement;
|
|
47
180
|
};
|
|
48
181
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TimePickerTriggerProps } from './TimePicker.types';
|
|
3
3
|
/**
|
|
4
|
-
* TimePickerTrigger Component -
|
|
5
|
-
* Displays
|
|
6
|
-
* Follows the same pattern as DatePickerTrigger and SelectButton
|
|
4
|
+
* TimePickerTrigger Component - combobox-style masked input
|
|
5
|
+
* Displays a masked time input that opens the wheel picker on focus
|
|
6
|
+
* Follows the same visual pattern as DatePickerTrigger and SelectButton
|
|
7
7
|
*/
|
|
8
8
|
export declare const TimePickerTrigger: React.FC<TimePickerTriggerProps>;
|
|
@@ -4,42 +4,45 @@ import { cn } from '../../../utils/cn.js';
|
|
|
4
4
|
import { TimePickerContext } from './TimePicker.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* TimePickerTrigger Component -
|
|
8
|
-
* Displays
|
|
9
|
-
* Follows the same pattern as DatePickerTrigger and SelectButton
|
|
7
|
+
* TimePickerTrigger Component - combobox-style masked input
|
|
8
|
+
* Displays a masked time input that opens the wheel picker on focus
|
|
9
|
+
* Follows the same visual pattern as DatePickerTrigger and SelectButton
|
|
10
10
|
*/
|
|
11
|
-
const TimePickerTrigger = ({ id, disabled, isOpen, state = 'default', size = 'md', clearable, onClear, iconStart, iconEnd, className,
|
|
11
|
+
const TimePickerTrigger = ({ id, disabled, isOpen, state = 'default', size = 'md', clearable, onClear, iconStart, iconEnd, className, inputValue, onInputChange, onInputFocus, onInputKeyDown, format, period, onPeriodToggle, placeholder, }) => {
|
|
12
12
|
var _a, _b, _c, _d;
|
|
13
13
|
const context = useContext(TimePickerContext);
|
|
14
14
|
if (!context) {
|
|
15
15
|
throw new Error('TimePickerTrigger must be used within a TimePicker');
|
|
16
16
|
}
|
|
17
|
-
const { theme, triggerRef, hasValue } = context;
|
|
17
|
+
const { theme, triggerRef, inputRef, hasValue } = context;
|
|
18
18
|
const baseStyle = theme.baseStyle || "";
|
|
19
19
|
const sizeStyle = ((_a = theme.triggerSizes) === null || _a === void 0 ? void 0 : _a[size]) || "";
|
|
20
20
|
const stateStyle = ((_b = theme.triggerStates) === null || _b === void 0 ? void 0 : _b[state]) || "";
|
|
21
21
|
const hoverStateStyle = ((_c = theme.triggerHoverStates) === null || _c === void 0 ? void 0 : _c[state]) || "";
|
|
22
|
-
const focusStateStyle = ((_d = theme.triggerFocusStates) === null || _d === void 0 ? void 0 : _d[state]) || "";
|
|
23
22
|
const iconStartStyle = theme.iconStartStyle || "";
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
// Apply focused styles when open - same pattern as SelectButton and DatePickerTrigger
|
|
23
|
+
const inputStyle = theme.inputStyle || "";
|
|
24
|
+
const periodToggleStyle = theme.periodToggleStyle || "";
|
|
25
|
+
// Apply focused styles when open — same pattern as SelectButton and DatePickerTrigger
|
|
28
26
|
const activeFocusState = isOpen
|
|
29
|
-
?
|
|
27
|
+
? ((_d = theme.triggerFocusStates) === null || _d === void 0 ? void 0 : _d[state]) || "outline-2 outline-[var(--color-primary-600)] -outline-offset-1 ring-4 ring-[var(--color-primary)]/10 dark:outline-[var(--color-primary-500)] dark:ring-[var(--color-primary-500)]/20"
|
|
30
28
|
: "";
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
// Determine whether start icon is present (for input padding)
|
|
30
|
+
const hasStartIcon = iconStart !== undefined ? Boolean(iconStart) : true;
|
|
31
|
+
const iconStartPadding = theme.iconStartPadding || "";
|
|
32
|
+
return (React__default.createElement("div", { ref: triggerRef, className: "relative w-full" },
|
|
33
|
+
React__default.createElement("div", { className: cn(baseStyle, stateStyle, hoverStateStyle, activeFocusState, 'w-full items-center', className // User overrides take highest precedence
|
|
34
|
+
) },
|
|
35
|
+
React__default.createElement("div", { className: "relative flex-1" },
|
|
36
|
+
React__default.createElement("input", { ref: inputRef, id: id, type: "text", inputMode: "numeric", value: inputValue, onChange: (e) => onInputChange(e.target.value), onFocus: onInputFocus, onKeyDown: onInputKeyDown, placeholder: placeholder, maxLength: 5, disabled: disabled, className: cn(inputStyle, sizeStyle, hasStartIcon && iconStartPadding), "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Enter time", autoComplete: "off" }),
|
|
37
|
+
iconStart !== undefined ? (iconStart && React__default.createElement("div", { className: iconStartStyle }, iconStart)) : (React__default.createElement("div", { className: iconStartStyle },
|
|
38
|
+
React__default.createElement(ClockIcon, { className: "h-4 w-4" })))),
|
|
39
|
+
format === '12h' && (React__default.createElement("button", { type: "button", onClick: onPeriodToggle, disabled: disabled, className: cn(periodToggleStyle, "shrink-0"), "aria-label": `Toggle AM/PM, current: ${period}`, tabIndex: -1 }, period || 'AM')),
|
|
37
40
|
clearable && hasValue && !disabled && (React__default.createElement("button", { type: "button", onClick: (e) => {
|
|
38
41
|
e.stopPropagation();
|
|
39
42
|
onClear === null || onClear === void 0 ? void 0 : onClear();
|
|
40
|
-
}, className:
|
|
43
|
+
}, className: "shrink-0 p-0.5 rounded text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-background-secondary)] transition-colors", "aria-label": "Clear time", tabIndex: -1 },
|
|
41
44
|
React__default.createElement(XMarkIcon, { className: "w-4 h-4" }))),
|
|
42
|
-
iconEnd !== undefined ? (iconEnd && React__default.createElement("span", { className:
|
|
45
|
+
iconEnd !== undefined ? (iconEnd && (React__default.createElement("span", { className: "shrink-0 flex items-center pr-3 pointer-events-none text-[var(--color-text-muted)] dark:text-[var(--color-neutral-500)]" }, iconEnd))) : (React__default.createElement("span", { className: "shrink-0 flex items-center pr-3 pointer-events-none text-[var(--color-text-muted)] dark:text-[var(--color-neutral-500)]" },
|
|
43
46
|
React__default.createElement(ChevronUpDownIcon, { className: "h-4 w-4" }))))));
|
|
44
47
|
};
|
|
45
48
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WheelColumnProps } from './TimePicker.types';
|
|
3
|
+
/**
|
|
4
|
+
* WheelColumn Component - iOS-style scroll wheel column
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - CSS scroll-snap for native snapping behavior
|
|
8
|
+
* - Momentum scrolling with -webkit-overflow-scrolling: touch
|
|
9
|
+
* - Click-to-select items
|
|
10
|
+
* - Mouse drag-to-scroll on desktop
|
|
11
|
+
* - Fade effect using CSS mask-image gradient
|
|
12
|
+
* - Center highlight row with fixed positioning
|
|
13
|
+
*/
|
|
14
|
+
export declare const WheelColumn: React.FC<WheelColumnProps>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React__default, { useCallback, useMemo } from 'react';
|
|
2
|
+
import { cn } from '../../../utils/cn.js';
|
|
3
|
+
import { useWheelPicker } from './useWheelPicker.js';
|
|
4
|
+
import { timePickerTheme } from './TimePicker.theme.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WheelColumn Component - iOS-style scroll wheel column
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - CSS scroll-snap for native snapping behavior
|
|
11
|
+
* - Momentum scrolling with -webkit-overflow-scrolling: touch
|
|
12
|
+
* - Click-to-select items
|
|
13
|
+
* - Mouse drag-to-scroll on desktop
|
|
14
|
+
* - Fade effect using CSS mask-image gradient
|
|
15
|
+
* - Center highlight row with fixed positioning
|
|
16
|
+
*/
|
|
17
|
+
const WheelColumn = ({ label, options, value, onChange, itemHeight = 40, visibleItems = 5, theme = {}, }) => {
|
|
18
|
+
const mergedTheme = { ...timePickerTheme, ...theme };
|
|
19
|
+
// Use wheel picker hook for scroll behavior
|
|
20
|
+
const { containerRef, scrollToValue, paddingY, currentIndex, isDragging } = useWheelPicker({
|
|
21
|
+
options,
|
|
22
|
+
value,
|
|
23
|
+
onChange,
|
|
24
|
+
itemHeight,
|
|
25
|
+
visibleItems,
|
|
26
|
+
});
|
|
27
|
+
// Handle clicking an item to select it (scroll to it, onChange fires on scroll end)
|
|
28
|
+
const handleItemClick = useCallback((option) => {
|
|
29
|
+
// Don't treat a drag release as a click
|
|
30
|
+
if (isDragging)
|
|
31
|
+
return;
|
|
32
|
+
scrollToValue(option);
|
|
33
|
+
}, [scrollToValue, isDragging]);
|
|
34
|
+
// Calculate container height
|
|
35
|
+
const containerHeight = itemHeight * visibleItems;
|
|
36
|
+
// Format value for display (pad numbers with leading zeros)
|
|
37
|
+
const formatValue = (val) => {
|
|
38
|
+
if (typeof val === 'number') {
|
|
39
|
+
return val.toString().padStart(2, '0');
|
|
40
|
+
}
|
|
41
|
+
return val;
|
|
42
|
+
};
|
|
43
|
+
// Memoize options list to prevent unnecessary re-renders
|
|
44
|
+
const optionElements = useMemo(() => {
|
|
45
|
+
return options.map((option, index) => {
|
|
46
|
+
const isActive = index === currentIndex;
|
|
47
|
+
return (React__default.createElement("div", { key: `${option}-${index}`, className: cn(mergedTheme.wheelItemStyle, isActive && mergedTheme.wheelItemActiveStyle, 'snap-center'), style: {
|
|
48
|
+
height: itemHeight,
|
|
49
|
+
minHeight: itemHeight,
|
|
50
|
+
}, role: "option", "aria-selected": isActive, "data-value": option, onClick: () => handleItemClick(option) }, formatValue(option)));
|
|
51
|
+
});
|
|
52
|
+
}, [options, currentIndex, mergedTheme, itemHeight, handleItemClick]);
|
|
53
|
+
return (React__default.createElement("div", { className: cn(mergedTheme.wheelColumnStyle), role: "listbox", "aria-label": label },
|
|
54
|
+
React__default.createElement("div", { className: cn(mergedTheme.wheelHeaderStyle) }, label || '\u00A0'),
|
|
55
|
+
React__default.createElement("div", { className: "relative flex-1", style: { height: containerHeight } },
|
|
56
|
+
React__default.createElement("div", { className: cn(mergedTheme.wheelHighlightStyle), style: {
|
|
57
|
+
top: paddingY,
|
|
58
|
+
height: itemHeight,
|
|
59
|
+
}, "aria-hidden": "true" }),
|
|
60
|
+
React__default.createElement("div", { ref: containerRef, className: cn('absolute inset-0 overflow-y-auto scrollbar-hide',
|
|
61
|
+
// CSS scroll snap for native snapping
|
|
62
|
+
'snap-y snap-mandatory',
|
|
63
|
+
// iOS momentum scrolling
|
|
64
|
+
'overscroll-contain'), style: {
|
|
65
|
+
paddingTop: paddingY,
|
|
66
|
+
paddingBottom: paddingY,
|
|
67
|
+
// CSS mask for fade effect at edges
|
|
68
|
+
maskImage: 'linear-gradient(to bottom, transparent 0%, black 30%, black 70%, transparent 100%)',
|
|
69
|
+
WebkitMaskImage: 'linear-gradient(to bottom, transparent 0%, black 30%, black 70%, transparent 100%)',
|
|
70
|
+
// iOS smooth scrolling
|
|
71
|
+
WebkitOverflowScrolling: 'touch',
|
|
72
|
+
// Hide scrollbar
|
|
73
|
+
scrollbarWidth: 'none',
|
|
74
|
+
msOverflowStyle: 'none',
|
|
75
|
+
}, tabIndex: 0, onKeyDown: (e) => {
|
|
76
|
+
if (e.key === 'ArrowUp') {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
const newIndex = Math.max(0, currentIndex - 1);
|
|
79
|
+
onChange(options[newIndex]);
|
|
80
|
+
}
|
|
81
|
+
else if (e.key === 'ArrowDown') {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
const newIndex = Math.min(options.length - 1, currentIndex + 1);
|
|
84
|
+
onChange(options[newIndex]);
|
|
85
|
+
}
|
|
86
|
+
} }, optionElements))));
|
|
87
|
+
};
|
|
88
|
+
WheelColumn.displayName = 'WheelColumn';
|
|
89
|
+
|
|
90
|
+
export { WheelColumn };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { TimePicker } from './TimePicker';
|
|
2
2
|
export { TimePickerTrigger } from './TimePickerTrigger';
|
|
3
3
|
export { TimePickerContent } from './TimePickerContent';
|
|
4
|
-
export
|
|
4
|
+
export { WheelColumn } from './WheelColumn';
|
|
5
|
+
export { useWheelPicker } from './useWheelPicker';
|
|
6
|
+
export type { TimePickerProps, TimePickerTriggerProps, TimePickerContentProps, WheelColumnProps, TimeFormat, TimePickerSize, TimePickerState, TimePickerThemeOverrides, ParsedTime, TimePeriod } from './TimePicker.types';
|
|
7
|
+
export type { UseWheelPickerOptions, UseWheelPickerReturn } from './useWheelPicker';
|
|
5
8
|
export { timePickerTheme } from './TimePicker.theme';
|
|
6
9
|
export { timePickerAnimations } from './TimePicker.animations';
|