@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.
Files changed (161) hide show
  1. package/README.md +1 -0
  2. package/dist/action-bar.d.ts +1 -2
  3. package/dist/action-bar.js +7 -8
  4. package/dist/blocks/design-canvas-inspector.js +4 -1
  5. package/dist/blocks/file-explorer.js +1 -1
  6. package/dist/chat-message.js +4 -13
  7. package/dist/hooks/use-textarea-trigger-menu.d.ts +21 -3
  8. package/dist/hooks/use-textarea-trigger-menu.js +36 -40
  9. package/dist/hooks/use-user-ask.d.ts +1 -0
  10. package/dist/hooks/use-user-ask.js +5 -1
  11. package/dist/knob-contracts/audio-recorder-knobs.d.ts +1 -1
  12. package/dist/knob-contracts/audio-recorder-knobs.js +2 -1
  13. package/dist/knob-contracts/chart-knobs.d.ts +4 -0
  14. package/dist/knob-contracts/chart-knobs.js +24 -0
  15. package/dist/knob-contracts/choice-knobs.d.ts +1 -1
  16. package/dist/knob-contracts/choice-knobs.js +1 -0
  17. package/dist/knob-contracts/dockable-panel-knobs.d.ts +1 -1
  18. package/dist/knob-contracts/dockable-panel-knobs.js +2 -1
  19. package/dist/knob-contracts/emoji-picker-knobs.d.ts +1 -1
  20. package/dist/knob-contracts/emoji-picker-knobs.js +1 -0
  21. package/dist/knob-contracts/empty-knobs.d.ts +1 -1
  22. package/dist/knob-contracts/empty-knobs.js +2 -1
  23. package/dist/knob-contracts/icon-picker-knobs.d.ts +1 -1
  24. package/dist/knob-contracts/icon-picker-knobs.js +3 -1
  25. package/dist/knob-contracts/resizable-knobs.d.ts +1 -1
  26. package/dist/knob-contracts/resizable-knobs.js +2 -2
  27. package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
  28. package/dist/knob-contracts/sidebar-knobs.js +3 -1
  29. package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
  30. package/dist/knob-contracts/tabs-knobs.js +2 -1
  31. package/dist/knob-contracts/tree-knobs.d.ts +1 -1
  32. package/dist/knob-contracts/tree-knobs.js +2 -1
  33. package/dist/lib/color.d.ts +2 -6
  34. package/dist/lib/color.js +45 -28
  35. package/dist/lib/contrast.d.ts +6 -0
  36. package/dist/lib/contrast.js +33 -1
  37. package/dist/lib/gradient.d.ts +17 -0
  38. package/dist/lib/gradient.js +69 -0
  39. package/dist/markdown-editor/drag-handle.js +73 -10
  40. package/dist/markdown-editor/drag-preview.d.ts +3 -0
  41. package/dist/markdown-editor/drag-preview.js +31 -0
  42. package/dist/markdown-editor/extensions.d.ts +2 -2
  43. package/dist/markdown-editor/extensions.js +25 -3
  44. package/dist/markdown-editor/suggestions.js +5 -5
  45. package/dist/markdown-editor/task-item.d.ts +3 -0
  46. package/dist/markdown-editor/task-item.js +50 -0
  47. package/dist/markdown-editor/toolbar.js +122 -63
  48. package/dist/markdown-editor.js +3 -3
  49. package/dist/skin.d.ts +0 -1
  50. package/dist/styles/index.css +3 -2
  51. package/dist/styles/recipes/action-bar.css +1 -1
  52. package/dist/styles/recipes/activity.css +1 -1
  53. package/dist/styles/recipes/alert.css +9 -10
  54. package/dist/styles/recipes/app-shell-header.css +2 -2
  55. package/dist/styles/recipes/audio-recorder.css +15 -4
  56. package/dist/styles/recipes/audio-visualizer.css +4 -4
  57. package/dist/styles/recipes/avatar.css +3 -3
  58. package/dist/styles/recipes/badge.css +2 -2
  59. package/dist/styles/recipes/button.css +2 -5
  60. package/dist/styles/recipes/card.css +0 -2
  61. package/dist/styles/recipes/chart.css +378 -0
  62. package/dist/styles/recipes/chat-composer-attachment.css +3 -3
  63. package/dist/styles/recipes/chat-composer.css +3 -3
  64. package/dist/styles/recipes/chat-layout.css +2 -2
  65. package/dist/styles/recipes/chat-message-social.css +1 -1
  66. package/dist/styles/recipes/chat-message.css +1 -1
  67. package/dist/styles/recipes/choice.css +9 -3
  68. package/dist/styles/recipes/code-diff.css +1 -1
  69. package/dist/styles/recipes/code.css +1 -1
  70. package/dist/styles/recipes/color-picker-details.css +17 -11
  71. package/dist/styles/recipes/color-picker-values.css +17 -7
  72. package/dist/styles/recipes/color-picker.css +88 -70
  73. package/dist/styles/recipes/context.css +2 -2
  74. package/dist/styles/recipes/dockable-panel.css +9 -2
  75. package/dist/styles/recipes/dynamic-notification-motion.css +1 -55
  76. package/dist/styles/recipes/dynamic-notification.css +0 -1
  77. package/dist/styles/recipes/emoji-picker.css +35 -19
  78. package/dist/styles/recipes/empty.css +19 -14
  79. package/dist/styles/recipes/field-parts.css +2 -2
  80. package/dist/styles/recipes/field.css +6 -4
  81. package/dist/styles/recipes/filter-bar.css +10 -10
  82. package/dist/styles/recipes/flow.css +5 -3
  83. package/dist/styles/recipes/gradient-editor.css +8 -0
  84. package/dist/styles/recipes/icon-picker.css +45 -10
  85. package/dist/styles/recipes/inline-attachment.css +4 -4
  86. package/dist/styles/recipes/inline-citation.css +2 -2
  87. package/dist/styles/recipes/item.css +4 -4
  88. package/dist/styles/recipes/markdown-editor.css +35 -24
  89. package/dist/styles/recipes/markdown.css +23 -27
  90. package/dist/styles/recipes/page-layout.css +13 -11
  91. package/dist/styles/recipes/popup-controls.css +2 -2
  92. package/dist/styles/recipes/popup-lists.css +3 -3
  93. package/dist/styles/recipes/popup.css +11 -9
  94. package/dist/styles/recipes/range.css +4 -5
  95. package/dist/styles/recipes/resizable.css +15 -10
  96. package/dist/styles/recipes/resize-handle.css +2 -2
  97. package/dist/styles/recipes/scroll-area.css +1 -1
  98. package/dist/styles/recipes/sidebar-menu.css +5 -15
  99. package/dist/styles/recipes/sidebar-mobile.css +4 -4
  100. package/dist/styles/recipes/sidebar-parts.css +26 -1
  101. package/dist/styles/recipes/sidebar.css +18 -31
  102. package/dist/styles/recipes/skeleton.css +10 -5
  103. package/dist/styles/recipes/stepper.css +1 -1
  104. package/dist/styles/recipes/switch.css +12 -11
  105. package/dist/styles/recipes/table-of-contents.css +6 -8
  106. package/dist/styles/recipes/table.css +4 -4
  107. package/dist/styles/recipes/tabs.css +10 -5
  108. package/dist/styles/recipes/task-list.css +3 -3
  109. package/dist/styles/recipes/tree.css +10 -3
  110. package/dist/styles/recipes/user-ask-details.css +5 -4
  111. package/dist/styles/recipes/user-ask.css +5 -5
  112. package/dist/styles/theme.css +158 -177
  113. package/dist/ui/chart-cartesian.d.ts +801 -0
  114. package/dist/ui/chart-cartesian.js +420 -0
  115. package/dist/ui/chart-colors.d.ts +7 -0
  116. package/dist/ui/chart-colors.js +27 -0
  117. package/dist/ui/chart-curves.d.ts +7 -0
  118. package/dist/ui/chart-curves.js +87 -0
  119. package/dist/ui/chart-marks.d.ts +68 -0
  120. package/dist/ui/chart-marks.js +227 -0
  121. package/dist/ui/chart-polar.d.ts +103 -0
  122. package/dist/ui/chart-polar.js +124 -0
  123. package/dist/ui/chart-series.d.ts +36 -0
  124. package/dist/ui/chart-series.js +71 -0
  125. package/dist/ui/chart.d.ts +32 -0
  126. package/dist/ui/chart.js +257 -0
  127. package/dist/ui/color-picker-area.d.ts +16 -0
  128. package/dist/ui/color-picker-area.js +175 -0
  129. package/dist/ui/color-picker-context.d.ts +27 -0
  130. package/dist/ui/color-picker-context.js +87 -0
  131. package/dist/ui/color-picker-contrast.d.ts +20 -0
  132. package/dist/ui/color-picker-contrast.js +129 -0
  133. package/dist/ui/color-picker-sliders.d.ts +15 -0
  134. package/dist/ui/color-picker-sliders.js +146 -0
  135. package/dist/ui/color-picker-swatches.d.ts +23 -0
  136. package/dist/ui/color-picker-swatches.js +94 -0
  137. package/dist/ui/color-picker-values.d.ts +59 -0
  138. package/dist/ui/color-picker-values.js +244 -0
  139. package/dist/ui/color-picker.d.ts +15 -110
  140. package/dist/ui/color-picker.js +30 -759
  141. package/dist/ui/emoji-picker.d.ts +10 -1
  142. package/dist/ui/emoji-picker.js +71 -14
  143. package/dist/ui/flow.js +1 -1
  144. package/dist/ui/gradient-editor-controls.d.ts +19 -0
  145. package/dist/ui/gradient-editor-controls.js +75 -0
  146. package/dist/ui/gradient-editor.d.ts +23 -22
  147. package/dist/ui/gradient-editor.js +77 -123
  148. package/dist/ui/icon-picker.d.ts +1 -1
  149. package/dist/ui/icon-picker.js +11 -6
  150. package/dist/ui/markdown-elements.d.ts +3 -1
  151. package/dist/ui/markdown-elements.js +62 -22
  152. package/dist/ui/markdown-heading.d.ts +9 -0
  153. package/dist/ui/markdown-heading.js +25 -0
  154. package/dist/ui/resizable.js +24 -9
  155. package/dist/ui/sidebar-provider.js +3 -12
  156. package/dist/ui/typography.d.ts +1 -0
  157. package/dist/ui/typography.js +12 -3
  158. package/dist/user-ask.js +4 -8
  159. package/package.json +7 -3
  160. package/dist/ui/emoji-icon-picker.d.ts +0 -13
  161. package/dist/ui/emoji-icon-picker.js +0 -50
