@xsolla/xui-gradient-picker 0.204.0

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/README.md ADDED
@@ -0,0 +1,280 @@
1
+ # Gradient Picker
2
+
3
+ A cross-platform React gradient picker: a live preview track with draggable colour stops, per-stop colour and opacity editing via ColorPicker, and CSS-compatible gradient output.
4
+
5
+ <!-- BEGIN:xui-mcp-instructions:gradient-picker -->
6
+
7
+ A compound component for defining a CSS-style colour gradient. Combines a visual gradient preview track with draggable stop markers and integrates with ColorPicker to edit the colour and opacity of each stop individually. Supports three gradient types and up to five colour stops.
8
+
9
+ ### When to use
10
+
11
+ - When a user needs to define a multi-colour gradient — background fills, banner overlays, avatar tints, UI theme customisation
12
+ - In design tool contexts, theme editors, or advanced colour configuration panels where fine-grained gradient control is required
13
+ - When the product supports gradient fills as a first-class input (e.g. a game customisation screen, a chart background picker)
14
+
15
+ ### When not to use
16
+
17
+ - When a solid colour is sufficient — use ColorPicker instead
18
+ - When only a simple two-colour linear gradient with fixed endpoints is needed and the user doesn't need to adjust stops — consider a simpler two-swatch input
19
+ - In contexts where gradient complexity would overwhelm the user — hide behind an "Advanced" toggle
20
+
21
+ ### Content guidelines
22
+
23
+ - Gradient type labels — use the standard CSS-adjacent names: "Linear", "Radial", "Angular" (or "Conic" if the product uses that term). Do not use internal technical names.
24
+ - Stop position display — when a stop is active, show its position as a percentage (e.g. 0%, 50%, 100%) in a read-only or editable label near the marker or in the ColorPicker header. This helps users set precise positions numerically.
25
+ - Minimum stops warning — if the user tries to remove the last stop, show a tooltip or brief inline message: "A gradient requires at least one stop" rather than silently blocking the action.
26
+
27
+ ### Behaviour guidelines
28
+
29
+ - Adding stops — clicking on an empty area of the stop track adds a new stop at that position, interpolating its initial colour from the gradient at that point. The new stop immediately becomes Active. Adding is only permitted up to the product-defined maximum (5 in Figma).
30
+ - Removing stops — a stop can be removed by dragging it off the track (up or down beyond a threshold) or via a delete action (e.g. pressing Delete / Backspace when the stop is active). A minimum of 1 stop must always remain; do not allow removing the last stop.
31
+ - Dragging stops — a stop is dragged horizontally along the track. Position is expressed as a percentage (0%–100%). Stops cannot be dragged past each other — they swap order when they cross. Provide a smooth position update with no snap unless the product explicitly requires snapping to percentage increments.
32
+ - Active stop ColorPicker — the ColorPicker panel opens below the component when a stop is activated. If the panel would push the component out of the viewport, position it above the track instead. Closing the ColorPicker (clicking outside, pressing Escape) deactivates the stop.
33
+ - Gradient type change — switching Gradient type via the Select applies immediately to the preview without resetting stop positions or colours.
34
+ - Angle / centre point — for Linear, the gradient angle should be adjustable (e.g. via a degree input or a rotation handle on the preview). For Radial, the centre point should be configurable. For Angular, the rotation angle and start point should be configurable. These controls are not shown in the Figma component directly but are part of the full implementation.
35
+ - Real-time preview — every interaction (dragging a stop, changing a colour, switching gradient type, adjusting angle) must update the gradient preview in real time without requiring a confirm action.
36
+ - Output format — the component outputs a CSS-compatible gradient string that can be applied directly as a background or background-image value. Provide a copy action to let the user copy the gradient string.
37
+
38
+ ### Accessibility
39
+
40
+ - The stop track must be operable by keyboard. When a stop has focus, ← / → arrows move it by 1% increments; Shift+← / Shift+→ move it by 10% increments.
41
+ - Each .GradientStop must have role=*"slider"* with aria-label identifying the stop (e.g. aria-label=*"Stop 1 position"*) and aria-valuenow / aria-valuemin=*"0"* / aria-valuemax=*"100"*.
42
+ - The gradient type selector must have aria-label=*"Gradient type"*.
43
+ - When a stop is activated and the ColorPicker opens, focus must move into the ColorPicker. When the ColorPicker closes, focus must return to the stop marker.
44
+ - The gradient preview is decorative — it must have aria-hidden=*"true"* and not receive focus.
45
+ - Adding a stop via keyboard: provide a button (e.g. *"+ Add stop"*) as a keyboard-accessible alternative to clicking on the track.
46
+ - Removing a stop via keyboard: when a stop is active, Delete / Backspace removes it and focus moves to the adjacent stop or the track.
47
+ - Do not rely on the visual gradient colour alone to communicate stop positions — always show numeric position values for screen reader users and users who cannot perceive colour differences in the gradient.
48
+
49
+ ### Gradient types
50
+
51
+ The angle can only be controlled for linear gradients and angular gradients.
52
+
53
+ ### Stop hover
54
+
55
+ While dragging a gradient stop, the row of the corresponding stop transitions into the active state.
56
+
57
+ <!-- END:xui-mcp-instructions:gradient-picker -->
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ npm install @xsolla/xui-gradient-picker
63
+ ```
64
+
65
+ ## Demo
66
+
67
+ ### Basic Gradient Picker
68
+
69
+ ```tsx
70
+ import * as React from "react";
71
+ import { GradientPicker } from "@xsolla/xui-gradient-picker";
72
+
73
+ export default function BasicGradientPicker() {
74
+ return <GradientPicker onChange={({ css }) => console.log(css)} />;
75
+ }
76
+ ```
77
+
78
+ ### Controlled Gradient Picker
79
+
80
+ ```tsx
81
+ import * as React from "react";
82
+ import {
83
+ GradientPicker,
84
+ DEFAULT_GRADIENT,
85
+ toCssGradient,
86
+ type GradientValue,
87
+ } from "@xsolla/xui-gradient-picker";
88
+
89
+ export default function ControlledGradientPicker() {
90
+ const [gradient, setGradient] = React.useState<GradientValue>(
91
+ DEFAULT_GRADIENT
92
+ );
93
+
94
+ return (
95
+ <>
96
+ <GradientPicker
97
+ value={gradient}
98
+ onChange={({ value }) => setGradient(value)}
99
+ />
100
+ <div style={{ backgroundImage: toCssGradient(gradient) }} />
101
+ </>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ### Radial Gradient
107
+
108
+ ```tsx
109
+ import * as React from "react";
110
+ import { GradientPicker } from "@xsolla/xui-gradient-picker";
111
+
112
+ export default function RadialGradient() {
113
+ return (
114
+ <GradientPicker
115
+ defaultValue={{
116
+ type: "radial",
117
+ angle: 0,
118
+ stops: [
119
+ { id: "stop-1", color: "#D9D9D9", position: 0, opacity: 100 },
120
+ { id: "stop-2", color: "#22A8C3", position: 100, opacity: 100 },
121
+ ],
122
+ }}
123
+ />
124
+ );
125
+ }
126
+ ```
127
+
128
+ Radial gradients have no rotation, so the angle field is hidden for them.
129
+
130
+ ### Angular ("Conic") Gradient
131
+
132
+ ```tsx
133
+ import * as React from "react";
134
+ import { GradientPicker } from "@xsolla/xui-gradient-picker";
135
+
136
+ export default function AngularGradient() {
137
+ return (
138
+ <GradientPicker
139
+ typeLabels={{ angular: "Conic gradient" }}
140
+ onChange={({ css }) => console.log(css)}
141
+ />
142
+ );
143
+ }
144
+ ```
145
+
146
+ ## Anatomy
147
+
148
+ ```jsx
149
+ import { GradientPicker } from "@xsolla/xui-gradient-picker";
150
+
151
+ <GradientPicker
152
+ value={gradient} // Controlled gradient value
153
+ defaultValue={initial} // Initial value for uncontrolled usage
154
+ onChange={handleChange} // ({ value, css }) => void
155
+ gradientTypes={["linear", "radial", "angular"]} // Types offered in the selector
156
+ typeLabels={{ angular: "Conic gradient" }} // Option label overrides
157
+ minStops={1} // Floor for removal
158
+ maxStops={5} // Ceiling for adding
159
+ disabled={false} // Disable every control
160
+ stopsLabel="Stops" // Heading above the stop list
161
+ />;
162
+ ```
163
+
164
+ ## API Reference
165
+
166
+ ### GradientPicker
167
+
168
+ **GradientPickerProps:**
169
+
170
+ | Prop | Type | Default | Description |
171
+ | :------------- | :---------------------------------------------- | :----------------------------------- | :------------------------------------------------------------------------------------------------------------ |
172
+ | `testID` | `string` | — | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
173
+ | value | `GradientValue` | — | Controlled gradient value. Pair with `onChange`. |
174
+ | defaultValue | `GradientValue` | `DEFAULT_GRADIENT` | Initial gradient value for uncontrolled usage. |
175
+ | onChange | `(event: GradientPickerChangeEvent) => void` | — | Fired on every interaction. Receives the new value and its CSS string. |
176
+ | gradientTypes | `GradientType[]` | `["linear", "radial", "angular"]` | Gradient types offered in the selector, in display order. |
177
+ | typeLabels | `Partial<Record<GradientType, string>>` | — | Overrides for the gradient-type option labels. |
178
+ | minStops | `number` | `1` | Smallest number of stops the user may reduce the gradient to. |
179
+ | maxStops | `number` | `5` | Largest number of stops the user may add. |
180
+ | disabled | `boolean` | `false` | Disables every control and blocks track interaction. |
181
+ | typeAriaLabel | `string` | `"Gradient type"` | Accessible name for the gradient-type selector. |
182
+ | angleAriaLabel | `string` | `"Gradient angle"` | Accessible name for the angle field. |
183
+ | stopsLabel | `string` | `"Stops"` | Heading rendered above the stop list. |
184
+
185
+ ### Types
186
+
187
+ ```typescript
188
+ type GradientType = "linear" | "radial" | "angular";
189
+
190
+ interface GradientStop {
191
+ id: string; // Stable identity, survives reordering
192
+ color: string; // "#RRGGBB"
193
+ position: number; // 0–100 (percent)
194
+ opacity: number; // 0–100 (percent)
195
+ }
196
+
197
+ interface GradientValue {
198
+ type: GradientType;
199
+ angle: number; // Degrees; ignored for "radial"
200
+ stops: GradientStop[];
201
+ }
202
+
203
+ interface GradientPickerChangeEvent {
204
+ value: GradientValue;
205
+ css: string; // e.g. "linear-gradient(0deg, #D9D9D9 0%, #22A8C3 100%)"
206
+ }
207
+ ```
208
+
209
+ ### Exported helpers
210
+
211
+ Every gradient operation is a pure function, so a consuming surface can render
212
+ or transform a gradient without mounting the component.
213
+
214
+ | Helper | Signature | Description |
215
+ | :------------------------------------ | :--------------------------------------------------------------- | :-------------------------------------------------------------------------------- |
216
+ | `toCssGradient(value)` | `(value: GradientValue) => string` | Serialises to `linear-gradient()` / `radial-gradient()` / `conic-gradient()`. |
217
+ | `toPreviewCssGradient(value)` | `(value: GradientValue) => string` | Left-to-right ramp used by the preview track, regardless of gradient type. |
218
+ | `interpolateColorAt(stops, position)` | `(stops: GradientStop[], position: number) => { color, opacity }` | Samples the gradient — the colour a stop added at `position` inherits. |
219
+ | `addStopAt(stops, position, max)` | `(…) => GradientStop[]` | Adds an interpolated stop; returns the input array unchanged at `max`. |
220
+ | `removeStop(stops, id, min)` | `(…) => GradientStop[]` | Removes by id; returns the input array unchanged at `min`. |
221
+ | `updateStop(stops, id, patch)` | `(…) => GradientStop[]` | Applies a clamped, normalised patch to one stop. |
222
+ | `sortStops(stops)` | `(stops: GradientStop[]) => GradientStop[]` | Position order, stable on ties, non-mutating. |
223
+ | `supportsAngle(type)` | `(type: GradientType) => boolean` | `false` for `radial` — the angle field is hidden for it. |
224
+ | `DEFAULT_GRADIENT` | `GradientValue` | The two-stop `#D9D9D9 → #22A8C3` linear ramp from the Figma component. |
225
+
226
+ ## CSS output
227
+
228
+ | Type | Output |
229
+ | :-------- | :-------------------------------------------------------------- |
230
+ | `linear` | `linear-gradient(<angle>deg, <stops>)` |
231
+ | `radial` | `radial-gradient(circle, <stops>)` |
232
+ | `angular` | `conic-gradient(from <angle>deg, <stops>)` |
233
+
234
+ A fully opaque stop serialises to its hex value; a partially transparent stop
235
+ serialises to `rgba()`. A gradient with a single stop is emitted twice (`0%` and
236
+ `100%`) because CSS gradients require at least two colour stops.
237
+
238
+ ## Keyboard navigation
239
+
240
+ | Key | Action |
241
+ | :------------------------ | :------------------------------------------------ |
242
+ | Tab / Shift+Tab | Move focus between markers, fields and buttons |
243
+ | ← / → (marker focused) | Move the stop by 1% |
244
+ | Shift+← / Shift+→ | Move the stop by 10% |
245
+ | Home / End | Jump the stop to 0% / 100% |
246
+ | Enter / Space | Activate the stop and open its ColorPicker |
247
+ | Delete / Backspace | Remove the stop (blocked at `minStops`) |
248
+ | Escape | Close the ColorPicker; focus returns to the marker |
249
+
250
+ ## Theme
251
+
252
+ - The panel background comes from the `layer/float` colour token (`theme.colors.layer.float`) so it reads as a floating surface in both light and dark mode, matching ColorPicker.
253
+ - Corner radius comes from `theme.shape.contextMenu.lg.borderRadius`.
254
+ - Stop markers use `theme.colors.background.primary` for their ring so the stop colour stays legible against any track fill.
255
+
256
+ ## Accessibility
257
+
258
+ - Each stop marker is a `role="slider"` with `aria-label="Stop N position"`, `aria-valuenow`, `aria-valuemin="0"`, `aria-valuemax="100"` and `aria-valuetext="N%"`.
259
+ - The preview track is `aria-hidden="true"` and is not focusable — position is always available numerically from the per-stop position field and the marker's `aria-valuetext`.
260
+ - The **+** button is the keyboard-accessible alternative to clicking the track; it drops the new stop in the widest gap.
261
+ - Closing the ColorPicker (Escape) returns focus to the marker that opened it.
262
+ - The angle field and every per-stop field carry an explicit `aria-label`.
263
+
264
+ ## Known gaps
265
+
266
+ These are deliberate v1 boundaries, tracked as follow-ups:
267
+
268
+ - **Type selector naming** — `SelectProps` has no `aria-label`, so the accessible
269
+ name for the gradient-type selector is carried by a wrapping
270
+ `role="group"` element. Once Select accepts `aria-label`, move it onto the
271
+ combobox itself.
272
+ - **ColorPicker placement** — the active-stop ColorPicker renders inline below
273
+ the stop list. The spec's "flip above the track when the panel would leave the
274
+ viewport" behaviour needs a floating-popover layer.
275
+ - **Pointer drag is web-only** — keyboard operation works everywhere; marker
276
+ dragging uses web mouse events. React Native `PanResponder` parity is a
277
+ follow-up, matching the approach `Slider` takes.
278
+ - **Radial centre point / angular start point** are not exposed. They are not in
279
+ the Figma component; the behaviour spec lists them as part of a fuller
280
+ implementation.
@@ -0,0 +1,243 @@
1
+ import React from 'react';
2
+ import { ThemeOverrideProps } from '@xsolla/xui-core';
3
+
4
+ /**
5
+ * Supported gradient geometries.
6
+ *
7
+ * `angular` maps to the CSS `conic-gradient()` function. Some products call
8
+ * this "Conic" — use `typeLabels` to relabel it without changing the value.
9
+ */
10
+ type GradientType = "linear" | "radial" | "angular";
11
+ /**
12
+ * A single colour stop on the gradient track.
13
+ */
14
+ interface GradientStop {
15
+ /**
16
+ * Stable identity for the stop. Used as the React key and as the handle for
17
+ * update / remove operations, so it must survive reordering.
18
+ */
19
+ id: string;
20
+ /**
21
+ * Stop colour as a `#RRGGBB` hex string. Opacity is tracked separately in
22
+ * `opacity` so the hex field stays human-editable.
23
+ */
24
+ color: string;
25
+ /**
26
+ * Position along the track, `0`–`100` (percent).
27
+ */
28
+ position: number;
29
+ /**
30
+ * Stop opacity, `0`–`100` (percent).
31
+ */
32
+ opacity: number;
33
+ }
34
+ /**
35
+ * The full gradient definition rendered by the picker.
36
+ */
37
+ interface GradientValue {
38
+ /**
39
+ * Gradient geometry.
40
+ */
41
+ type: GradientType;
42
+ /**
43
+ * Rotation in degrees. Only meaningful for `linear` and `angular` — a radial
44
+ * gradient has no angle, so the angle field is hidden for it.
45
+ */
46
+ angle: number;
47
+ /**
48
+ * Colour stops. Order is not significant: the component sorts by `position`
49
+ * when serialising, so stops may swap as the user drags them past each other.
50
+ */
51
+ stops: GradientStop[];
52
+ }
53
+ /**
54
+ * Payload emitted on every gradient change.
55
+ */
56
+ interface GradientPickerChangeEvent {
57
+ /**
58
+ * The new gradient definition.
59
+ */
60
+ value: GradientValue;
61
+ /**
62
+ * The same gradient serialised as a CSS-compatible string, ready to drop into
63
+ * a `background` / `background-image` declaration.
64
+ */
65
+ css: string;
66
+ }
67
+ interface GradientPickerProps extends ThemeOverrideProps {
68
+ /**
69
+ * Controlled gradient value. Pair with `onChange`.
70
+ */
71
+ value?: GradientValue;
72
+ /**
73
+ * Initial gradient value for uncontrolled usage.
74
+ */
75
+ defaultValue?: GradientValue;
76
+ /**
77
+ * Called on every interaction — stop drag, colour edit, opacity edit,
78
+ * gradient-type switch, angle change, add / remove stop.
79
+ */
80
+ onChange?: (event: GradientPickerChangeEvent) => void;
81
+ /**
82
+ * Gradient types offered in the type selector, in display order.
83
+ * @default ["linear", "radial", "angular"]
84
+ */
85
+ gradientTypes?: GradientType[];
86
+ /**
87
+ * Overrides for the gradient-type option labels — e.g. `{ angular: "Conic gradient" }`
88
+ * when the product uses the CSS term.
89
+ */
90
+ typeLabels?: Partial<Record<GradientType, string>>;
91
+ /**
92
+ * Smallest number of stops the user may reduce the gradient to. The remove
93
+ * control is disabled once this floor is reached.
94
+ * @default 1
95
+ */
96
+ minStops?: number;
97
+ /**
98
+ * Largest number of stops the user may add. The add control is disabled once
99
+ * this ceiling is reached.
100
+ * @default 5
101
+ */
102
+ maxStops?: number;
103
+ /**
104
+ * Disables every control and blocks track interaction.
105
+ */
106
+ disabled?: boolean;
107
+ /**
108
+ * Accessible label for the gradient-type selector.
109
+ * @default "Gradient type"
110
+ */
111
+ typeAriaLabel?: string;
112
+ /**
113
+ * Accessible label for the angle field.
114
+ * @default "Gradient angle"
115
+ */
116
+ angleAriaLabel?: string;
117
+ /**
118
+ * Heading rendered above the stop list.
119
+ * @default "Stops"
120
+ */
121
+ stopsLabel?: string;
122
+ testID?: string;
123
+ }
124
+
125
+ /**
126
+ * A compound control for defining a CSS gradient.
127
+ *
128
+ * Combines a live preview track carrying draggable stop markers with a per-stop
129
+ * row editor (position, colour, opacity) and an integrated `ColorPicker` for
130
+ * the active stop. Supports linear, radial and angular (CSS `conic`) gradients
131
+ * and 1–5 colour stops.
132
+ *
133
+ * Every interaction updates the preview immediately — there is no confirm step —
134
+ * and the gradient is emitted both as structured data and as a ready-to-apply
135
+ * CSS string.
136
+ *
137
+ * @example
138
+ * ```tsx
139
+ * const [gradient, setGradient] = useState<GradientValue>();
140
+ *
141
+ * <GradientPicker
142
+ * value={gradient}
143
+ * onChange={({ value, css }) => {
144
+ * setGradient(value);
145
+ * setBackground(css); // e.g. "linear-gradient(0deg, #D9D9D9 0%, #22A8C3 100%)"
146
+ * }}
147
+ * />
148
+ * ```
149
+ */
150
+ declare const GradientPicker: React.FC<GradientPickerProps>;
151
+
152
+ interface GradientStopMarkerProps extends ThemeOverrideProps {
153
+ /**
154
+ * The stop this marker represents.
155
+ */
156
+ stop: GradientStop;
157
+ /**
158
+ * 1-based index used to build the accessible name (`"Stop 2 position"`).
159
+ */
160
+ index: number;
161
+ /**
162
+ * Whether this stop is the one currently being edited in the ColorPicker.
163
+ */
164
+ active?: boolean;
165
+ /**
166
+ * Whether the whole picker is disabled.
167
+ */
168
+ disabled?: boolean;
169
+ /**
170
+ * Pointer-down on the marker — the parent owns the drag because it owns the
171
+ * track geometry.
172
+ */
173
+ onDragStart?: (event: React.MouseEvent) => void;
174
+ /**
175
+ * Keyboard interaction on the marker. Handled by the parent so that arrow
176
+ * keys, Home/End, Enter/Space and Delete/Backspace share one implementation.
177
+ */
178
+ onKeyDown?: (event: React.KeyboardEvent) => void;
179
+ }
180
+ /**
181
+ * A single draggable handle on the gradient preview track.
182
+ *
183
+ * Exposed as `role="slider"` over the `0`–`100` position range so the stop can
184
+ * be moved with the keyboard alone, and so its numeric position is announced —
185
+ * the visual gradient must never be the only carrier of that information.
186
+ */
187
+ declare const GradientStopMarker: React.FC<GradientStopMarkerProps>;
188
+
189
+ /**
190
+ * Returns the stops ordered by position without mutating the input array.
191
+ * Ties keep their original relative order, so two stops parked on the same
192
+ * percent do not flicker while one of them is being dragged.
193
+ */
194
+ declare const sortStops: (stops: GradientStop[]) => GradientStop[];
195
+ /**
196
+ * Serialises the gradient to a CSS-compatible string usable as a `background`
197
+ * or `background-image` value.
198
+ */
199
+ declare const toCssGradient: (value: GradientValue) => string;
200
+ /**
201
+ * The gradient rendered inside the horizontal preview track. The track always
202
+ * reads left-to-right regardless of gradient type, so the user can see stop
203
+ * ordering while dragging — the type-specific rendering is what `toCssGradient`
204
+ * produces for the consuming surface.
205
+ */
206
+ declare const toPreviewCssGradient: (value: GradientValue) => string;
207
+ /**
208
+ * Whether the given gradient type exposes an angle control. Radial gradients
209
+ * have no rotation, so the angle field is hidden for them.
210
+ */
211
+ declare const supportsAngle: (value: GradientValue["type"]) => boolean;
212
+ /**
213
+ * Samples the gradient at `position` (`0`–`100`) and returns the interpolated
214
+ * colour + opacity. Used to give a newly added stop the colour the gradient
215
+ * already had at that point, so adding a stop never visibly changes the ramp.
216
+ */
217
+ declare const interpolateColorAt: (stops: GradientStop[], position: number) => {
218
+ color: string;
219
+ opacity: number;
220
+ };
221
+ /**
222
+ * Adds a stop at `position`, taking its colour from the gradient at that point.
223
+ * Returns the original array untouched when `maxStops` is already reached, so
224
+ * callers can compare by reference to detect a no-op.
225
+ */
226
+ declare const addStopAt: (stops: GradientStop[], position: number, maxStops: number) => GradientStop[];
227
+ /**
228
+ * Removes a stop by id. Returns the original array when the removal would drop
229
+ * below `minStops`, or when the id is unknown.
230
+ */
231
+ declare const removeStop: (stops: GradientStop[], id: string, minStops: number) => GradientStop[];
232
+ /**
233
+ * Applies a partial update to a single stop, clamping position and opacity and
234
+ * normalising the hex colour.
235
+ */
236
+ declare const updateStop: (stops: GradientStop[], id: string, patch: Partial<Omit<GradientStop, "id">>) => GradientStop[];
237
+ /**
238
+ * The default gradient — the two-stop `#D9D9D9 → #22A8C3` linear ramp from the
239
+ * Figma component.
240
+ */
241
+ declare const DEFAULT_GRADIENT: GradientValue;
242
+
243
+ export { DEFAULT_GRADIENT, GradientPicker, type GradientPickerChangeEvent, type GradientPickerProps, type GradientStop, GradientStopMarker, type GradientStopMarkerProps, type GradientType, type GradientValue, addStopAt, interpolateColorAt, removeStop, sortStops, supportsAngle, toCssGradient, toPreviewCssGradient, updateStop };