@ctrl-ui/react 0.8.20 → 0.9.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 +1 -0
- package/dist/action-bar.d.ts +1 -2
- package/dist/action-bar.js +7 -8
- package/dist/blocks/design-canvas-inspector.js +4 -1
- package/dist/blocks/file-explorer.js +1 -1
- package/dist/chat-message.js +4 -13
- package/dist/hooks/use-textarea-trigger-menu.d.ts +21 -3
- package/dist/hooks/use-textarea-trigger-menu.js +36 -40
- package/dist/hooks/use-user-ask.d.ts +1 -0
- package/dist/hooks/use-user-ask.js +5 -1
- package/dist/knob-contracts/audio-recorder-knobs.d.ts +1 -1
- package/dist/knob-contracts/audio-recorder-knobs.js +2 -1
- package/dist/knob-contracts/chart-knobs.d.ts +4 -0
- package/dist/knob-contracts/chart-knobs.js +24 -0
- package/dist/knob-contracts/choice-knobs.d.ts +1 -1
- package/dist/knob-contracts/choice-knobs.js +1 -0
- package/dist/knob-contracts/dockable-panel-knobs.d.ts +1 -1
- package/dist/knob-contracts/dockable-panel-knobs.js +2 -1
- package/dist/knob-contracts/emoji-picker-knobs.d.ts +1 -1
- package/dist/knob-contracts/emoji-picker-knobs.js +1 -0
- package/dist/knob-contracts/empty-knobs.d.ts +1 -1
- package/dist/knob-contracts/empty-knobs.js +2 -1
- package/dist/knob-contracts/icon-picker-knobs.d.ts +1 -1
- package/dist/knob-contracts/icon-picker-knobs.js +3 -1
- package/dist/knob-contracts/resizable-knobs.d.ts +1 -1
- package/dist/knob-contracts/resizable-knobs.js +2 -2
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +3 -1
- package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
- package/dist/knob-contracts/tabs-knobs.js +2 -1
- package/dist/knob-contracts/tree-knobs.d.ts +1 -1
- package/dist/knob-contracts/tree-knobs.js +2 -1
- package/dist/lib/color.d.ts +2 -6
- package/dist/lib/color.js +45 -28
- package/dist/lib/contrast.d.ts +6 -0
- package/dist/lib/contrast.js +33 -1
- package/dist/lib/gradient.d.ts +17 -0
- package/dist/lib/gradient.js +69 -0
- package/dist/markdown-editor/drag-handle.js +73 -10
- package/dist/markdown-editor/drag-preview.d.ts +3 -0
- package/dist/markdown-editor/drag-preview.js +31 -0
- package/dist/markdown-editor/extensions.d.ts +2 -2
- package/dist/markdown-editor/extensions.js +25 -3
- package/dist/markdown-editor/suggestions.js +5 -5
- package/dist/markdown-editor/task-item.d.ts +3 -0
- package/dist/markdown-editor/task-item.js +50 -0
- package/dist/markdown-editor/toolbar.js +122 -63
- package/dist/markdown-editor.js +3 -3
- package/dist/skin.d.ts +0 -1
- package/dist/styles/index.css +3 -2
- package/dist/styles/recipes/action-bar.css +1 -1
- package/dist/styles/recipes/activity.css +1 -1
- package/dist/styles/recipes/alert.css +9 -10
- package/dist/styles/recipes/app-shell-header.css +2 -2
- package/dist/styles/recipes/audio-recorder.css +15 -4
- package/dist/styles/recipes/audio-visualizer.css +4 -4
- package/dist/styles/recipes/avatar.css +3 -3
- package/dist/styles/recipes/badge.css +2 -2
- package/dist/styles/recipes/button.css +2 -5
- package/dist/styles/recipes/card.css +0 -2
- package/dist/styles/recipes/chart.css +378 -0
- package/dist/styles/recipes/chat-composer-attachment.css +3 -3
- package/dist/styles/recipes/chat-composer.css +3 -3
- package/dist/styles/recipes/chat-layout.css +2 -2
- package/dist/styles/recipes/chat-message-social.css +1 -1
- package/dist/styles/recipes/chat-message.css +1 -1
- package/dist/styles/recipes/choice.css +9 -3
- package/dist/styles/recipes/code-diff.css +1 -1
- package/dist/styles/recipes/code.css +1 -1
- package/dist/styles/recipes/color-picker-details.css +17 -11
- package/dist/styles/recipes/color-picker-values.css +17 -7
- package/dist/styles/recipes/color-picker.css +88 -70
- package/dist/styles/recipes/context.css +2 -2
- package/dist/styles/recipes/dockable-panel.css +9 -2
- package/dist/styles/recipes/dynamic-notification-motion.css +1 -55
- package/dist/styles/recipes/dynamic-notification.css +0 -1
- package/dist/styles/recipes/emoji-picker.css +35 -19
- package/dist/styles/recipes/empty.css +19 -14
- package/dist/styles/recipes/field-parts.css +2 -2
- package/dist/styles/recipes/field.css +6 -4
- package/dist/styles/recipes/filter-bar.css +10 -10
- package/dist/styles/recipes/flow.css +5 -3
- package/dist/styles/recipes/gradient-editor.css +8 -0
- package/dist/styles/recipes/icon-picker.css +45 -10
- package/dist/styles/recipes/inline-attachment.css +4 -4
- package/dist/styles/recipes/inline-citation.css +2 -2
- package/dist/styles/recipes/item.css +4 -4
- package/dist/styles/recipes/markdown-editor.css +35 -24
- package/dist/styles/recipes/markdown.css +23 -27
- package/dist/styles/recipes/page-layout.css +13 -11
- package/dist/styles/recipes/popup-controls.css +2 -2
- package/dist/styles/recipes/popup-lists.css +3 -3
- package/dist/styles/recipes/popup.css +11 -9
- package/dist/styles/recipes/range.css +4 -5
- package/dist/styles/recipes/resizable.css +15 -10
- package/dist/styles/recipes/resize-handle.css +2 -2
- package/dist/styles/recipes/scroll-area.css +1 -1
- package/dist/styles/recipes/sidebar-menu.css +5 -15
- package/dist/styles/recipes/sidebar-mobile.css +4 -4
- package/dist/styles/recipes/sidebar-parts.css +26 -1
- package/dist/styles/recipes/sidebar.css +18 -31
- package/dist/styles/recipes/skeleton.css +10 -5
- package/dist/styles/recipes/stepper.css +1 -1
- package/dist/styles/recipes/switch.css +12 -11
- package/dist/styles/recipes/table-of-contents.css +6 -8
- package/dist/styles/recipes/table.css +4 -4
- package/dist/styles/recipes/tabs.css +10 -5
- package/dist/styles/recipes/task-list.css +3 -3
- package/dist/styles/recipes/tree.css +10 -3
- package/dist/styles/recipes/user-ask-details.css +5 -4
- package/dist/styles/recipes/user-ask.css +5 -5
- package/dist/styles/theme.css +158 -177
- package/dist/ui/chart-cartesian.d.ts +801 -0
- package/dist/ui/chart-cartesian.js +420 -0
- package/dist/ui/chart-colors.d.ts +7 -0
- package/dist/ui/chart-colors.js +27 -0
- package/dist/ui/chart-curves.d.ts +7 -0
- package/dist/ui/chart-curves.js +87 -0
- package/dist/ui/chart-marks.d.ts +68 -0
- package/dist/ui/chart-marks.js +227 -0
- package/dist/ui/chart-polar.d.ts +103 -0
- package/dist/ui/chart-polar.js +124 -0
- package/dist/ui/chart-series.d.ts +36 -0
- package/dist/ui/chart-series.js +71 -0
- package/dist/ui/chart.d.ts +32 -0
- package/dist/ui/chart.js +257 -0
- package/dist/ui/color-picker-area.d.ts +16 -0
- package/dist/ui/color-picker-area.js +175 -0
- package/dist/ui/color-picker-context.d.ts +27 -0
- package/dist/ui/color-picker-context.js +87 -0
- package/dist/ui/color-picker-contrast.d.ts +20 -0
- package/dist/ui/color-picker-contrast.js +129 -0
- package/dist/ui/color-picker-sliders.d.ts +15 -0
- package/dist/ui/color-picker-sliders.js +146 -0
- package/dist/ui/color-picker-swatches.d.ts +23 -0
- package/dist/ui/color-picker-swatches.js +94 -0
- package/dist/ui/color-picker-values.d.ts +59 -0
- package/dist/ui/color-picker-values.js +244 -0
- package/dist/ui/color-picker.d.ts +15 -110
- package/dist/ui/color-picker.js +30 -759
- package/dist/ui/emoji-picker.d.ts +10 -1
- package/dist/ui/emoji-picker.js +71 -14
- package/dist/ui/flow.js +1 -1
- package/dist/ui/gradient-editor-controls.d.ts +19 -0
- package/dist/ui/gradient-editor-controls.js +75 -0
- package/dist/ui/gradient-editor.d.ts +23 -22
- package/dist/ui/gradient-editor.js +77 -123
- package/dist/ui/icon-picker.d.ts +1 -1
- package/dist/ui/icon-picker.js +11 -6
- package/dist/ui/markdown-elements.d.ts +3 -1
- package/dist/ui/markdown-elements.js +62 -22
- package/dist/ui/markdown-heading.d.ts +9 -0
- package/dist/ui/markdown-heading.js +25 -0
- package/dist/ui/resizable.js +24 -9
- package/dist/ui/sidebar-provider.js +3 -12
- package/dist/ui/typography.d.ts +1 -0
- package/dist/ui/typography.js +12 -3
- package/dist/user-ask.js +4 -8
- package/package.json +7 -3
- package/dist/ui/emoji-icon-picker.d.ts +0 -13
- package/dist/ui/emoji-icon-picker.js +0 -50
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { EmojiPickerKnobStyle } from "../knob-contracts/emoji-picker-knobs.js";
|
|
2
|
+
import { IconPicker } from "./icon-picker.js";
|
|
3
|
+
import { Tabs, TabsList } from "./tabs.js";
|
|
2
4
|
import { CSSProperties, ComponentProps } from "react";
|
|
3
5
|
import { Emoji, EmojiPicker as EmojiPicker$1 } from "frimousse";
|
|
4
6
|
//#region src/ui/emoji-picker.d.ts
|
|
@@ -21,9 +23,16 @@ export declare function EmojiPickerRecent({ emojis, label, ...props }: EmojiPick
|
|
|
21
23
|
export type EmojiPickerSearchProps = Omit<ComponentProps<typeof EmojiPicker$1.Search>, "style"> & EmojiPickerStyle;
|
|
22
24
|
export declare function EmojiPickerSearch({ className, placeholder, "aria-label": ariaLabel, ...props }: EmojiPickerSearchProps): import("react").JSX.Element;
|
|
23
25
|
export type EmojiPickerContentProps = Omit<ComponentProps<typeof EmojiPicker$1.Viewport>, "style"> & EmojiPickerStyle;
|
|
24
|
-
export declare function EmojiPickerContent({ className, ref, ...props }: EmojiPickerContentProps): import("react").JSX.Element;
|
|
26
|
+
export declare function EmojiPickerContent({ className, ref, children, ...props }: EmojiPickerContentProps): import("react").JSX.Element;
|
|
25
27
|
export type EmojiPickerFooterProps = Omit<ComponentProps<"div">, "style" | "children"> & EmojiPickerStyle & {
|
|
26
28
|
placeholder?: string;
|
|
27
29
|
};
|
|
28
30
|
export declare function EmojiPickerFooter({ className, placeholder, ...props }: EmojiPickerFooterProps): import("react").JSX.Element;
|
|
31
|
+
export declare function EmojiIconPicker({ children, defaultValue, ...props }: ComponentProps<typeof Tabs<"emoji" | "icons">>): import("react").JSX.Element;
|
|
32
|
+
export declare function EmojiIconPickerTabs({ emojiLabel, iconsLabel, ...props }: Omit<ComponentProps<typeof TabsList>, "children"> & {
|
|
33
|
+
emojiLabel?: string;
|
|
34
|
+
iconsLabel?: string;
|
|
35
|
+
}): import("react").JSX.Element;
|
|
36
|
+
export declare function EmojiIconPickerEmoji(props: ComponentProps<typeof EmojiPicker>): import("react").JSX.Element;
|
|
37
|
+
export declare function EmojiIconPickerIcons(props: ComponentProps<typeof IconPicker>): import("react").JSX.Element;
|
|
29
38
|
//#endregion
|
package/dist/ui/emoji-picker.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { ScrollArea } from "./scroll-area.js";
|
|
3
4
|
import { Spinner } from "./spinner.js";
|
|
5
|
+
import { PopoverViewport } from "./popover.js";
|
|
6
|
+
import { IconPicker } from "./icon-picker.js";
|
|
7
|
+
import { Tabs, TabsList, TabsPanel, TabsTab } from "./tabs.js";
|
|
4
8
|
import { Toolbar } from "@base-ui/react/toolbar";
|
|
5
9
|
import { createContext, useContext, useImperativeHandle, useRef, useState } from "react";
|
|
6
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -16,6 +20,7 @@ function useEmojiPicker() {
|
|
|
16
20
|
function EmojiPicker({ className, columns = 8, style, ref, onEmojiSelect, resolveEmojiData = defaultEmojiDataResolver, ...props }) {
|
|
17
21
|
const rootRef = useRef(null);
|
|
18
22
|
const viewportRef = useRef(null);
|
|
23
|
+
const listRef = useRef(null);
|
|
19
24
|
const [loadState, setLoadState] = useState({ status: "loading" });
|
|
20
25
|
const [retryAttempt, setRetryAttempt] = useState(0);
|
|
21
26
|
useImperativeHandle(ref, () => {
|
|
@@ -50,6 +55,7 @@ function EmojiPicker({ className, columns = 8, style, ref, onEmojiSelect, resolv
|
|
|
50
55
|
columns,
|
|
51
56
|
rootRef,
|
|
52
57
|
viewportRef,
|
|
58
|
+
listRef,
|
|
53
59
|
loadState,
|
|
54
60
|
retryEmojiData,
|
|
55
61
|
selectEmoji
|
|
@@ -96,17 +102,18 @@ function emojiCategoryRows(emojiData, columns) {
|
|
|
96
102
|
});
|
|
97
103
|
}
|
|
98
104
|
function EmojiPickerCategories({ "aria-label": ariaLabel = "Emoji categories", onKeyDown, ...props }) {
|
|
99
|
-
const { columns, loadState, rootRef, viewportRef } = useEmojiPicker();
|
|
105
|
+
const { columns, loadState, rootRef, viewportRef, listRef } = useEmojiPicker();
|
|
100
106
|
if (loadState.status !== "ready") return null;
|
|
101
107
|
const categories = emojiCategoryRows(loadState.data, columns);
|
|
102
108
|
const scrollToCategory = (startRow, categoryIndex) => {
|
|
103
109
|
const root = rootRef.current;
|
|
104
110
|
const viewport = viewportRef.current;
|
|
105
|
-
|
|
111
|
+
const list = listRef.current;
|
|
112
|
+
if (!root || !viewport || !list) return;
|
|
106
113
|
const metrics = getComputedStyle(root);
|
|
107
114
|
const rowHeight = Number.parseFloat(metrics.getPropertyValue("--frimousse-row-height"));
|
|
108
115
|
const headerHeight = Number.parseFloat(metrics.getPropertyValue("--frimousse-category-header-height"));
|
|
109
|
-
viewport.scrollTo({ top: startRow * rowHeight + categoryIndex * headerHeight });
|
|
116
|
+
viewport.scrollTo({ top: list.offsetTop + startRow * rowHeight + categoryIndex * headerHeight });
|
|
110
117
|
};
|
|
111
118
|
return /* @__PURE__ */ jsx(Toolbar.Root, {
|
|
112
119
|
"data-control-ui": "emoji-picker",
|
|
@@ -204,7 +211,7 @@ function EmojiPickerRow({ children, className, ...props }) {
|
|
|
204
211
|
"data-control-ui": "emoji-picker",
|
|
205
212
|
"data-control-family": "emoji-picker",
|
|
206
213
|
"data-slot": "row",
|
|
207
|
-
className
|
|
214
|
+
className,
|
|
208
215
|
...props,
|
|
209
216
|
children
|
|
210
217
|
});
|
|
@@ -231,19 +238,23 @@ function EmojiPickerCategoryHeader({ category, className, ...props }) {
|
|
|
231
238
|
children: category.label
|
|
232
239
|
});
|
|
233
240
|
}
|
|
234
|
-
function EmojiPickerContent({ className, ref, ...props }) {
|
|
235
|
-
const { viewportRef, loadState, retryEmojiData } = useEmojiPicker();
|
|
241
|
+
function EmojiPickerContent({ className, ref, children, ...props }) {
|
|
242
|
+
const { viewportRef, listRef, loadState, retryEmojiData } = useEmojiPicker();
|
|
236
243
|
useImperativeHandle(ref, () => {
|
|
237
244
|
if (!viewportRef.current) throw new Error("EmojiPicker viewport is not mounted.");
|
|
238
245
|
return viewportRef.current;
|
|
239
246
|
});
|
|
240
|
-
return /* @__PURE__ */ jsx(
|
|
241
|
-
|
|
242
|
-
"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
return /* @__PURE__ */ jsx(ScrollArea, {
|
|
248
|
+
lockAxis: "x",
|
|
249
|
+
className: cn("min-h-0 flex-1", className),
|
|
250
|
+
viewportRef,
|
|
251
|
+
viewportProps: {
|
|
252
|
+
"data-control-ui": "emoji-picker",
|
|
253
|
+
"data-control-family": "emoji-picker",
|
|
254
|
+
"data-slot": "content",
|
|
255
|
+
...props,
|
|
256
|
+
render: renderEmojiViewport
|
|
257
|
+
},
|
|
247
258
|
children: loadState.status === "error" ? /* @__PURE__ */ jsxs("div", {
|
|
248
259
|
"data-control-ui": "emoji-picker",
|
|
249
260
|
"data-control-family": "emoji-picker",
|
|
@@ -255,6 +266,7 @@ function EmojiPickerContent({ className, ref, ...props }) {
|
|
|
255
266
|
children: "Try again"
|
|
256
267
|
})]
|
|
257
268
|
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
269
|
+
children,
|
|
258
270
|
/* @__PURE__ */ jsx(EmojiPicker$1.Loading, {
|
|
259
271
|
"data-control-ui": "emoji-picker",
|
|
260
272
|
"data-control-family": "emoji-picker",
|
|
@@ -274,6 +286,7 @@ function EmojiPickerContent({ className, ref, ...props }) {
|
|
|
274
286
|
"data-control-family": "emoji-picker",
|
|
275
287
|
"data-slot": "list",
|
|
276
288
|
className: "select-none",
|
|
289
|
+
ref: listRef,
|
|
277
290
|
components: {
|
|
278
291
|
Row: EmojiPickerRow,
|
|
279
292
|
Emoji: EmojiPickerEmoji,
|
|
@@ -283,6 +296,9 @@ function EmojiPickerContent({ className, ref, ...props }) {
|
|
|
283
296
|
] })
|
|
284
297
|
});
|
|
285
298
|
}
|
|
299
|
+
function renderEmojiViewport(viewportProps) {
|
|
300
|
+
return /* @__PURE__ */ jsx(EmojiPicker$1.Viewport, { ...viewportProps });
|
|
301
|
+
}
|
|
286
302
|
function EmojiPickerFooter({ className, placeholder = "Pick an emoji…", ...props }) {
|
|
287
303
|
return /* @__PURE__ */ jsx("div", {
|
|
288
304
|
"data-control-ui": "emoji-picker",
|
|
@@ -311,5 +327,46 @@ function EmojiPickerFooter({ className, placeholder = "Pick an emoji…", ...pro
|
|
|
311
327
|
}) })
|
|
312
328
|
});
|
|
313
329
|
}
|
|
330
|
+
function EmojiIconPicker({ children, defaultValue = "emoji", ...props }) {
|
|
331
|
+
return /* @__PURE__ */ jsx(Tabs, {
|
|
332
|
+
"data-control-ui": "emoji-icon-picker",
|
|
333
|
+
"data-control-family": "tabs",
|
|
334
|
+
"data-slot": "root",
|
|
335
|
+
defaultValue,
|
|
336
|
+
...props,
|
|
337
|
+
children: /* @__PURE__ */ jsx(PopoverViewport, { children })
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
function EmojiIconPickerTabs({ emojiLabel = "Emoji", iconsLabel = "Icons", ...props }) {
|
|
341
|
+
return /* @__PURE__ */ jsxs(TabsList, {
|
|
342
|
+
size: "xs",
|
|
343
|
+
className: "mx-2 mt-2",
|
|
344
|
+
"aria-label": "Choose emoji or icon",
|
|
345
|
+
...props,
|
|
346
|
+
children: [/* @__PURE__ */ jsx(TabsTab, {
|
|
347
|
+
value: "emoji",
|
|
348
|
+
children: emojiLabel
|
|
349
|
+
}), /* @__PURE__ */ jsx(TabsTab, {
|
|
350
|
+
value: "icons",
|
|
351
|
+
children: iconsLabel
|
|
352
|
+
})]
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function EmojiIconPickerEmoji(props) {
|
|
356
|
+
return /* @__PURE__ */ jsx(TabsPanel, {
|
|
357
|
+
value: "emoji",
|
|
358
|
+
"data-slide": void 0,
|
|
359
|
+
className: "mt-0",
|
|
360
|
+
children: /* @__PURE__ */ jsx(EmojiPicker, { ...props })
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
function EmojiIconPickerIcons(props) {
|
|
364
|
+
return /* @__PURE__ */ jsx(TabsPanel, {
|
|
365
|
+
value: "icons",
|
|
366
|
+
"data-slide": void 0,
|
|
367
|
+
className: "mt-0",
|
|
368
|
+
children: /* @__PURE__ */ jsx(IconPicker, { ...props })
|
|
369
|
+
});
|
|
370
|
+
}
|
|
314
371
|
//#endregion
|
|
315
|
-
export { EmojiPicker, EmojiPickerCategories, EmojiPickerContent, EmojiPickerFooter, EmojiPickerReactions, EmojiPickerRecent, EmojiPickerSearch };
|
|
372
|
+
export { EmojiIconPicker, EmojiIconPickerEmoji, EmojiIconPickerIcons, EmojiIconPickerTabs, EmojiPicker, EmojiPickerCategories, EmojiPickerContent, EmojiPickerFooter, EmojiPickerReactions, EmojiPickerRecent, EmojiPickerSearch };
|
package/dist/ui/flow.js
CHANGED
|
@@ -146,7 +146,7 @@ function FlowEdgeLabelChip({ className, ...props }) {
|
|
|
146
146
|
"data-control-ui": "flow",
|
|
147
147
|
"data-control-family": "flow",
|
|
148
148
|
"data-slot": "edge-label-chip",
|
|
149
|
-
className: cn("
|
|
149
|
+
className: cn("max-w-40 truncate", className)
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
//#endregion
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ControlSize } from "../control-variants.js";
|
|
2
|
+
//#region src/ui/gradient-editor-controls.d.ts
|
|
3
|
+
type GradientEditorSelectProps = {
|
|
4
|
+
size?: ControlSize;
|
|
5
|
+
className?: string;
|
|
6
|
+
"aria-label"?: string;
|
|
7
|
+
"aria-labelledby"?: string;
|
|
8
|
+
};
|
|
9
|
+
export type GradientEditorTypeSelectProps = GradientEditorSelectProps;
|
|
10
|
+
export type GradientEditorInterpolationSelectProps = GradientEditorSelectProps;
|
|
11
|
+
export type GradientEditorAngleProps = {
|
|
12
|
+
size?: ControlSize;
|
|
13
|
+
className?: string;
|
|
14
|
+
"aria-label"?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function GradientEditorTypeSelect(props: GradientEditorTypeSelectProps): import("react").JSX.Element;
|
|
17
|
+
export declare function GradientEditorInterpolationSelect(props: GradientEditorInterpolationSelectProps): import("react").JSX.Element;
|
|
18
|
+
export declare function GradientEditorAngle({ size, className, "aria-label": ariaLabel }: GradientEditorAngleProps): import("react").JSX.Element | null;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
|
|
3
|
+
import { NumberField, NumberFieldGroup, NumberFieldInput, NumberFieldScrubArea } from "./number-field.js";
|
|
4
|
+
import { useGradientEditor } from "./gradient-editor.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/ui/gradient-editor-controls.tsx
|
|
7
|
+
const GRADIENT_TYPE_LABELS = {
|
|
8
|
+
linear: "Linear",
|
|
9
|
+
radial: "Radial",
|
|
10
|
+
conic: "Conic"
|
|
11
|
+
};
|
|
12
|
+
const GRADIENT_INTERPOLATION_LABELS = {
|
|
13
|
+
srgb: "sRGB",
|
|
14
|
+
oklab: "OKLab",
|
|
15
|
+
oklch: "OKLCH"
|
|
16
|
+
};
|
|
17
|
+
const WHOLE_DEGREES = { maximumFractionDigits: 0 };
|
|
18
|
+
function GradientEditorSelect({ value, onValueChange, labels, defaultLabel, size = "sm", className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) {
|
|
19
|
+
return /* @__PURE__ */ jsxs(Select, {
|
|
20
|
+
value,
|
|
21
|
+
onValueChange,
|
|
22
|
+
items: labels,
|
|
23
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
24
|
+
size,
|
|
25
|
+
"aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? defaultLabel : ariaLabel,
|
|
26
|
+
"aria-labelledby": ariaLabelledBy,
|
|
27
|
+
className,
|
|
28
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
29
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: Object.entries(labels).map(([option, label]) => /* @__PURE__ */ jsx(SelectItem, {
|
|
30
|
+
value: option,
|
|
31
|
+
children: label
|
|
32
|
+
}, option)) })]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function GradientEditorTypeSelect(props) {
|
|
36
|
+
const { type, setType } = useGradientEditor();
|
|
37
|
+
return /* @__PURE__ */ jsx(GradientEditorSelect, {
|
|
38
|
+
value: type,
|
|
39
|
+
onValueChange: setType,
|
|
40
|
+
labels: GRADIENT_TYPE_LABELS,
|
|
41
|
+
defaultLabel: "Gradient type",
|
|
42
|
+
...props
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function GradientEditorInterpolationSelect(props) {
|
|
46
|
+
const { interpolation, setInterpolation } = useGradientEditor();
|
|
47
|
+
return /* @__PURE__ */ jsx(GradientEditorSelect, {
|
|
48
|
+
value: interpolation,
|
|
49
|
+
onValueChange: setInterpolation,
|
|
50
|
+
labels: GRADIENT_INTERPOLATION_LABELS,
|
|
51
|
+
defaultLabel: "Gradient color space",
|
|
52
|
+
...props
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function GradientEditorAngle({ size = "sm", className, "aria-label": ariaLabel = "Gradient angle" }) {
|
|
56
|
+
const { type, angle, setAngle } = useGradientEditor();
|
|
57
|
+
if (type === "radial") return null;
|
|
58
|
+
return /* @__PURE__ */ jsx(NumberField, {
|
|
59
|
+
size,
|
|
60
|
+
className,
|
|
61
|
+
value: angle,
|
|
62
|
+
min: 0,
|
|
63
|
+
max: 360,
|
|
64
|
+
format: WHOLE_DEGREES,
|
|
65
|
+
onValueChange: (next) => {
|
|
66
|
+
if (next !== null) setAngle(next);
|
|
67
|
+
},
|
|
68
|
+
children: /* @__PURE__ */ jsxs(NumberFieldGroup, {
|
|
69
|
+
className: "w-full",
|
|
70
|
+
children: [/* @__PURE__ */ jsx(NumberFieldInput, { "aria-label": ariaLabel }), /* @__PURE__ */ jsx(NumberFieldScrubArea, { children: "°" })]
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { GradientEditorAngle, GradientEditorInterpolationSelect, GradientEditorTypeSelect };
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { ControlSize } from "../control-variants.js";
|
|
2
1
|
import { GradientEditorKnobStyle } from "../knob-contracts/gradient-editor-knobs.js";
|
|
3
|
-
import {
|
|
2
|
+
import { GradientInterpolation, GradientStop, GradientType, GradientValue } from "../lib/gradient.js";
|
|
3
|
+
import { CSSProperties, ComponentProps, RefObject } from "react";
|
|
4
4
|
//#region src/ui/gradient-editor.d.ts
|
|
5
|
-
export type GradientType = "linear" | "radial" | "conic";
|
|
6
|
-
export type GradientStop = {
|
|
7
|
-
id: string;
|
|
8
|
-
position: number;
|
|
9
|
-
color: string;
|
|
10
|
-
};
|
|
11
5
|
export type GradientEditorProps = Omit<ComponentProps<"div">, "onChange" | "defaultValue"> & {
|
|
12
|
-
value?:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
defaultAngle?: number;
|
|
16
|
-
onValueChange?: (value: string) => void;
|
|
6
|
+
value?: GradientValue;
|
|
7
|
+
defaultValue?: GradientValue;
|
|
8
|
+
onValueChange?: (value: GradientValue) => void;
|
|
17
9
|
} & {
|
|
18
10
|
style?: CSSProperties & GradientEditorKnobStyle;
|
|
19
11
|
};
|
|
@@ -30,17 +22,26 @@ export type GradientEditorStopProps = Omit<ComponentProps<"button">, "style"> &
|
|
|
30
22
|
export type GradientEditorStopAddProps = Omit<ComponentProps<"button">, "onClick" | "style"> & {
|
|
31
23
|
style?: CSSProperties & GradientEditorKnobStyle;
|
|
32
24
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
type GradientEditorContextValue = GradientValue & {
|
|
26
|
+
gradient: string;
|
|
27
|
+
selectedStop: GradientStop | undefined;
|
|
28
|
+
canRemoveStop: boolean;
|
|
29
|
+
trackRef: RefObject<HTMLFieldSetElement | null>;
|
|
30
|
+
stopNodes: Map<string, HTMLButtonElement>;
|
|
31
|
+
select: (id: string) => void;
|
|
32
|
+
setStopColor: (id: string, color: string) => void;
|
|
33
|
+
setStopPosition: (id: string, position: number) => void;
|
|
34
|
+
addStop: (position: number) => void;
|
|
35
|
+
removeStop: (id: string) => void;
|
|
36
|
+
setType: (type: GradientType) => void;
|
|
37
|
+
setAngle: (angle: number) => void;
|
|
38
|
+
setInterpolation: (interpolation: GradientInterpolation) => void;
|
|
38
39
|
};
|
|
39
|
-
export declare function
|
|
40
|
+
export declare function useGradientEditor(): GradientEditorContextValue;
|
|
41
|
+
export declare function GradientEditor({ value: controlledValue, defaultValue, onValueChange, className, children, ...props }: GradientEditorProps): import("react").JSX.Element;
|
|
40
42
|
export declare function GradientEditorPreview({ className, style, "aria-label": ariaLabel, ...props }: GradientEditorPreviewProps): import("react").JSX.Element;
|
|
41
43
|
export declare function GradientEditorTrack({ className, children, style, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: GradientEditorTrackProps): import("react").JSX.Element;
|
|
42
44
|
export declare function GradientEditorStop({ stop, className, style, onPointerDown, onKeyDown, onFocus, onDoubleClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ref, ...props }: GradientEditorStopProps): import("react").JSX.Element;
|
|
43
45
|
export declare function GradientEditorStopAdd({ className, children, ...props }: GradientEditorStopAddProps): import("react").JSX.Element;
|
|
44
|
-
|
|
45
|
-
export
|
|
46
|
-
//#endregion
|
|
46
|
+
//#endregion
|
|
47
|
+
export type { GradientInterpolation, GradientStop, GradientType, GradientValue };
|
|
@@ -1,85 +1,86 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
|
|
4
3
|
import { useColorArea } from "../hooks/use-color-area.js";
|
|
5
|
-
import { formatGradient } from "../lib/
|
|
6
|
-
import { ColorPicker, ColorPickerAlpha, ColorPickerArea, ColorPickerContent, ColorPickerFormatSelect, ColorPickerHue, ColorPickerInput, ColorPickerTrigger } from "./color-picker.js";
|
|
4
|
+
import { formatGradient, gradientColorAt } from "../lib/gradient.js";
|
|
7
5
|
import { createContext, useContext, useRef, useState } from "react";
|
|
8
|
-
import { jsx
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
7
|
//#region src/ui/gradient-editor.tsx
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
8
|
+
const DEFAULT_GRADIENT = {
|
|
9
|
+
type: "linear",
|
|
10
|
+
angle: 90,
|
|
11
|
+
interpolation: "oklab",
|
|
12
|
+
stops: [{
|
|
13
|
+
id: "stop-1",
|
|
14
|
+
position: 0,
|
|
15
|
+
color: "#7c3aed"
|
|
16
|
+
}, {
|
|
17
|
+
id: "stop-2",
|
|
18
|
+
position: 1,
|
|
19
|
+
color: "#3b82f6"
|
|
20
|
+
}]
|
|
21
|
+
};
|
|
22
|
+
const MIN_GRADIENT_STOPS = 2;
|
|
20
23
|
const clamp01 = (n) => Math.min(1, Math.max(0, n));
|
|
24
|
+
function unusedStopId(stops) {
|
|
25
|
+
const taken = new Set(stops.map((stop) => stop.id));
|
|
26
|
+
let ordinal = stops.length + 1;
|
|
27
|
+
while (taken.has(`stop-${ordinal}`)) ordinal += 1;
|
|
28
|
+
return `stop-${ordinal}`;
|
|
29
|
+
}
|
|
21
30
|
const GradientEditorContext = createContext(null);
|
|
22
31
|
function useGradientEditor() {
|
|
23
32
|
const ctx = useContext(GradientEditorContext);
|
|
24
33
|
if (!ctx) throw new Error("GradientEditor parts must be rendered inside <GradientEditor>.");
|
|
25
34
|
return ctx;
|
|
26
35
|
}
|
|
27
|
-
function GradientEditor({
|
|
28
|
-
const [
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const [selectedId, setSelectedId] = useState(
|
|
32
|
-
const idCounter = useRef(defaultStops.length);
|
|
36
|
+
function GradientEditor({ value: controlledValue, defaultValue = DEFAULT_GRADIENT, onValueChange, className, children, ...props }) {
|
|
37
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
38
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
39
|
+
const { stops } = value;
|
|
40
|
+
const [selectedId, setSelectedId] = useState(stops[0]?.id);
|
|
33
41
|
const trackRef = useRef(null);
|
|
34
42
|
const [stopNodes] = useState(() => /* @__PURE__ */ new Map());
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
function change(patch) {
|
|
44
|
+
const next = {
|
|
45
|
+
...value,
|
|
46
|
+
...patch
|
|
47
|
+
};
|
|
48
|
+
if (controlledValue === void 0) setUncontrolledValue(next);
|
|
49
|
+
onValueChange?.(next);
|
|
39
50
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
color
|
|
43
|
-
} : stop));
|
|
44
|
-
const setStopPosition = (id, position) => updateStops(stops.map((stop) => stop.id === id ? {
|
|
51
|
+
const canRemoveStop = stops.length > MIN_GRADIENT_STOPS;
|
|
52
|
+
const changeStop = (id, patch) => change({ stops: stops.map((stop) => stop.id === id ? {
|
|
45
53
|
...stop,
|
|
46
|
-
|
|
47
|
-
} : stop));
|
|
54
|
+
...patch
|
|
55
|
+
} : stop) });
|
|
48
56
|
const addStop = (position) => {
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
updateStops([...stops, {
|
|
57
|
+
const id = unusedStopId(stops);
|
|
58
|
+
const clamped = clamp01(position);
|
|
59
|
+
change({ stops: [...stops, {
|
|
53
60
|
id,
|
|
54
|
-
position:
|
|
55
|
-
color:
|
|
56
|
-
}]);
|
|
61
|
+
position: clamped,
|
|
62
|
+
color: gradientColorAt(value, clamped)
|
|
63
|
+
}] });
|
|
57
64
|
setSelectedId(id);
|
|
58
65
|
};
|
|
59
66
|
const removeStop = (id) => {
|
|
60
|
-
if (stops.
|
|
61
|
-
const nextStops = stops.filter((stop) => stop.id !== id);
|
|
62
|
-
updateStops(nextStops);
|
|
63
|
-
setSelectedId((current) => current === id ? nextStops[0]?.id ?? current : current);
|
|
64
|
-
};
|
|
65
|
-
const setType = (nextType) => {
|
|
66
|
-
setTypeState(nextType);
|
|
67
|
-
onValueChange?.(formatGradient(stops, nextType, angle));
|
|
67
|
+
if (canRemoveStop) change({ stops: stops.filter((stop) => stop.id !== id) });
|
|
68
68
|
};
|
|
69
69
|
const ctx = {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
gradient,
|
|
70
|
+
...value,
|
|
71
|
+
gradient: formatGradient(value),
|
|
72
|
+
selectedStop: stops.find((stop) => stop.id === selectedId) ?? stops[0],
|
|
73
|
+
canRemoveStop,
|
|
75
74
|
trackRef,
|
|
76
75
|
stopNodes,
|
|
77
76
|
select: setSelectedId,
|
|
78
|
-
setStopColor,
|
|
79
|
-
setStopPosition,
|
|
77
|
+
setStopColor: (id, color) => changeStop(id, { color }),
|
|
78
|
+
setStopPosition: (id, position) => changeStop(id, { position: clamp01(position) }),
|
|
80
79
|
addStop,
|
|
81
80
|
removeStop,
|
|
82
|
-
setType
|
|
81
|
+
setType: (type) => change({ type }),
|
|
82
|
+
setAngle: (angle) => change({ angle }),
|
|
83
|
+
setInterpolation: (interpolation) => change({ interpolation })
|
|
83
84
|
};
|
|
84
85
|
return /* @__PURE__ */ jsx(GradientEditorContext.Provider, {
|
|
85
86
|
value: ctx,
|
|
@@ -95,6 +96,10 @@ function GradientEditor({ defaultStops = DEFAULT_STOPS, defaultType = "linear",
|
|
|
95
96
|
}
|
|
96
97
|
function GradientEditorPreview({ className, style, "aria-label": ariaLabel = "Gradient preview", ...props }) {
|
|
97
98
|
const { gradient } = useGradientEditor();
|
|
99
|
+
const imageStyle = {
|
|
100
|
+
...style,
|
|
101
|
+
"--_gradient-editor-image": gradient
|
|
102
|
+
};
|
|
98
103
|
return /* @__PURE__ */ jsx("div", {
|
|
99
104
|
"data-control-ui": "gradient-editor",
|
|
100
105
|
"data-control-family": "gradient-editor",
|
|
@@ -102,16 +107,21 @@ function GradientEditorPreview({ className, style, "aria-label": ariaLabel = "Gr
|
|
|
102
107
|
role: "img",
|
|
103
108
|
"aria-label": ariaLabel,
|
|
104
109
|
className: cn("w-full", className),
|
|
105
|
-
style:
|
|
106
|
-
...style,
|
|
107
|
-
backgroundImage: gradient
|
|
108
|
-
},
|
|
110
|
+
style: imageStyle,
|
|
109
111
|
...props
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
function GradientEditorTrack({ className, children, style, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }) {
|
|
113
|
-
const { stops, trackRef, addStop } = useGradientEditor();
|
|
114
|
-
const
|
|
115
|
+
const { stops, interpolation, trackRef, addStop } = useGradientEditor();
|
|
116
|
+
const imageStyle = {
|
|
117
|
+
...style,
|
|
118
|
+
"--_gradient-editor-image": formatGradient({
|
|
119
|
+
type: "linear",
|
|
120
|
+
angle: 90,
|
|
121
|
+
interpolation,
|
|
122
|
+
stops
|
|
123
|
+
})
|
|
124
|
+
};
|
|
115
125
|
return /* @__PURE__ */ jsx("fieldset", {
|
|
116
126
|
ref: trackRef,
|
|
117
127
|
"data-control-ui": "gradient-editor",
|
|
@@ -120,12 +130,9 @@ function GradientEditorTrack({ className, children, style, "aria-label": ariaLab
|
|
|
120
130
|
"aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Gradient stops" : ariaLabel,
|
|
121
131
|
"aria-labelledby": ariaLabelledBy,
|
|
122
132
|
className: cn("relative m-0 min-w-0 w-full cursor-copy touch-pan-y p-0", className),
|
|
123
|
-
style:
|
|
124
|
-
...style,
|
|
125
|
-
backgroundImage: stripe
|
|
126
|
-
},
|
|
133
|
+
style: imageStyle,
|
|
127
134
|
onPointerDown: (event) => {
|
|
128
|
-
if (event.target
|
|
135
|
+
if (!(event.target === event.currentTarget)) return;
|
|
129
136
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
130
137
|
addStop((event.clientX - rect.left) / rect.width);
|
|
131
138
|
},
|
|
@@ -134,9 +141,7 @@ function GradientEditorTrack({ className, children, style, "aria-label": ariaLab
|
|
|
134
141
|
});
|
|
135
142
|
}
|
|
136
143
|
function GradientEditorStop({ stop, className, style, onPointerDown, onKeyDown, onFocus, onDoubleClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ref, ...props }) {
|
|
137
|
-
const { stops,
|
|
138
|
-
const selected = stop.id === selectedId;
|
|
139
|
-
const canRemove = stops.length > 2;
|
|
144
|
+
const { stops, selectedStop, canRemoveStop, select, setStopPosition, removeStop, trackRef, stopNodes } = useGradientEditor();
|
|
140
145
|
const { onPointerDown: startDrag } = useColorArea((offset, rect) => setStopPosition(stop.id, offset.x / rect.width), trackRef);
|
|
141
146
|
function handlePointerDown(event) {
|
|
142
147
|
onPointerDown?.(event);
|
|
@@ -157,7 +162,7 @@ function GradientEditorStop({ stop, className, style, onPointerDown, onKeyDown,
|
|
|
157
162
|
};
|
|
158
163
|
}
|
|
159
164
|
function remove() {
|
|
160
|
-
if (!
|
|
165
|
+
if (!canRemoveStop) return;
|
|
161
166
|
const index = stops.findIndex((candidate) => candidate.id === stop.id);
|
|
162
167
|
const neighbour = stops[index + 1] ?? stops[index - 1];
|
|
163
168
|
if (neighbour) stopNodes.get(neighbour.id)?.focus();
|
|
@@ -200,7 +205,7 @@ function GradientEditorStop({ stop, className, style, onPointerDown, onKeyDown,
|
|
|
200
205
|
break;
|
|
201
206
|
case "Backspace":
|
|
202
207
|
case "Delete":
|
|
203
|
-
if (!
|
|
208
|
+
if (!canRemoveStop) return;
|
|
204
209
|
event.preventDefault();
|
|
205
210
|
remove();
|
|
206
211
|
}
|
|
@@ -218,7 +223,7 @@ function GradientEditorStop({ stop, className, style, onPointerDown, onKeyDown,
|
|
|
218
223
|
"data-control-ui": "gradient-editor",
|
|
219
224
|
"data-control-family": "gradient-editor",
|
|
220
225
|
"data-slot": "stop",
|
|
221
|
-
"data-selected":
|
|
226
|
+
"data-selected": stop.id === selectedStop?.id ? "true" : void 0,
|
|
222
227
|
"aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? defaultLabel : ariaLabel,
|
|
223
228
|
"aria-labelledby": ariaLabelledBy,
|
|
224
229
|
"aria-orientation": "horizontal",
|
|
@@ -262,56 +267,5 @@ function GradientEditorStopAdd({ className, children, ...props }) {
|
|
|
262
267
|
})
|
|
263
268
|
});
|
|
264
269
|
}
|
|
265
|
-
function GradientEditorStopColor() {
|
|
266
|
-
const { stops, selectedId, setStopColor } = useGradientEditor();
|
|
267
|
-
const selected = stops.find((s) => s.id === selectedId) ?? stops[0];
|
|
268
|
-
if (!selected) return null;
|
|
269
|
-
return /* @__PURE__ */ jsxs(ColorPicker, {
|
|
270
|
-
value: selected.color,
|
|
271
|
-
onValueChange: (color) => setStopColor(selected.id, color),
|
|
272
|
-
defaultFormat: "hex",
|
|
273
|
-
children: [/* @__PURE__ */ jsx(ColorPickerTrigger, {}), /* @__PURE__ */ jsxs(ColorPickerContent, { children: [
|
|
274
|
-
/* @__PURE__ */ jsx(ColorPickerArea, {}),
|
|
275
|
-
/* @__PURE__ */ jsx(ColorPickerHue, {}),
|
|
276
|
-
/* @__PURE__ */ jsx(ColorPickerAlpha, {}),
|
|
277
|
-
/* @__PURE__ */ jsxs("div", {
|
|
278
|
-
"data-control-ui": "gradient-editor",
|
|
279
|
-
"data-control-family": "gradient-editor",
|
|
280
|
-
"data-slot": "value-row",
|
|
281
|
-
className: "flex",
|
|
282
|
-
children: [/* @__PURE__ */ jsx(ColorPickerFormatSelect, {}), /* @__PURE__ */ jsx(ColorPickerInput, { className: "flex-1" })]
|
|
283
|
-
})
|
|
284
|
-
] })]
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
function GradientEditorTypeSelect({ size = "sm", className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) {
|
|
288
|
-
const { type, setType } = useGradientEditor();
|
|
289
|
-
return /* @__PURE__ */ jsxs(Select, {
|
|
290
|
-
value: type,
|
|
291
|
-
onValueChange: (value) => {
|
|
292
|
-
if (isGradientType(value)) setType(value);
|
|
293
|
-
},
|
|
294
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
295
|
-
size,
|
|
296
|
-
"aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Gradient type" : ariaLabel,
|
|
297
|
-
"aria-labelledby": ariaLabelledBy,
|
|
298
|
-
className,
|
|
299
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
300
|
-
}), /* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
301
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
302
|
-
value: "linear",
|
|
303
|
-
children: "Linear"
|
|
304
|
-
}),
|
|
305
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
306
|
-
value: "radial",
|
|
307
|
-
children: "Radial"
|
|
308
|
-
}),
|
|
309
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
310
|
-
value: "conic",
|
|
311
|
-
children: "Conic"
|
|
312
|
-
})
|
|
313
|
-
] })]
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
270
|
//#endregion
|
|
317
|
-
export { GradientEditor, GradientEditorPreview, GradientEditorStop, GradientEditorStopAdd,
|
|
271
|
+
export { GradientEditor, GradientEditorPreview, GradientEditorStop, GradientEditorStopAdd, GradientEditorTrack, useGradientEditor };
|
package/dist/ui/icon-picker.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare function IconPickerSearch({ placeholder, "aria-label": ariaLabel,
|
|
|
27
27
|
export type IconPickerContentProps = Omit<ComponentProps<"div">, "style" | "children"> & IconPickerStyle & {
|
|
28
28
|
empty?: ReactNode;
|
|
29
29
|
};
|
|
30
|
-
export declare function IconPickerContent({ className, empty, "aria-label": ariaLabel, ...props }: IconPickerContentProps): import("react").JSX.Element;
|
|
30
|
+
export declare function IconPickerContent({ className, ref, empty, "aria-label": ariaLabel, ...props }: IconPickerContentProps): import("react").JSX.Element;
|
|
31
31
|
export type IconPickerColorsProps = Omit<ComponentProps<"div">, "style" | "defaultValue" | "onChange" | "children"> & IconPickerStyle & ControlledChoice & {
|
|
32
32
|
colors: readonly IconPickerColor[];
|
|
33
33
|
};
|