package/README.md CHANGED
@@ -71,6 +71,7 @@ Install a peer only when you import the component that needs it.
71
71
  | Component | Peer |
72
72
  | --- | --- |
73
73
  | `ui/calendar` | `react-day-picker` |
74
+ | `ui/chart` | `@tanstack/charts` |
74
75
  | `ui/code`, `ui/code-diff` | `@tanstack/react-virtual`, `diff`, `shiki` |
75
76
  | `ui/command` | `cmdk` |
76
77
  | `ui/flow` | `@xyflow/react` |
@@ -14,7 +14,6 @@ export type ActionBarContextValue = {
14
14
  export type ActionBarProps = Omit<ComponentProps<"div">, "style"> & {
15
15
  label?: string;
16
16
  align?: "start" | "end";
17
- context?: ActionBarContextValue;
18
17
  copyValue?: ActionBarCopyValue;
19
18
  editValue?: ActionBarCopyValue;
20
19
  onCopy?: (value: string) => void;
@@ -23,7 +22,7 @@ export type ActionBarProps = Omit<ComponentProps<"div">, "style"> & {
23
22
  onEditError?: (error: unknown) => void;
24
23
  style?: CSSProperties & ActionBarKnobStyle;
25
24
  };
26
- export declare function ActionBar({ label, align, className, children, context, copyValue, editValue, onCopy, onCopyError, onEdit, onEditError, ...props }: ActionBarProps): import("react").JSX.Element;
25
+ export declare function ActionBar({ label, align, className, children, copyValue, editValue, onCopy, onCopyError, onEdit, onEditError, ...props }: ActionBarProps): import("react").JSX.Element;
27
26
  type ActionBarItemBaseProps = Omit<ComponentProps<typeof Button>, "iconOnly" | "children"> & {
28
27
  icon?: ReactNode;
29
28
  };
@@ -11,15 +11,14 @@ const ActionBarContext = createContext({});
11
11
  async function resolveCopyValue(value) {
12
12
  return typeof value === "function" ? await value() : value;
13
13
  }
14
- function ActionBar({ label = "Message actions", align = "start", className, children, context, copyValue, editValue, onCopy, onCopyError, onEdit, onEditError, ...props }) {
14
+ function ActionBar({ label = "Message actions", align = "start", className, children, copyValue, editValue, onCopy, onCopyError, onEdit, onEditError, ...props }) {
15
15
  const actionContext = {
16
- ...context,
17
- copyValue: copyValue ?? context?.copyValue,
18
- editValue: editValue ?? context?.editValue,
19
- onCopy: onCopy ?? context?.onCopy,
20
- onCopyError: onCopyError ?? context?.onCopyError,
21
- onEdit: onEdit ?? context?.onEdit,
22
- onEditError: onEditError ?? context?.onEditError
16
+ copyValue,
17
+ editValue,
18
+ onCopy,
19
+ onCopyError,
20
+ onEdit,
21
+ onEditError
23
22
  };
24
23
  return /* @__PURE__ */ jsx(ActionBarContext.Provider, {
25
24
  value: actionContext,
@@ -2,9 +2,12 @@
2
2
  import { Button } from "../ui/button.js";
3
3
  import { Heading } from "../ui/typography.js";
4
4
  import { resizeDesignCanvasLayer } from "./design-canvas-data.js";
5
+ import { ColorPickerArea } from "../ui/color-picker-area.js";
6
+ import { ColorPickerHue } from "../ui/color-picker-sliders.js";
5
7
  import { InputGroup, InputGroupAddon } from "../ui/input-group.js";
6
8
  import { NumberField, NumberFieldGroup, NumberFieldInput, NumberFieldScrubArea } from "../ui/number-field.js";
7
- import { ColorPicker, ColorPickerArea, ColorPickerContent, ColorPickerEyeDropper, ColorPickerHue, ColorPickerInput, ColorPickerTrigger } from "../ui/color-picker.js";
9
+ import { ColorPickerEyeDropper, ColorPickerInput } from "../ui/color-picker-values.js";
10
+ import { ColorPicker, ColorPickerContent, ColorPickerTrigger } from "../ui/color-picker.js";
8
11
  import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "../ui/empty.js";
9
12
  import { Separator } from "../ui/separator.js";
10
13
  import { Toggle } from "../ui/toggle.js";
@@ -12,9 +12,9 @@ import { InputGroup, InputGroupAddon } from "../ui/input-group.js";
12
12
  import { Input } from "../ui/input.js";
13
13
  import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "../ui/empty.js";
14
14
  import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "../ui/resizable.js";
15
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
15
16
  import { groupFileExplorerItems, orderFileExplorerEntries, resolveFileExplorer, searchFileExplorer } from "./file-explorer-data.js";
16
17
  import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "../ui/breadcrumb.js";
17
- import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
18
18
  import { Fragment, useEffect, useId, useRef, useState } from "react";
19
19
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
20
20
  import { ChevronLeftIcon, ChevronRightIcon, FileIcon, FolderIcon, MoreHorizontalIcon, SearchIcon, XIcon } from "lucide-react";
@@ -148,14 +148,7 @@ function useMessageEditor({ value, onSave, onSaveError }) {
148
148
  const inputRef = useRef(null);
149
149
  const triggerRef = useRef(null);
150
150
  const savingRef = useRef(false);
151
- const mountedRef = useRef(false);
152
151
  const errorId = useId();
153
- useEffect(() => {
154
- mountedRef.current = true;
155
- return () => {
156
- mountedRef.current = false;
157
- };
158
- }, []);
159
152
  useLayoutEffect(() => {
160
153
  if (editing) {
161
154
  const input = inputRef.current;
@@ -190,15 +183,13 @@ function useMessageEditor({ value, onSave, onSaveError }) {
190
183
  setFailed(false);
191
184
  try {
192
185
  await onSave(draft);
193
- if (mountedRef.current) setEditing(false);
186
+ setEditing(false);
194
187
  } catch (error) {
195
- if (mountedRef.current) {
196
- setFailed(true);
197
- onSaveError?.(error);
198
- }
188
+ setFailed(true);
189
+ onSaveError?.(error);
199
190
  } finally {
200
191
  savingRef.current = false;
201
- if (mountedRef.current) setSaving(false);
192
+ setSaving(false);
202
193
  }
203
194
  }
204
195
  return {
@@ -1,7 +1,25 @@
1
- import { TriggerConfig, TriggerMenuController, TriggerMenuItemData } from "./use-trigger-menu.js";
2
- import { RefObject } from "react";
1
+ import { TriggerMatch } from "../lib/trigger-detect.js";
2
+ import { TriggerConfig, TriggerMenuInputAria, TriggerMenuItemData } from "./use-trigger-menu.js";
3
+ import { ComponentProps, RefObject } from "react";
3
4
  //#region src/hooks/use-textarea-trigger-menu.d.ts
4
5
  export declare function useTextareaTriggerMenu<Item extends TriggerMenuItemData>(ref: RefObject<HTMLTextAreaElement | null>, options: {
5
6
  triggers: readonly TriggerConfig<Item>[];
6
- }): TriggerMenuController<Item>;
7
+ }): {
8
+ open: boolean;
9
+ items: readonly Item[];
10
+ activeIndex: number;
11
+ anchorRect: DOMRect | null;
12
+ activeChar: string | null;
13
+ query: string;
14
+ listId: string;
15
+ optionId: (index: number) => string;
16
+ inputAria: TriggerMenuInputAria;
17
+ report: (match: TriggerMatch | null, anchorRect: DOMRect | null) => void;
18
+ handleKeyDown: (key: string) => boolean;
19
+ setActiveIndex: (index: number) => void;
20
+ select: (item: Item) => void;
21
+ close: () => void;
22
+ setOpen: (open: boolean) => void;
23
+ getTextareaProps: (props?: ComponentProps<"textarea">) => ComponentProps<"textarea">;
24
+ };
7
25
  //#endregion
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { isComposingKey, useTriggerMenu } from "./use-trigger-menu.js";
3
3
  import { caretRectInTextarea, detectTrigger } from "../lib/trigger-detect.js";
4
- import { useEffect, useEffectEvent } from "react";
5
4
  //#region src/hooks/use-textarea-trigger-menu.ts
5
+ const CLOSE_AFTER_BLUR_MS = 120;
6
6
  function replaceRange(element, start, end, text) {
7
7
  element.focus();
8
8
  element.setSelectionRange(start, end);
@@ -27,47 +27,43 @@ function useTextareaTriggerMenu(ref, options) {
27
27
  });
28
28
  }
29
29
  });
30
- const syncTrigger = useEffectEvent(() => {
31
- const element = ref.current;
32
- if (!element) return;
33
- const caret = element.selectionStart ?? element.value.length;
30
+ function reportTriggerAtCaret(textarea) {
31
+ const caret = textarea.selectionStart ?? textarea.value.length;
34
32
  const chars = options.triggers.map((trigger) => trigger.char);
35
- const match = detectTrigger(element.value.slice(0, caret), chars);
36
- controller.report(match, match === null ? null : caretRectInTextarea(element, match.start));
37
- });
38
- const handleKeyDown = useEffectEvent((event) => {
39
- if (isComposingKey(event)) return;
40
- if (controller.open && controller.handleKeyDown(event.key)) event.preventDefault();
41
- });
42
- const closeAfterBlur = useEffectEvent(() => {
43
- controller.close();
44
- });
45
- useEffect(() => {
46
- const element = ref.current;
47
- if (!element) return;
48
- function onKeyDown(event) {
49
- handleKeyDown(event);
50
- }
51
- function syncAfterInput() {
52
- window.setTimeout(syncTrigger, 0);
53
- }
54
- function onBlur() {
55
- window.setTimeout(closeAfterBlur, 120);
56
- }
57
- element.addEventListener("input", syncAfterInput);
58
- element.addEventListener("keydown", onKeyDown);
59
- element.addEventListener("keyup", syncTrigger);
60
- element.addEventListener("click", syncTrigger);
61
- element.addEventListener("blur", onBlur);
62
- return () => {
63
- element.removeEventListener("input", syncAfterInput);
64
- element.removeEventListener("keydown", onKeyDown);
65
- element.removeEventListener("keyup", syncTrigger);
66
- element.removeEventListener("click", syncTrigger);
67
- element.removeEventListener("blur", onBlur);
33
+ const match = detectTrigger(textarea.value.slice(0, caret), chars);
34
+ controller.report(match, match === null ? null : caretRectInTextarea(textarea, match.start));
35
+ }
36
+ function getTextareaProps(props = {}) {
37
+ const { onChange, onKeyDown, onKeyUp, onClick, onBlur, ...textareaProps } = props;
38
+ return {
39
+ ...textareaProps,
40
+ ...controller.inputAria,
41
+ onChange: (event) => {
42
+ onChange?.(event);
43
+ reportTriggerAtCaret(event.currentTarget);
44
+ },
45
+ onKeyDown: (event) => {
46
+ if (!isComposingKey(event.nativeEvent) && controller.open && controller.handleKeyDown(event.key)) event.preventDefault();
47
+ onKeyDown?.(event);
48
+ },
49
+ onKeyUp: (event) => {
50
+ onKeyUp?.(event);
51
+ reportTriggerAtCaret(event.currentTarget);
52
+ },
53
+ onClick: (event) => {
54
+ onClick?.(event);
55
+ reportTriggerAtCaret(event.currentTarget);
56
+ },
57
+ onBlur: (event) => {
58
+ onBlur?.(event);
59
+ window.setTimeout(controller.close, CLOSE_AFTER_BLUR_MS);
60
+ }
68
61
  };
69
- }, [ref]);
70
- return controller;
62
+ }
63
+ return {
64
+ ...controller,
65
+ getTextareaProps
66
+ };
71
67
  }
72
68
  //#endregion
73
69
  export { useTextareaTriggerMenu };
@@ -27,6 +27,7 @@ export declare function useUserAsk({ onComplete, onDismiss }: Pick<UserAskProps,
27
27
  questions: UserAskQuestionEntry[];
28
28
  activeIndex: number;
29
29
  activeQuestion: UserAskQuestionEntry;
30
+ hasNavigated: boolean;
30
31
  canContinue: boolean;
31
32
  isLastQuestion: boolean;
32
33
  registerQuestion: (entry: UserAskQuestionEntry) => void;
@@ -20,6 +20,7 @@ function useUserAsk({ onComplete, onDismiss }) {
20
20
  const [selections, setSelections] = useState({});
21
21
  const [freeformTexts, setFreeformTexts] = useState({});
22
22
  const [requestedIndex, setRequestedIndex] = useState(0);
23
+ const [hasNavigated, setHasNavigated] = useState(false);
23
24
  const [registerQuestion] = useState(() => (entry) => {
24
25
  setQuestions((previous) => upsert(previous, entry));
25
26
  });
@@ -102,7 +103,9 @@ function useUserAsk({ onComplete, onDismiss }) {
102
103
  const canContinue = activeQuestion !== void 0 && answerFor(activeQuestion.id) !== void 0;
103
104
  const isLastQuestion = activeIndex === questions.length - 1;
104
105
  function goTo(index) {
105
- setRequestedIndex(Math.max(0, Math.min(index, questions.length - 1)));
106
+ const targetIndex = Math.max(0, Math.min(index, questions.length - 1));
107
+ if (targetIndex !== activeIndex) setHasNavigated(true);
108
+ setRequestedIndex(targetIndex);
106
109
  }
107
110
  function resolveAnswers() {
108
111
  const answers = {};
@@ -174,6 +177,7 @@ function useUserAsk({ onComplete, onDismiss }) {
174
177
  questions,
175
178
  activeIndex,
176
179
  activeQuestion,
180
+ hasNavigated,
177
181
  canContinue,
178
182
  isLastQuestion,
179
183
  registerQuestion,
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/audio-recorder-knobs.d.ts
2
- export declare const audioRecorderKnobs: readonly ["--cui-audio-recorder-foreground", "--cui-audio-recorder-active-foreground", "--cui-audio-recorder-recording-ring-color", "--cui-audio-recorder-error-foreground", "--cui-audio-recorder-meta-foreground"];
2
+ export declare const audioRecorderKnobs: readonly ["--cui-audio-recorder-foreground", "--cui-audio-recorder-recording-foreground", "--cui-audio-recorder-recorded-foreground", "--cui-audio-recorder-recording-ring-color", "--cui-audio-recorder-error-foreground", "--cui-audio-recorder-meta-foreground"];
3
3
  export type AudioRecorderKnobStyle = Partial<Record<(typeof audioRecorderKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,7 +1,8 @@
1
1
  //#region src/knob-contracts/audio-recorder-knobs.ts
2
2
  const audioRecorderKnobs = [
3
3
  "--cui-audio-recorder-foreground",
4
- "--cui-audio-recorder-active-foreground",
4
+ "--cui-audio-recorder-recording-foreground",
5
+ "--cui-audio-recorder-recorded-foreground",
5
6
  "--cui-audio-recorder-recording-ring-color",
6
7
  "--cui-audio-recorder-error-foreground",
7
8
  "--cui-audio-recorder-meta-foreground"
@@ -0,0 +1,4 @@
1
+ //#region src/knob-contracts/chart-knobs.d.ts
2
+ export declare const chartKnobs: readonly ["--cui-chart-foreground", "--cui-chart-background", "--cui-chart-line-size", "--cui-chart-area-opacity", "--cui-chart-hatch-opacity", "--cui-chart-hatch-tint-opacity", "--cui-chart-tooltip-background", "--cui-chart-tooltip-foreground", "--cui-chart-tooltip-border-color", "--cui-chart-tooltip-border-width", "--cui-chart-tooltip-radius", "--cui-chart-tooltip-shadow", "--cui-chart-tooltip-padding", "--cui-chart-legend-gap", "--cui-chart-swatch-size", "--cui-chart-swatch-radius", "--cui-chart-animation-duration", "--cui-chart-transition-duration", "--cui-chart-easing"];
3
+ export type ChartKnobStyle = Partial<Record<(typeof chartKnobs)[number], string>>;
4
+ //#endregion
@@ -0,0 +1,24 @@
1
+ //#region src/knob-contracts/chart-knobs.ts
2
+ const chartKnobs = [
3
+ "--cui-chart-foreground",
4
+ "--cui-chart-background",
5
+ "--cui-chart-line-size",
6
+ "--cui-chart-area-opacity",
7
+ "--cui-chart-hatch-opacity",
8
+ "--cui-chart-hatch-tint-opacity",
9
+ "--cui-chart-tooltip-background",
10
+ "--cui-chart-tooltip-foreground",
11
+ "--cui-chart-tooltip-border-color",
12
+ "--cui-chart-tooltip-border-width",
13
+ "--cui-chart-tooltip-radius",
14
+ "--cui-chart-tooltip-shadow",
15
+ "--cui-chart-tooltip-padding",
16
+ "--cui-chart-legend-gap",
17
+ "--cui-chart-swatch-size",
18
+ "--cui-chart-swatch-radius",
19
+ "--cui-chart-animation-duration",
20
+ "--cui-chart-transition-duration",
21
+ "--cui-chart-easing"
22
+ ];
23
+ //#endregion
24
+ export { chartKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/choice-knobs.d.ts
2
- export declare const choiceKnobs: readonly ["--cui-choice-radius", "--cui-choice-border-color", "--cui-choice-border-width", "--cui-choice-checked-background", "--cui-choice-checked-border-color", "--cui-choice-shadow"];
2
+ export declare const choiceKnobs: readonly ["--cui-choice-radius", "--cui-choice-border-color", "--cui-choice-border-width", "--cui-choice-background", "--cui-choice-checked-background", "--cui-choice-checked-border-color", "--cui-choice-shadow"];
3
3
  export type ChoiceKnobStyle = Partial<Record<(typeof choiceKnobs)[number], string>>;
4
4
  //#endregion
@@ -3,6 +3,7 @@ const choiceKnobs = [
3
3
  "--cui-choice-radius",
4
4
  "--cui-choice-border-color",
5
5
  "--cui-choice-border-width",
6
+ "--cui-choice-background",
6
7
  "--cui-choice-checked-background",
7
8
  "--cui-choice-checked-border-color",
8
9
  "--cui-choice-shadow"
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/dockable-panel-knobs.d.ts
2
- export declare const dockablePanelKnobs: readonly ["--cui-dockable-panel-radius", "--cui-dockable-panel-background", "--cui-dockable-panel-foreground", "--cui-dockable-panel-border-color", "--cui-dockable-panel-border-width", "--cui-dockable-panel-shadow", "--cui-dockable-panel-drop-zone-active-background", "--cui-dockable-panel-drop-zone-active-border-color"];
2
+ export declare const dockablePanelKnobs: readonly ["--cui-dockable-panel-radius", "--cui-dockable-panel-background", "--cui-dockable-panel-foreground", "--cui-dockable-panel-border-color", "--cui-dockable-panel-border-width", "--cui-dockable-panel-shadow", "--cui-dockable-panel-drop-zone-active-background", "--cui-dockable-panel-drop-zone-active-border-color", "--cui-dockable-panel-drop-zone-background"];
3
3
  export type DockablePanelKnobStyle = Partial<Record<(typeof dockablePanelKnobs)[number], string>>;
4
4
  //#endregion
@@ -7,7 +7,8 @@ const dockablePanelKnobs = [
7
7
  "--cui-dockable-panel-border-width",
8
8
  "--cui-dockable-panel-shadow",
9
9
  "--cui-dockable-panel-drop-zone-active-background",
10
- "--cui-dockable-panel-drop-zone-active-border-color"
10
+ "--cui-dockable-panel-drop-zone-active-border-color",
11
+ "--cui-dockable-panel-drop-zone-background"
11
12
  ];
12
13
  //#endregion
13
14
  export { dockablePanelKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/emoji-picker-knobs.d.ts
2
- export declare const emojiPickerKnobs: readonly ["--cui-emoji-picker-cell-size", "--cui-emoji-picker-height", "--cui-emoji-picker-cell-radius", "--cui-emoji-picker-active-background", "--cui-emoji-picker-header-background", "--cui-emoji-picker-header-foreground"];
2
+ export declare const emojiPickerKnobs: readonly ["--cui-emoji-picker-cell-size", "--cui-emoji-picker-height", "--cui-emoji-picker-cell-radius", "--cui-emoji-picker-glyph-size", "--cui-emoji-picker-active-background", "--cui-emoji-picker-header-background", "--cui-emoji-picker-header-foreground"];
3
3
  export type EmojiPickerKnobStyle = Partial<Record<(typeof emojiPickerKnobs)[number], string>>;
4
4
  //#endregion
@@ -3,6 +3,7 @@ const emojiPickerKnobs = [
3
3
  "--cui-emoji-picker-cell-size",
4
4
  "--cui-emoji-picker-height",
5
5
  "--cui-emoji-picker-cell-radius",
6
+ "--cui-emoji-picker-glyph-size",
6
7
  "--cui-emoji-picker-active-background",
7
8
  "--cui-emoji-picker-header-background",
8
9
  "--cui-emoji-picker-header-foreground"
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/empty-knobs.d.ts
2
- export declare const emptyKnobs: readonly ["--cui-empty-radius", "--cui-empty-background", "--cui-empty-border-color", "--cui-empty-border-width", "--cui-empty-border-style", "--cui-empty-media-radius", "--cui-empty-media-background", "--cui-empty-shadow", "--cui-empty-foreground", "--cui-empty-description-foreground", "--cui-empty-media-foreground", "--cui-empty-padding", "--cui-empty-gap", "--cui-empty-header-gap", "--cui-empty-content-gap", "--cui-empty-content-size", "--cui-empty-media-size", "--cui-empty-media-icon-size", "--cui-empty-font-size", "--cui-empty-title-font-weight"];
2
+ export declare const emptyKnobs: readonly ["--cui-empty-radius", "--cui-empty-background", "--cui-empty-border-color", "--cui-empty-border-width", "--cui-empty-border-style", "--cui-empty-media-radius", "--cui-empty-media-background", "--cui-empty-shadow", "--cui-empty-foreground", "--cui-empty-description-foreground", "--cui-empty-media-foreground", "--cui-empty-padding", "--cui-empty-gap", "--cui-empty-header-gap", "--cui-empty-content-gap", "--cui-empty-content-size", "--cui-empty-media-size", "--cui-empty-media-icon-size", "--cui-empty-font-size", "--cui-empty-title-font-weight", "--cui-empty-media-background-image"];
3
3
  export type EmptyKnobStyle = Partial<Record<(typeof emptyKnobs)[number], string>>;
4
4
  //#endregion
@@ -19,7 +19,8 @@ const emptyKnobs = [
19
19
  "--cui-empty-media-size",
20
20
  "--cui-empty-media-icon-size",
21
21
  "--cui-empty-font-size",
22
- "--cui-empty-title-font-weight"
22
+ "--cui-empty-title-font-weight",
23
+ "--cui-empty-media-background-image"
23
24
  ];
24
25
  //#endregion
25
26
  export { emptyKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/icon-picker-knobs.d.ts
2
- export declare const iconPickerKnobs: readonly ["--cui-icon-picker-cell-size", "--cui-icon-picker-cell-radius", "--cui-icon-picker-foreground", "--cui-icon-picker-active-background"];
2
+ export declare const iconPickerKnobs: readonly ["--cui-icon-picker-cell-size", "--cui-icon-picker-cell-radius", "--cui-icon-picker-icon-size", "--cui-icon-picker-foreground", "--cui-icon-picker-cell-hover-background", "--cui-icon-picker-cell-pressed-background"];
3
3
  export type IconPickerKnobStyle = Partial<Record<(typeof iconPickerKnobs)[number], string>>;
4
4
  //#endregion
@@ -2,8 +2,10 @@
2
2
  const iconPickerKnobs = [
3
3
  "--cui-icon-picker-cell-size",
4
4
  "--cui-icon-picker-cell-radius",
5
+ "--cui-icon-picker-icon-size",
5
6
  "--cui-icon-picker-foreground",
6
- "--cui-icon-picker-active-background"
7
+ "--cui-icon-picker-cell-hover-background",
8
+ "--cui-icon-picker-cell-pressed-background"
7
9
  ];
8
10
  //#endregion
9
11
  export { iconPickerKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/resizable-knobs.d.ts
2
- export declare const resizableKnobs: readonly ["--cui-resizable-group-background", "--cui-resizable-group-radius", "--cui-resizable-group-border-color", "--cui-resizable-group-border-width", "--cui-resizable-handle-color", "--cui-resizable-handle-hover-background", "--cui-resizable-handle-active-background", "--cui-resizable-grip-radius", "--cui-resizable-grip-background", "--cui-resizable-grip-foreground"];
2
+ export declare const resizableKnobs: readonly ["--cui-resizable-group-background", "--cui-resizable-group-radius", "--cui-resizable-group-border-color", "--cui-resizable-group-border-width", "--cui-resizable-handle-hover-background", "--cui-resizable-handle-active-background", "--cui-resizable-grip-radius", "--cui-resizable-grip-background", "--cui-resizable-grip-foreground", "--cui-resizable-handle-background"];
3
3
  export type ResizableKnobStyle = Partial<Record<(typeof resizableKnobs)[number], string>>;
4
4
  //#endregion
@@ -4,12 +4,12 @@ const resizableKnobs = [
4
4
  "--cui-resizable-group-radius",
5
5
  "--cui-resizable-group-border-color",
6
6
  "--cui-resizable-group-border-width",
7
- "--cui-resizable-handle-color",
8
7
  "--cui-resizable-handle-hover-background",
9
8
  "--cui-resizable-handle-active-background",
10
9
  "--cui-resizable-grip-radius",
11
10
  "--cui-resizable-grip-background",
12
- "--cui-resizable-grip-foreground"
11
+ "--cui-resizable-grip-foreground",
12
+ "--cui-resizable-handle-background"
13
13
  ];
14
14
  //#endregion
15
15
  export { resizableKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/sidebar-knobs.d.ts
2
- export declare const sidebarKnobs: readonly ["--cui-sidebar-nav-height", "--cui-sidebar-nav-background", "--cui-sidebar-nav-foreground", "--cui-sidebar-nav-border-color", "--cui-sidebar-nav-border-width", "--cui-sidebar-nav-shadow", "--cui-sidebar-nav-item-radius", "--cui-sidebar-nav-item-active-background", "--cui-sidebar-nav-item-active-foreground", "--cui-sidebar-nav-gap", "--cui-sidebar-menu-badge-height", "--cui-sidebar-menu-badge-background", "--cui-sidebar-menu-badge-foreground", "--cui-sidebar-rail-divider-background", "--cui-sidebar-wrapper-background", "--cui-sidebar-wrapper-background-image", "--cui-sidebar-inner-background", "--cui-sidebar-inner-border-color", "--cui-sidebar-inner-background-image", "--cui-sidebar-inner-backdrop-filter", "--cui-sidebar-inner-border-width", "--cui-sidebar-inner-radius", "--cui-sidebar-inner-shadow", "--cui-sidebar-header-background", "--cui-sidebar-header-shadow", "--cui-sidebar-inset-background", "--cui-sidebar-inset-background-image", "--cui-sidebar-inset-shadow", "--cui-sidebar-inset-border-color", "--cui-sidebar-inset-border-width", "--cui-sidebar-inset-radius", "--cui-sidebar-inset-inset", "--cui-sidebar-menu-button-radius", "--cui-sidebar-group-label-foreground", "--cui-sidebar-menu-button-foreground", "--cui-sidebar-menu-button-hover-background", "--cui-sidebar-menu-button-hover-foreground", "--cui-sidebar-menu-button-hover-shadow", "--cui-sidebar-menu-button-active-background", "--cui-sidebar-menu-button-active-foreground", "--cui-sidebar-menu-button-active-shadow", "--cui-sidebar-menu-button-track-active-foreground", "--cui-sidebar-menu-button-height", "--cui-sidebar-menu-button-padding-block", "--cui-sidebar-menu-button-padding-inline", "--cui-sidebar-menu-button-font-size", "--cui-sidebar-menu-button-font-weight", "--cui-sidebar-menu-button-active-font-weight", "--cui-sidebar-group-label-font-size", "--cui-sidebar-group-label-font-weight", "--cui-sidebar-group-label-letter-spacing", "--cui-sidebar-group-label-text-transform", "--cui-sidebar-group-label-padding", "--cui-sidebar-skip-link-background", "--cui-sidebar-skip-link-foreground", "--cui-sidebar-skip-link-radius", "--cui-sidebar-skip-link-shadow"];
2
+ export declare const sidebarKnobs: readonly ["--cui-sidebar-nav-height", "--cui-sidebar-nav-background", "--cui-sidebar-nav-foreground", "--cui-sidebar-nav-border-color", "--cui-sidebar-nav-border-width", "--cui-sidebar-nav-shadow", "--cui-sidebar-nav-item-radius", "--cui-sidebar-nav-item-active-background", "--cui-sidebar-nav-item-active-foreground", "--cui-sidebar-nav-gap", "--cui-sidebar-menu-badge-height", "--cui-sidebar-menu-badge-background", "--cui-sidebar-menu-badge-foreground", "--cui-sidebar-rail-divider-background", "--cui-sidebar-wrapper-background", "--cui-sidebar-wrapper-background-image", "--cui-sidebar-inner-background", "--cui-sidebar-inner-border-color", "--cui-sidebar-inner-background-image", "--cui-sidebar-inner-backdrop-filter", "--cui-sidebar-inner-border-width", "--cui-sidebar-inner-radius", "--cui-sidebar-inner-shadow", "--cui-sidebar-header-background", "--cui-sidebar-header-shadow", "--cui-sidebar-inset-background", "--cui-sidebar-inset-background-image", "--cui-sidebar-inset-shadow", "--cui-sidebar-inset-border-color", "--cui-sidebar-inset-border-width", "--cui-sidebar-inset-radius", "--cui-sidebar-inset-inset", "--cui-sidebar-menu-button-radius", "--cui-sidebar-group-label-foreground", "--cui-sidebar-menu-button-foreground", "--cui-sidebar-menu-button-hover-background", "--cui-sidebar-menu-button-hover-foreground", "--cui-sidebar-menu-button-hover-shadow", "--cui-sidebar-menu-button-active-background", "--cui-sidebar-menu-button-active-foreground", "--cui-sidebar-menu-button-active-shadow", "--cui-sidebar-menu-button-track-active-foreground", "--cui-sidebar-menu-button-height", "--cui-sidebar-menu-button-padding-block", "--cui-sidebar-menu-button-padding-inline", "--cui-sidebar-menu-button-font-size", "--cui-sidebar-menu-button-font-weight", "--cui-sidebar-menu-button-active-font-weight", "--cui-sidebar-group-label-font-size", "--cui-sidebar-group-label-font-weight", "--cui-sidebar-group-label-letter-spacing", "--cui-sidebar-group-label-text-transform", "--cui-sidebar-group-label-padding", "--cui-sidebar-skip-link-background", "--cui-sidebar-skip-link-foreground", "--cui-sidebar-skip-link-radius", "--cui-sidebar-skip-link-shadow", "--cui-sidebar-menu-button-background", "--cui-sidebar-menu-button-shadow"];
3
3
  export type SidebarKnobStyle = Partial<Record<(typeof sidebarKnobs)[number], string>>;
4
4
  //#endregion
@@ -56,7 +56,9 @@ const sidebarKnobs = [
56
56
  "--cui-sidebar-skip-link-background",
57
57
  "--cui-sidebar-skip-link-foreground",
58
58
  "--cui-sidebar-skip-link-radius",
59
- "--cui-sidebar-skip-link-shadow"
59
+ "--cui-sidebar-skip-link-shadow",
60
+ "--cui-sidebar-menu-button-background",
61
+ "--cui-sidebar-menu-button-shadow"
60
62
  ];
61
63
  //#endregion
62
64
  export { sidebarKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/tabs-knobs.d.ts
2
- export declare const tabsKnobs: readonly ["--cui-tabs-surface-background", "--cui-tabs-surface-radius", "--cui-tabs-trigger-radius", "--cui-tabs-list-padding", "--cui-tabs-list-radius", "--cui-tabs-list-background", "--cui-tabs-list-backdrop-filter", "--cui-tabs-indicator-background", "--cui-tabs-foreground", "--cui-tabs-active-foreground", "--cui-tabs-hover-foreground", "--cui-tabs-indicator-shadow", "--cui-tabs-list-shadow", "--cui-tabs-border-color", "--cui-tabs-border-width"];
2
+ export declare const tabsKnobs: readonly ["--cui-tabs-surface-background", "--cui-tabs-surface-radius", "--cui-tabs-trigger-radius", "--cui-tabs-list-padding", "--cui-tabs-list-radius", "--cui-tabs-list-background", "--cui-tabs-list-backdrop-filter", "--cui-tabs-indicator-background", "--cui-tabs-foreground", "--cui-tabs-active-foreground", "--cui-tabs-hover-foreground", "--cui-tabs-indicator-shadow", "--cui-tabs-list-shadow", "--cui-tabs-border-color", "--cui-tabs-border-width", "--cui-tabs-indicator-background-image"];
3
3
  export type TabsKnobStyle = Partial<Record<(typeof tabsKnobs)[number], string>>;
4
4
  //#endregion
@@ -14,7 +14,8 @@ const tabsKnobs = [
14
14
  "--cui-tabs-indicator-shadow",
15
15
  "--cui-tabs-list-shadow",
16
16
  "--cui-tabs-border-color",
17
- "--cui-tabs-border-width"
17
+ "--cui-tabs-border-width",
18
+ "--cui-tabs-indicator-background-image"
18
19
  ];
19
20
  //#endregion
20
21
  export { tabsKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/tree-knobs.d.ts
2
- export declare const treeKnobs: readonly ["--cui-tree-item-trigger-radius", "--cui-tree-item-trigger-foreground", "--cui-tree-item-trigger-hover-background", "--cui-tree-item-trigger-hover-foreground", "--cui-tree-item-trigger-selected-background", "--cui-tree-item-trigger-selected-foreground", "--cui-tree-item-trigger-font-size", "--cui-tree-item-trigger-selected-font-weight", "--cui-tree-indent-inset"];
2
+ export declare const treeKnobs: readonly ["--cui-tree-item-trigger-radius", "--cui-tree-item-trigger-foreground", "--cui-tree-item-trigger-hover-background", "--cui-tree-item-trigger-hover-foreground", "--cui-tree-item-trigger-selected-background", "--cui-tree-item-trigger-selected-foreground", "--cui-tree-item-trigger-font-size", "--cui-tree-item-trigger-selected-font-weight", "--cui-tree-indent-inset", "--cui-tree-item-trigger-background"];
3
3
  export type TreeKnobStyle = Partial<Record<(typeof treeKnobs)[number], string>>;
4
4
  //#endregion
@@ -8,7 +8,8 @@ const treeKnobs = [
8
8
  "--cui-tree-item-trigger-selected-foreground",
9
9
  "--cui-tree-item-trigger-font-size",
10
10
  "--cui-tree-item-trigger-selected-font-weight",
11
- "--cui-tree-indent-inset"
11
+ "--cui-tree-indent-inset",
12
+ "--cui-tree-item-trigger-background"
12
13
  ];
13
14
  //#endregion
14
15
  export { treeKnobs };
@@ -33,7 +33,7 @@ export type ChannelSpec = {
33
33
  max: number;
34
34
  step: number;
35
35
  };
36
- export declare function hsvaToRgba({ h, s, v, a }: Hsva): Rgba;
36
+ export declare function hsvaToRgba(hsva: Hsva): Rgba;
37
37
  export declare function rgbaToHsva({ r, g, b, a }: Rgba): Hsva;
38
38
  export declare function hsvaToHsla({ h, s, v, a }: Hsva): Hsla;
39
39
  export declare function hslaToHsva({ h, s, l, a }: Hsla): Hsva;
@@ -47,6 +47,7 @@ export declare function formatColor(hsva: Hsva, format: ColorFormat, opts?: {
47
47
  alpha?: boolean;
48
48
  }): string;
49
49
  export declare function parseColor(input: string): Hsva | null;
50
+ export declare function preserveAchromatic(next: Hsva, prev: Hsva): Hsva;
50
51
  export declare function getChannels(hsva: Hsva, format: ColorFormat): ChannelSpec[];
51
52
  export declare function setChannel(hsva: Hsva, id: ChannelId, value: number): Hsva;
52
53
  export declare function pointToSaturationValue(rect: {
@@ -56,11 +57,6 @@ export declare function pointToSaturationValue(rect: {
56
57
  s: number;
57
58
  v: number;
58
59
  };
59
- export type GradientKind = "linear" | "radial" | "conic";
60
- export declare function formatGradient(stops: {
61
- position: number;
62
- color: string;
63
- }[], type: GradientKind, angle: number): string;
64
60
  export declare function pointToHueSat(rect: {
65
61
  width: number;
66
62
  height: number;