@ctrl-ui/react 0.8.4 → 0.8.6

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 (134) hide show
  1. package/dist/audio-visualizer.js +1 -1
  2. package/dist/chat-composer-editor/extensions/mention.js +4 -0
  3. package/dist/chat-layout.d.ts +5 -0
  4. package/dist/chat-layout.js +61 -20
  5. package/dist/chat-message.d.ts +5 -0
  6. package/dist/chat-message.js +19 -2
  7. package/dist/context.js +0 -2
  8. package/dist/email/email-brand.d.ts +60 -0
  9. package/dist/email/email-brand.js +101 -0
  10. package/dist/email/email-code.d.ts +18 -0
  11. package/dist/email/email-code.js +172 -0
  12. package/dist/email/email-footer.d.ts +63 -0
  13. package/dist/email/email-footer.js +98 -0
  14. package/dist/email/email.d.ts +60 -11
  15. package/dist/email/email.js +155 -24
  16. package/dist/email/templates.d.ts +54 -9
  17. package/dist/email/templates.js +314 -116
  18. package/dist/email/theme.d.ts +13 -5
  19. package/dist/email/theme.js +30 -8
  20. package/dist/hooks/use-chat-message.d.ts +1 -0
  21. package/dist/hooks/use-chat-message.js +1 -0
  22. package/dist/hooks/use-chat-thread-scroll.d.ts +8 -0
  23. package/dist/hooks/use-chat-thread-scroll.js +66 -0
  24. package/dist/hooks/use-user-ask.d.ts +6 -4
  25. package/dist/hooks/use-user-ask.js +56 -17
  26. package/dist/inline-attachment.js +1 -1
  27. package/dist/knob-contracts/action-bar-knobs.d.ts +1 -1
  28. package/dist/knob-contracts/action-bar-knobs.js +1 -1
  29. package/dist/knob-contracts/activity-knobs.d.ts +1 -1
  30. package/dist/knob-contracts/activity-knobs.js +2 -1
  31. package/dist/knob-contracts/audio-visualizer-knobs.d.ts +1 -1
  32. package/dist/knob-contracts/audio-visualizer-knobs.js +1 -0
  33. package/dist/knob-contracts/chat-composer-attachment-knobs.d.ts +1 -1
  34. package/dist/knob-contracts/chat-composer-attachment-knobs.js +2 -0
  35. package/dist/knob-contracts/chat-composer-knobs.d.ts +1 -1
  36. package/dist/knob-contracts/chat-composer-knobs.js +1 -0
  37. package/dist/knob-contracts/chat-layout-knobs.d.ts +1 -1
  38. package/dist/knob-contracts/chat-layout-knobs.js +2 -1
  39. package/dist/knob-contracts/chat-message-knobs.d.ts +1 -1
  40. package/dist/knob-contracts/chat-message-knobs.js +3 -1
  41. package/dist/knob-contracts/context-knobs.d.ts +1 -1
  42. package/dist/knob-contracts/context-knobs.js +3 -0
  43. package/dist/knob-contracts/inline-attachment-knobs.d.ts +1 -1
  44. package/dist/knob-contracts/inline-attachment-knobs.js +4 -0
  45. package/dist/knob-contracts/inline-citation-knobs.d.ts +1 -1
  46. package/dist/knob-contracts/inline-citation-knobs.js +3 -1
  47. package/dist/knob-contracts/page-layout-knobs.d.ts +4 -0
  48. package/dist/knob-contracts/page-layout-knobs.js +16 -0
  49. package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
  50. package/dist/knob-contracts/table-of-contents-knobs.js +3 -3
  51. package/dist/knob-contracts/task-list-knobs.d.ts +1 -1
  52. package/dist/knob-contracts/task-list-knobs.js +4 -0
  53. package/dist/knob-contracts/user-ask-knobs.d.ts +1 -1
  54. package/dist/knob-contracts/user-ask-knobs.js +4 -0
  55. package/dist/lib/phone-input-format.js +1 -1
  56. package/dist/markdown-block.js +1 -1
  57. package/dist/styles/index.css +2 -1
  58. package/dist/styles/recipes/action-bar.css +37 -5
  59. package/dist/styles/recipes/activity.css +36 -3
  60. package/dist/styles/recipes/alert.css +2 -0
  61. package/dist/styles/recipes/audio-visualizer.css +8 -1
  62. package/dist/styles/recipes/button-group.css +8 -0
  63. package/dist/styles/recipes/button.css +15 -0
  64. package/dist/styles/recipes/calendar.css +21 -0
  65. package/dist/styles/recipes/card.css +2 -0
  66. package/dist/styles/recipes/chat-composer-attachment.css +33 -2
  67. package/dist/styles/recipes/chat-composer.css +16 -2
  68. package/dist/styles/recipes/chat-layout.css +25 -1
  69. package/dist/styles/recipes/chat-message.css +69 -2
  70. package/dist/styles/recipes/choice.css +12 -0
  71. package/dist/styles/recipes/code-diff.css +1 -0
  72. package/dist/styles/recipes/code.css +25 -0
  73. package/dist/styles/recipes/context.css +30 -18
  74. package/dist/styles/recipes/dynamic-notification-input.css +6 -0
  75. package/dist/styles/recipes/dynamic-notification.css +1 -0
  76. package/dist/styles/recipes/environment-variables.css +1 -0
  77. package/dist/styles/recipes/field-parts.css +2 -0
  78. package/dist/styles/recipes/field.css +6 -0
  79. package/dist/styles/recipes/gradient-editor.css +17 -0
  80. package/dist/styles/recipes/inline-attachment.css +57 -14
  81. package/dist/styles/recipes/inline-citation.css +44 -6
  82. package/dist/styles/recipes/item.css +3 -1
  83. package/dist/styles/recipes/markdown-block.css +1 -0
  84. package/dist/styles/recipes/markdown.css +7 -0
  85. package/dist/styles/recipes/page-layout.css +219 -0
  86. package/dist/styles/recipes/pagination.css +16 -0
  87. package/dist/styles/recipes/popup-drawer.css +3 -1
  88. package/dist/styles/recipes/popup-toast.css +2 -0
  89. package/dist/styles/recipes/popup.css +8 -12
  90. package/dist/styles/recipes/range.css +24 -2
  91. package/dist/styles/recipes/rich-tooltip.css +1 -0
  92. package/dist/styles/recipes/source-badge.css +20 -0
  93. package/dist/styles/recipes/table-of-contents.css +10 -10
  94. package/dist/styles/recipes/tabs.css +16 -0
  95. package/dist/styles/recipes/task-list.css +61 -8
  96. package/dist/styles/recipes/thread-rail.css +19 -13
  97. package/dist/styles/recipes/toolbar.css +21 -0
  98. package/dist/styles/recipes/transcript-divider.css +1 -0
  99. package/dist/styles/recipes/user-ask.css +59 -16
  100. package/dist/styles/theme.css +34 -0
  101. package/dist/thread-rail.js +1 -1
  102. package/dist/ui/alert-dialog.js +2 -2
  103. package/dist/ui/autocomplete.js +1 -1
  104. package/dist/ui/color-picker.js +3 -3
  105. package/dist/ui/combobox.js +1 -1
  106. package/dist/ui/command.d.ts +5 -3
  107. package/dist/ui/command.js +27 -3
  108. package/dist/ui/context-menu.js +2 -2
  109. package/dist/ui/dialog.js +2 -2
  110. package/dist/ui/drawer.js +2 -2
  111. package/dist/ui/dropdown-menu.js +1 -1
  112. package/dist/ui/dropzone.js +4 -1
  113. package/dist/ui/gradient-editor.js +2 -2
  114. package/dist/ui/hover-card.js +1 -1
  115. package/dist/ui/infinite-canvas.js +1 -0
  116. package/dist/ui/menubar.js +2 -2
  117. package/dist/ui/navigation-menu.js +1 -1
  118. package/dist/ui/number-field.js +1 -1
  119. package/dist/ui/page-layout.d.ts +44 -0
  120. package/dist/ui/page-layout.js +108 -0
  121. package/dist/ui/phone-input.js +4 -4
  122. package/dist/ui/popover.js +1 -1
  123. package/dist/ui/resizable.js +1 -1
  124. package/dist/ui/rich-tooltip.js +1 -1
  125. package/dist/ui/select.js +1 -1
  126. package/dist/ui/sheet.js +2 -2
  127. package/dist/ui/sidebar-resize-rail.js +1 -1
  128. package/dist/ui/slider.js +1 -1
  129. package/dist/ui/toast.js +2 -2
  130. package/dist/ui/tooltip.js +1 -1
  131. package/dist/ui/trigger-menu.js +1 -1
  132. package/dist/user-ask.d.ts +5 -3
  133. package/dist/user-ask.js +38 -13
  134. package/package.json +3 -2
@@ -0,0 +1,66 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ //#region src/hooks/use-chat-thread-scroll.ts
3
+ const BOTTOM_THRESHOLD = 24;
4
+ const SETTLE_TIMEOUT = 700;
5
+ function useChatThreadScroll() {
6
+ const viewportRef = useRef(null);
7
+ const contentRef = useRef(null);
8
+ const pinnedRef = useRef(true);
9
+ const [atBottom, setAtBottom] = useState(true);
10
+ const settlingRef = useRef(void 0);
11
+ function scrollToBottom(behavior = "smooth") {
12
+ const viewport = viewportRef.current;
13
+ if (!viewport) return;
14
+ pinnedRef.current = true;
15
+ setAtBottom(true);
16
+ clearTimeout(settlingRef.current);
17
+ settlingRef.current = setTimeout(() => {
18
+ settlingRef.current = void 0;
19
+ }, SETTLE_TIMEOUT);
20
+ viewport.scrollTo({
21
+ top: viewport.scrollHeight,
22
+ behavior
23
+ });
24
+ }
25
+ useEffect(() => {
26
+ const viewport = viewportRef.current;
27
+ const content = contentRef.current;
28
+ if (!viewport || !content) return;
29
+ function settle() {
30
+ clearTimeout(settlingRef.current);
31
+ settlingRef.current = void 0;
32
+ readPosition();
33
+ }
34
+ function readPosition() {
35
+ if (!viewport || settlingRef.current) return;
36
+ const distance = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
37
+ pinnedRef.current = distance <= BOTTOM_THRESHOLD;
38
+ setAtBottom(pinnedRef.current);
39
+ }
40
+ const observer = new ResizeObserver(() => {
41
+ if (!viewport) return;
42
+ if (pinnedRef.current) viewport.scrollTop = viewport.scrollHeight;
43
+ else readPosition();
44
+ });
45
+ observer.observe(content);
46
+ observer.observe(viewport);
47
+ viewport.addEventListener("scroll", readPosition, { passive: true });
48
+ viewport.addEventListener("scrollend", settle);
49
+ viewport.scrollTop = viewport.scrollHeight;
50
+ readPosition();
51
+ return () => {
52
+ observer.disconnect();
53
+ clearTimeout(settlingRef.current);
54
+ viewport.removeEventListener("scroll", readPosition);
55
+ viewport.removeEventListener("scrollend", settle);
56
+ };
57
+ }, []);
58
+ return {
59
+ viewportRef,
60
+ contentRef,
61
+ atBottom,
62
+ scrollToBottom
63
+ };
64
+ }
65
+ //#endregion
66
+ export { useChatThreadScroll };
@@ -1,7 +1,7 @@
1
1
  import { UserAskKnobStyle } from "../knob-contracts/user-ask-knobs.js";
2
2
  import { CSSProperties, ComponentProps, KeyboardEvent, ReactNode } from "react";
3
3
  //#region src/hooks/use-user-ask.d.ts
4
- export type UserAskAnswers = Record<string, string>;
4
+ export type UserAskAnswers = Record<string, string | string[]>;
5
5
  export type UserAskProps = Omit<ComponentProps<"section">, "style"> & {
6
6
  children?: ReactNode;
7
7
  onComplete?: (answers: UserAskAnswers) => void;
@@ -12,7 +12,8 @@ export type UserAskQuestionEntry = {
12
12
  key: string;
13
13
  id: string;
14
14
  title: string;
15
- defaultValue?: string;
15
+ multiple?: boolean;
16
+ defaultValues?: string[];
16
17
  };
17
18
  export type UserAskOptionEntry = {
18
19
  key: string;
@@ -32,12 +33,13 @@ export declare function useUserAsk({ onComplete, onDismiss }: Pick<UserAskProps,
32
33
  registerOption: (questionId: string, entry: UserAskOptionEntry) => void;
33
34
  unregisterOption: (questionId: string, key: string) => void;
34
35
  optionsFor: (questionId: string) => UserAskOptionEntry[];
35
- selectionFor: (questionId: string) => string | undefined;
36
+ allowsMultiple: (questionId: string) => boolean;
37
+ selectionFor: (questionId: string) => string;
36
38
  isSelected: (questionId: string, optionKey: string) => boolean;
37
39
  select: (questionId: string, optionKey: string) => void;
38
40
  freeformTextFor: (questionId: string) => string;
39
41
  setFreeformText: (questionId: string, text: string) => void;
40
- answerFor: (questionId: string) => string | undefined;
42
+ answerFor: (questionId: string) => string | string[] | undefined;
41
43
  resolveAnswers: () => UserAskAnswers;
42
44
  goTo: (index: number) => void;
43
45
  advance: () => void;
@@ -3,6 +3,7 @@ import { useState } from "react";
3
3
  function upsert(entries, entry) {
4
4
  const index = entries.findIndex((existing) => existing.key === entry.key);
5
5
  if (index === -1) return [...entries, entry];
6
+ if (JSON.stringify(entries[index]) === JSON.stringify(entry)) return entries;
6
7
  const next = [...entries];
7
8
  next[index] = entry;
8
9
  return next;
@@ -36,21 +37,39 @@ function useUserAsk({ onComplete, onDismiss }) {
36
37
  function optionsFor(questionId) {
37
38
  return optionsByQuestion[questionId] ?? [];
38
39
  }
39
- function selectionFor(questionId) {
40
+ function allowsMultiple(questionId) {
41
+ return questions.find((question) => question.id === questionId)?.multiple === true;
42
+ }
43
+ function selectedKeysFor(questionId) {
40
44
  const explicit = selections[questionId];
41
45
  if (explicit) return explicit;
42
- const defaultValue = questions.find((question) => question.id === questionId)?.defaultValue;
43
- if (defaultValue === void 0) return void 0;
44
- return optionsFor(questionId).find((option) => !option.freeform && option.value === defaultValue)?.key;
46
+ const defaults = questions.find((question) => question.id === questionId)?.defaultValues;
47
+ if (defaults === void 0) return [];
48
+ return optionsFor(questionId).filter((option) => !option.freeform && defaults.includes(option.value)).map((option) => option.key);
49
+ }
50
+ function selectionFor(questionId) {
51
+ return selectedKeysFor(questionId)[0];
45
52
  }
46
53
  function isSelected(questionId, optionKey) {
47
- return selectionFor(questionId) === optionKey;
54
+ return selectedKeysFor(questionId).includes(optionKey);
48
55
  }
49
56
  function select(questionId, optionKey) {
50
- setSelections((previous) => ({
51
- ...previous,
52
- [questionId]: optionKey
53
- }));
57
+ if (!allowsMultiple(questionId)) {
58
+ setSelections((previous) => ({
59
+ ...previous,
60
+ [questionId]: [optionKey]
61
+ }));
62
+ return;
63
+ }
64
+ const derived = selectedKeysFor(questionId);
65
+ setSelections((previous) => {
66
+ const current = previous[questionId] ?? derived;
67
+ const next = current.includes(optionKey) ? current.filter((entry) => entry !== optionKey) : [...current, optionKey];
68
+ return {
69
+ ...previous,
70
+ [questionId]: next
71
+ };
72
+ });
54
73
  }
55
74
  function freeformTextFor(questionId) {
56
75
  return freeformTexts[questionId] ?? "";
@@ -62,12 +81,17 @@ function useUserAsk({ onComplete, onDismiss }) {
62
81
  }));
63
82
  }
64
83
  function answerFor(questionId) {
65
- const selectedKey = selectionFor(questionId);
66
- const option = optionsFor(questionId).find((entry) => entry.key === selectedKey);
67
- if (!option) return void 0;
68
- if (!option.freeform) return option.value;
69
- const text = freeformTextFor(questionId).trim();
70
- return text.length > 0 ? text : void 0;
84
+ const options = optionsFor(questionId);
85
+ const resolve = (optionKey) => {
86
+ const option = options.find((entry) => entry.key === optionKey);
87
+ if (!option) return void 0;
88
+ if (!option.freeform) return option.value;
89
+ const text = freeformTextFor(questionId).trim();
90
+ return text.length > 0 ? text : void 0;
91
+ };
92
+ const values = selectedKeysFor(questionId).map(resolve).filter((value) => value !== void 0);
93
+ if (!allowsMultiple(questionId)) return values[0];
94
+ return values.length > 0 ? values : void 0;
71
95
  }
72
96
  const canContinue = activeQuestion !== void 0 && answerFor(activeQuestion.id) !== void 0;
73
97
  const isLastQuestion = activeIndex === questions.length - 1;
@@ -111,6 +135,20 @@ function useUserAsk({ onComplete, onDismiss }) {
111
135
  const option = optionsFor(activeQuestion.id)[digit - 1];
112
136
  if (option && !option.disabled) select(activeQuestion.id, option.key);
113
137
  }
138
+ function moveActiveOption(event, delta) {
139
+ if (!activeQuestion) return;
140
+ if (!allowsMultiple(activeQuestion.id)) {
141
+ moveSelection(delta);
142
+ return;
143
+ }
144
+ const rows = [...event.currentTarget.querySelector("[data-slot=\"question\"][data-active]")?.querySelectorAll("[data-slot=\"option\"]:not([disabled])") ?? []];
145
+ if (rows.length === 0) return;
146
+ const focused = rows.findIndex((candidate) => candidate.contains(document.activeElement));
147
+ let start = focused;
148
+ if (focused === -1) start = delta > 0 ? -1 : 0;
149
+ const row = rows[(start + delta + rows.length) % rows.length];
150
+ (row?.matches("button, input") ? row : row?.querySelector("input, button"))?.focus();
151
+ }
114
152
  function handleKeyDown(event) {
115
153
  if (event.defaultPrevented) return;
116
154
  if (event.key === "Escape") {
@@ -126,12 +164,12 @@ function useUserAsk({ onComplete, onDismiss }) {
126
164
  if (event.target instanceof HTMLElement && event.target.closest("input, textarea, [contenteditable]")) return;
127
165
  if (event.key === "ArrowDown") {
128
166
  event.preventDefault();
129
- moveSelection(1);
167
+ moveActiveOption(event, 1);
130
168
  return;
131
169
  }
132
170
  if (event.key === "ArrowUp") {
133
171
  event.preventDefault();
134
- moveSelection(-1);
172
+ moveActiveOption(event, -1);
135
173
  return;
136
174
  }
137
175
  if (/^[1-9]$/.test(event.key)) {
@@ -150,6 +188,7 @@ function useUserAsk({ onComplete, onDismiss }) {
150
188
  registerOption,
151
189
  unregisterOption,
152
190
  optionsFor,
191
+ allowsMultiple,
153
192
  selectionFor,
154
193
  isSelected,
155
194
  select,
@@ -146,7 +146,7 @@ function InlineAttachmentContent({ className, ...props }) {
146
146
  "data-control-ui": "inline-attachment",
147
147
  "data-control-family": "inline-attachment",
148
148
  "data-slot": "content",
149
- className: cn("absolute inset-x-3 bottom-3", className),
149
+ className: cn("absolute", className),
150
150
  ...props
151
151
  });
152
152
  }
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/action-bar-knobs.d.ts
2
- export declare const actionBarKnobs: readonly [];
2
+ export declare const actionBarKnobs: readonly ["--cui-action-bar-hidden-opacity", "--cui-action-bar-visible-opacity"];
3
3
  export type ActionBarKnobStyle = Partial<Record<(typeof actionBarKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/action-bar-knobs.ts
2
- const actionBarKnobs = [];
2
+ const actionBarKnobs = ["--cui-action-bar-hidden-opacity", "--cui-action-bar-visible-opacity"];
3
3
  //#endregion
4
4
  export { actionBarKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/activity-knobs.d.ts
2
- export declare const activityKnobs: readonly ["--cui-activity-row-foreground", "--cui-activity-trigger-radius", "--cui-activity-trigger-hover-background", "--cui-activity-code-background"];
2
+ export declare const activityKnobs: readonly ["--cui-activity-row-foreground", "--cui-activity-trigger-radius", "--cui-activity-trigger-hover-background", "--cui-activity-code-background", "--cui-activity-code-radius"];
3
3
  export type ActivityKnobStyle = Partial<Record<(typeof activityKnobs)[number], string>>;
4
4
  //#endregion
@@ -3,7 +3,8 @@ const activityKnobs = [
3
3
  "--cui-activity-row-foreground",
4
4
  "--cui-activity-trigger-radius",
5
5
  "--cui-activity-trigger-hover-background",
6
- "--cui-activity-code-background"
6
+ "--cui-activity-code-background",
7
+ "--cui-activity-code-radius"
7
8
  ];
8
9
  //#endregion
9
10
  export { activityKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/audio-visualizer-knobs.d.ts
2
- export declare const audioVisualizerKnobs: readonly ["--cui-audio-visualizer-radius", "--cui-audio-visualizer-bar-background", "--cui-audio-visualizer-line-fill", "--cui-audio-visualizer-line-stroke"];
2
+ export declare const audioVisualizerKnobs: readonly ["--cui-audio-visualizer-radius", "--cui-audio-visualizer-bar-radius", "--cui-audio-visualizer-bar-background", "--cui-audio-visualizer-line-fill", "--cui-audio-visualizer-line-stroke"];
3
3
  export type AudioVisualizerKnobStyle = Partial<Record<(typeof audioVisualizerKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,6 +1,7 @@
1
1
  //#region src/knob-contracts/audio-visualizer-knobs.ts
2
2
  const audioVisualizerKnobs = [
3
3
  "--cui-audio-visualizer-radius",
4
+ "--cui-audio-visualizer-bar-radius",
4
5
  "--cui-audio-visualizer-bar-background",
5
6
  "--cui-audio-visualizer-line-fill",
6
7
  "--cui-audio-visualizer-line-stroke"
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/chat-composer-attachment-knobs.d.ts
2
- export declare const chatComposerAttachmentKnobs: readonly ["--cui-chat-composer-attachment-radius", "--cui-chat-composer-attachment-background", "--cui-chat-composer-attachment-border-color", "--cui-chat-composer-attachment-shadow", "--cui-chat-composer-attachment-backdrop-filter", "--cui-chat-composer-attachment-progress-background", "--cui-chat-composer-attachment-progress-foreground", "--cui-chat-composer-attachment-image-outline-color"];
2
+ export declare const chatComposerAttachmentKnobs: readonly ["--cui-chat-composer-attachment-radius", "--cui-chat-composer-attachment-height", "--cui-chat-composer-attachment-list-padding", "--cui-chat-composer-attachment-background", "--cui-chat-composer-attachment-border-color", "--cui-chat-composer-attachment-shadow", "--cui-chat-composer-attachment-backdrop-filter", "--cui-chat-composer-attachment-progress-background", "--cui-chat-composer-attachment-progress-foreground", "--cui-chat-composer-attachment-image-outline-color"];
3
3
  export type ChatComposerAttachmentKnobStyle = Partial<Record<(typeof chatComposerAttachmentKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,6 +1,8 @@
1
1
  //#region src/knob-contracts/chat-composer-attachment-knobs.ts
2
2
  const chatComposerAttachmentKnobs = [
3
3
  "--cui-chat-composer-attachment-radius",
4
+ "--cui-chat-composer-attachment-height",
5
+ "--cui-chat-composer-attachment-list-padding",
4
6
  "--cui-chat-composer-attachment-background",
5
7
  "--cui-chat-composer-attachment-border-color",
6
8
  "--cui-chat-composer-attachment-shadow",
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/chat-composer-knobs.d.ts
2
- export declare const chatComposerKnobs: readonly ["--cui-chat-composer-root-background", "--cui-chat-composer-shell-radius", "--cui-chat-composer-shell-background", "--cui-chat-composer-shell-background-image", "--cui-chat-composer-shell-backdrop-filter", "--cui-chat-composer-shell-border-color", "--cui-chat-composer-shell-border-width", "--cui-chat-composer-shell-shadow", "--cui-chat-composer-input-foreground", "--cui-chat-composer-input-placeholder-foreground", "--cui-chat-composer-mention-background", "--cui-chat-composer-mention-radius", "--cui-chat-composer-mention-border-color", "--cui-chat-composer-mention-border-width"];
2
+ export declare const chatComposerKnobs: readonly ["--cui-chat-composer-root-background", "--cui-chat-composer-shell-radius", "--cui-chat-composer-shell-background", "--cui-chat-composer-shell-background-image", "--cui-chat-composer-shell-backdrop-filter", "--cui-chat-composer-shell-border-color", "--cui-chat-composer-shell-border-width", "--cui-chat-composer-shell-shadow", "--cui-chat-composer-input-foreground", "--cui-chat-composer-input-placeholder-foreground", "--cui-chat-composer-mention-background", "--cui-chat-composer-mention-radius", "--cui-chat-composer-mention-icon-radius", "--cui-chat-composer-mention-border-color", "--cui-chat-composer-mention-border-width"];
3
3
  export type ChatComposerKnobStyle = Partial<Record<(typeof chatComposerKnobs)[number], string>>;
4
4
  //#endregion
@@ -12,6 +12,7 @@ const chatComposerKnobs = [
12
12
  "--cui-chat-composer-input-placeholder-foreground",
13
13
  "--cui-chat-composer-mention-background",
14
14
  "--cui-chat-composer-mention-radius",
15
+ "--cui-chat-composer-mention-icon-radius",
15
16
  "--cui-chat-composer-mention-border-color",
16
17
  "--cui-chat-composer-mention-border-width"
17
18
  ];
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/chat-layout-knobs.d.ts
2
- export declare const chatLayoutKnobs: readonly ["--cui-chat-layout-radius", "--cui-chat-layout-background", "--cui-chat-layout-border-color", "--cui-chat-layout-border-width", "--cui-chat-layout-shadow"];
2
+ export declare const chatLayoutKnobs: readonly ["--cui-chat-layout-radius", "--cui-chat-layout-background", "--cui-chat-layout-border-color", "--cui-chat-layout-border-width", "--cui-chat-layout-shadow", "--cui-chat-layout-scroll-button-gap"];
3
3
  export type ChatLayoutKnobStyle = Partial<Record<(typeof chatLayoutKnobs)[number], string>>;
4
4
  //#endregion
@@ -4,7 +4,8 @@ const chatLayoutKnobs = [
4
4
  "--cui-chat-layout-background",
5
5
  "--cui-chat-layout-border-color",
6
6
  "--cui-chat-layout-border-width",
7
- "--cui-chat-layout-shadow"
7
+ "--cui-chat-layout-shadow",
8
+ "--cui-chat-layout-scroll-button-gap"
8
9
  ];
9
10
  //#endregion
10
11
  export { chatLayoutKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/chat-message-knobs.d.ts
2
- export declare const chatMessageKnobs: readonly ["--cui-chat-message-avatar-radius", "--cui-chat-message-avatar-background", "--cui-chat-message-avatar-border-color", "--cui-chat-message-avatar-border-width", "--cui-chat-message-radius", "--cui-chat-message-corner-radius", "--cui-chat-message-background", "--cui-chat-message-background-image", "--cui-chat-message-foreground", "--cui-chat-message-border-color", "--cui-chat-message-border-width", "--cui-chat-message-shadow"];
2
+ export declare const chatMessageKnobs: readonly ["--cui-chat-message-avatar-radius", "--cui-chat-message-avatar-background", "--cui-chat-message-avatar-border-color", "--cui-chat-message-avatar-border-width", "--cui-chat-message-radius", "--cui-chat-message-corner-radius", "--cui-chat-message-background", "--cui-chat-message-background-image", "--cui-chat-message-foreground", "--cui-chat-message-border-color", "--cui-chat-message-border-width", "--cui-chat-message-shadow", "--cui-chat-message-pending-dot-color", "--cui-chat-message-pending-dot-size"];
3
3
  export type ChatMessageKnobStyle = Partial<Record<(typeof chatMessageKnobs)[number], string>>;
4
4
  //#endregion
@@ -11,7 +11,9 @@ const chatMessageKnobs = [
11
11
  "--cui-chat-message-foreground",
12
12
  "--cui-chat-message-border-color",
13
13
  "--cui-chat-message-border-width",
14
- "--cui-chat-message-shadow"
14
+ "--cui-chat-message-shadow",
15
+ "--cui-chat-message-pending-dot-color",
16
+ "--cui-chat-message-pending-dot-size"
15
17
  ];
16
18
  //#endregion
17
19
  export { chatMessageKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/context-knobs.d.ts
2
- export declare const contextKnobs: readonly ["--cui-context-graph-radius", "--cui-context-track-fill", "--cui-context-segment-tool-fill", "--cui-context-segment-message-fill", "--cui-context-segment-source-fill", "--cui-context-segment-reasoning-fill", "--cui-context-overage-fill", "--cui-context-limit-marker-color"];
2
+ export declare const contextKnobs: readonly ["--cui-context-graph-radius", "--cui-context-legend-indicator-radius", "--cui-context-segment-system-fill", "--cui-context-segment-cache-fill", "--cui-context-track-fill", "--cui-context-segment-tool-fill", "--cui-context-segment-message-fill", "--cui-context-segment-source-fill", "--cui-context-segment-reasoning-fill", "--cui-context-overage-fill", "--cui-context-limit-marker-color"];
3
3
  export type ContextKnobStyle = Partial<Record<(typeof contextKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,6 +1,9 @@
1
1
  //#region src/knob-contracts/context-knobs.ts
2
2
  const contextKnobs = [
3
3
  "--cui-context-graph-radius",
4
+ "--cui-context-legend-indicator-radius",
5
+ "--cui-context-segment-system-fill",
6
+ "--cui-context-segment-cache-fill",
4
7
  "--cui-context-track-fill",
5
8
  "--cui-context-segment-tool-fill",
6
9
  "--cui-context-segment-message-fill",
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/inline-attachment-knobs.d.ts
2
- export declare const inlineAttachmentKnobs: readonly ["--cui-inline-attachment-radius", "--cui-inline-attachment-background", "--cui-inline-attachment-ring-color", "--cui-inline-attachment-shadow", "--cui-inline-attachment-hover-shadow", "--cui-inline-attachment-content-radius", "--cui-inline-attachment-content-background", "--cui-inline-attachment-content-foreground", "--cui-inline-attachment-content-shadow", "--cui-inline-attachment-image-outline-color"];
2
+ export declare const inlineAttachmentKnobs: readonly ["--cui-inline-attachment-radius", "--cui-inline-attachment-background", "--cui-inline-attachment-ring-color", "--cui-inline-attachment-padding", "--cui-inline-attachment-document-padding", "--cui-inline-attachment-document-background", "--cui-inline-attachment-document-background-image", "--cui-inline-attachment-shadow", "--cui-inline-attachment-hover-shadow", "--cui-inline-attachment-content-radius", "--cui-inline-attachment-content-background", "--cui-inline-attachment-content-foreground", "--cui-inline-attachment-content-shadow", "--cui-inline-attachment-image-outline-color"];
3
3
  export type InlineAttachmentKnobStyle = Partial<Record<(typeof inlineAttachmentKnobs)[number], string>>;
4
4
  //#endregion
@@ -3,6 +3,10 @@ const inlineAttachmentKnobs = [
3
3
  "--cui-inline-attachment-radius",
4
4
  "--cui-inline-attachment-background",
5
5
  "--cui-inline-attachment-ring-color",
6
+ "--cui-inline-attachment-padding",
7
+ "--cui-inline-attachment-document-padding",
8
+ "--cui-inline-attachment-document-background",
9
+ "--cui-inline-attachment-document-background-image",
6
10
  "--cui-inline-attachment-shadow",
7
11
  "--cui-inline-attachment-hover-shadow",
8
12
  "--cui-inline-attachment-content-radius",
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/inline-citation-knobs.d.ts
2
- export declare const inlineCitationKnobs: readonly ["--cui-inline-citation-trigger-radius", "--cui-inline-citation-trigger-background", "--cui-inline-citation-trigger-foreground", "--cui-inline-citation-trigger-border-color", "--cui-inline-citation-trigger-border-width", "--cui-inline-citation-trigger-hover-background", "--cui-inline-citation-trigger-hover-foreground", "--cui-inline-citation-navigation-background", "--cui-inline-citation-quote-background", "--cui-inline-citation-quote-radius"];
2
+ export declare const inlineCitationKnobs: readonly ["--cui-inline-citation-trigger-radius", "--cui-inline-citation-trigger-background", "--cui-inline-citation-trigger-foreground", "--cui-inline-citation-trigger-border-color", "--cui-inline-citation-trigger-border-width", "--cui-inline-citation-trigger-hover-background", "--cui-inline-citation-trigger-hover-foreground", "--cui-inline-citation-navigation-background", "--cui-inline-citation-quote-background", "--cui-inline-citation-quote-radius", "--cui-inline-citation-favicon-background", "--cui-inline-citation-favicon-radius"];
3
3
  export type InlineCitationKnobStyle = Partial<Record<(typeof inlineCitationKnobs)[number], string>>;
4
4
  //#endregion
@@ -9,7 +9,9 @@ const inlineCitationKnobs = [
9
9
  "--cui-inline-citation-trigger-hover-foreground",
10
10
  "--cui-inline-citation-navigation-background",
11
11
  "--cui-inline-citation-quote-background",
12
- "--cui-inline-citation-quote-radius"
12
+ "--cui-inline-citation-quote-radius",
13
+ "--cui-inline-citation-favicon-background",
14
+ "--cui-inline-citation-favicon-radius"
13
15
  ];
14
16
  //#endregion
15
17
  export { inlineCitationKnobs };
@@ -0,0 +1,4 @@
1
+ //#region src/knob-contracts/page-layout-knobs.d.ts
2
+ export declare const pageLayoutKnobs: readonly ["--cui-page-layout-article-size", "--cui-page-layout-aside-size", "--cui-page-layout-padding-inline", "--cui-page-layout-padding-block", "--cui-page-layout-column-gap", "--cui-page-layout-header-start-gap", "--cui-page-layout-header-gap", "--cui-page-layout-header-column-gap", "--cui-page-layout-header-row-gap", "--cui-page-layout-size", "--cui-page-layout-sticky-gap"];
3
+ export type PageLayoutKnobStyle = Partial<Record<(typeof pageLayoutKnobs)[number], string>>;
4
+ //#endregion
@@ -0,0 +1,16 @@
1
+ //#region src/knob-contracts/page-layout-knobs.ts
2
+ const pageLayoutKnobs = [
3
+ "--cui-page-layout-article-size",
4
+ "--cui-page-layout-aside-size",
5
+ "--cui-page-layout-padding-inline",
6
+ "--cui-page-layout-padding-block",
7
+ "--cui-page-layout-column-gap",
8
+ "--cui-page-layout-header-start-gap",
9
+ "--cui-page-layout-header-gap",
10
+ "--cui-page-layout-header-column-gap",
11
+ "--cui-page-layout-header-row-gap",
12
+ "--cui-page-layout-size",
13
+ "--cui-page-layout-sticky-gap"
14
+ ];
15
+ //#endregion
16
+ export { pageLayoutKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/table-of-contents-knobs.d.ts
2
- export declare const tableOfContentsKnobs: readonly ["--cui-table-of-contents-background", "--cui-table-of-contents-border-color", "--cui-table-of-contents-border-width", "--cui-table-of-contents-radius", "--cui-table-of-contents-shadow", "--cui-table-of-contents-backdrop-filter", "--cui-table-of-contents-padding", "--cui-table-of-contents-label-foreground", "--cui-table-of-contents-label-font-size", "--cui-table-of-contents-label-font-weight", "--cui-table-of-contents-label-gap", "--cui-table-of-contents-item-foreground", "--cui-table-of-contents-item-hover-foreground", "--cui-table-of-contents-item-active-foreground", "--cui-table-of-contents-item-font-size", "--cui-table-of-contents-item-line-height", "--cui-table-of-contents-item-font-weight", "--cui-table-of-contents-item-root-font-weight", "--cui-table-of-contents-item-padding-block", "--cui-table-of-contents-item-padding-inline", "--cui-table-of-contents-item-indent", "--cui-table-of-contents-rail-background", "--cui-table-of-contents-rail-width", "--cui-table-of-contents-trail-background", "--cui-table-of-contents-trail-width", "--cui-table-of-contents-trail-radius", "--cui-table-of-contents-highlight-radius", "--cui-table-of-contents-highlight-background"];
2
+ export declare const tableOfContentsKnobs: readonly ["--cui-table-of-contents-background", "--cui-table-of-contents-border-color", "--cui-table-of-contents-border-width", "--cui-table-of-contents-radius", "--cui-table-of-contents-shadow", "--cui-table-of-contents-backdrop-filter", "--cui-table-of-contents-padding", "--cui-table-of-contents-label-foreground", "--cui-table-of-contents-label-font-size", "--cui-table-of-contents-label-font-weight", "--cui-table-of-contents-label-gap", "--cui-table-of-contents-item-foreground", "--cui-table-of-contents-item-hover-foreground", "--cui-table-of-contents-item-active-foreground", "--cui-table-of-contents-item-font-size", "--cui-table-of-contents-item-line-height", "--cui-table-of-contents-item-font-weight", "--cui-table-of-contents-item-root-font-weight", "--cui-table-of-contents-item-padding-block", "--cui-table-of-contents-item-padding-inline", "--cui-table-of-contents-item-indent-size", "--cui-table-of-contents-rail-background", "--cui-table-of-contents-rail-size", "--cui-table-of-contents-trail-background", "--cui-table-of-contents-trail-size", "--cui-table-of-contents-trail-radius", "--cui-table-of-contents-highlight-radius", "--cui-table-of-contents-highlight-background"];
3
3
  export type TableOfContentsKnobStyle = Partial<Record<(typeof tableOfContentsKnobs)[number], string>>;
4
4
  //#endregion
@@ -20,11 +20,11 @@ const tableOfContentsKnobs = [
20
20
  "--cui-table-of-contents-item-root-font-weight",
21
21
  "--cui-table-of-contents-item-padding-block",
22
22
  "--cui-table-of-contents-item-padding-inline",
23
- "--cui-table-of-contents-item-indent",
23
+ "--cui-table-of-contents-item-indent-size",
24
24
  "--cui-table-of-contents-rail-background",
25
- "--cui-table-of-contents-rail-width",
25
+ "--cui-table-of-contents-rail-size",
26
26
  "--cui-table-of-contents-trail-background",
27
- "--cui-table-of-contents-trail-width",
27
+ "--cui-table-of-contents-trail-size",
28
28
  "--cui-table-of-contents-trail-radius",
29
29
  "--cui-table-of-contents-highlight-radius",
30
30
  "--cui-table-of-contents-highlight-background"
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/task-list-knobs.d.ts
2
- export declare const taskListKnobs: readonly ["--cui-task-list-radius", "--cui-task-list-background", "--cui-task-list-foreground", "--cui-task-list-border-color", "--cui-task-list-border-width", "--cui-task-list-shadow", "--cui-task-list-item-foreground", "--cui-task-list-item-pending-foreground", "--cui-task-list-indicator-foreground", "--cui-task-list-indicator-active-foreground"];
2
+ export declare const taskListKnobs: readonly ["--cui-task-list-radius", "--cui-task-list-ring-color", "--cui-task-list-items-padding", "--cui-task-list-item-radius", "--cui-task-list-trigger-hover-background", "--cui-task-list-background", "--cui-task-list-foreground", "--cui-task-list-border-color", "--cui-task-list-border-width", "--cui-task-list-shadow", "--cui-task-list-item-foreground", "--cui-task-list-item-pending-foreground", "--cui-task-list-indicator-foreground", "--cui-task-list-indicator-active-foreground"];
3
3
  export type TaskListKnobStyle = Partial<Record<(typeof taskListKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,6 +1,10 @@
1
1
  //#region src/knob-contracts/task-list-knobs.ts
2
2
  const taskListKnobs = [
3
3
  "--cui-task-list-radius",
4
+ "--cui-task-list-ring-color",
5
+ "--cui-task-list-items-padding",
6
+ "--cui-task-list-item-radius",
7
+ "--cui-task-list-trigger-hover-background",
4
8
  "--cui-task-list-background",
5
9
  "--cui-task-list-foreground",
6
10
  "--cui-task-list-border-color",
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/user-ask-knobs.d.ts
2
- export declare const userAskKnobs: readonly ["--cui-user-ask-radius", "--cui-user-ask-background", "--cui-user-ask-foreground", "--cui-user-ask-border-color", "--cui-user-ask-border-width", "--cui-user-ask-shadow", "--cui-user-ask-option-radius", "--cui-user-ask-option-hover-background", "--cui-user-ask-option-selected-background", "--cui-user-ask-indicator-background", "--cui-user-ask-indicator-foreground", "--cui-user-ask-input-background", "--cui-user-ask-input-foreground"];
2
+ export declare const userAskKnobs: readonly ["--cui-user-ask-radius", "--cui-user-ask-padding", "--cui-user-ask-backdrop-filter", "--cui-user-ask-indicator-radius", "--cui-user-ask-indicator-multiple-radius", "--cui-user-ask-background", "--cui-user-ask-foreground", "--cui-user-ask-border-color", "--cui-user-ask-border-width", "--cui-user-ask-shadow", "--cui-user-ask-option-radius", "--cui-user-ask-option-hover-background", "--cui-user-ask-option-selected-background", "--cui-user-ask-indicator-background", "--cui-user-ask-indicator-foreground", "--cui-user-ask-input-background", "--cui-user-ask-input-foreground"];
3
3
  export type UserAskKnobStyle = Partial<Record<(typeof userAskKnobs)[number], string>>;
4
4
  //#endregion
@@ -1,6 +1,10 @@
1
1
  //#region src/knob-contracts/user-ask-knobs.ts
2
2
  const userAskKnobs = [
3
3
  "--cui-user-ask-radius",
4
+ "--cui-user-ask-padding",
5
+ "--cui-user-ask-backdrop-filter",
6
+ "--cui-user-ask-indicator-radius",
7
+ "--cui-user-ask-indicator-multiple-radius",
4
8
  "--cui-user-ask-background",
5
9
  "--cui-user-ask-foreground",
6
10
  "--cui-user-ask-border-color",
@@ -1,5 +1,5 @@
1
- import { getCountryCallingCode } from "react-phone-number-input/max";
2
1
  import { AsYouType } from "libphonenumber-js/max";
2
+ import { getCountryCallingCode } from "react-phone-number-input/max";
3
3
  //#region src/lib/phone-input-format.ts
4
4
  function normalizePhoneInputText(value, country) {
5
5
  if (!country) return value;
@@ -68,7 +68,7 @@ function MarkdownBlockContent({ children, className, ...props }) {
68
68
  "data-control-ui": "markdown-block",
69
69
  "data-control-family": "markdown-block",
70
70
  "data-slot": "content",
71
- className: cn("max-h-[420px] overflow-auto mask-y-from-[calc(100%_-_var(--scroll-fade-size))]", className),
71
+ className: cn("max-h-[420px] overflow-auto mask-b-from-[calc(100%_-_var(--scroll-fade-size))]", className),
72
72
  ...props,
73
73
  children: children ?? /* @__PURE__ */ jsx(Markdown, { content: code })
74
74
  });
@@ -37,6 +37,7 @@
37
37
  @import "./recipes/color-picker.css";
38
38
  @import "./recipes/color-picker-details.css";
39
39
  @import "./recipes/color-picker-values.css";
40
+ @import "./recipes/empty.css";
40
41
  @import "./recipes/context.css";
41
42
  @import "./recipes/popup-drawer.css";
42
43
  @import "./recipes/dockable-panel.css";
@@ -46,7 +47,6 @@
46
47
  @import "./recipes/dynamic-notification.css";
47
48
  @import "./recipes/dynamic-notification-input.css";
48
49
  @import "./recipes/dynamic-notification-motion.css";
49
- @import "./recipes/empty.css";
50
50
  @import "./recipes/environment-variables.css";
51
51
  @import "./recipes/resizable.css";
52
52
  @import "./recipes/gradient-editor.css";
@@ -59,6 +59,7 @@
59
59
  @import "./recipes/markdown-block.css";
60
60
  @import "./recipes/range.css";
61
61
  @import "./recipes/morphing-panel.css";
62
+ @import "./recipes/page-layout.css";
62
63
  @import "./recipes/pagination.css";
63
64
  @import "./recipes/phone-input.css";
64
65
  @import "./recipes/rich-tooltip.css";
@@ -1,22 +1,54 @@
1
1
  @layer components {
2
2
  :where([data-control-family="action-bar"][data-slot="root"]) {
3
+ --cui-action-bar-hidden-opacity: 0;
4
+ --cui-action-bar-visible-opacity: 1;
3
5
  margin-block-start: calc(var(--spacing) * 1);
4
6
  min-block-size: calc(var(--spacing) * 8);
5
7
  gap: calc(var(--spacing) * 1);
6
- opacity: 1;
8
+ opacity: var(--cui-action-bar-visible-opacity);
9
+ transition-property: opacity;
10
+ transition-duration: var(--duration-fast);
11
+ transition-timing-function: var(--ease-standard);
7
12
  }
8
13
 
9
- @media (hover: hover) {
14
+ @media (hover: hover) and (pointer: fine) {
10
15
  :where([data-control-family="chat-layout"][data-slot="turn"] [data-control-family="action-bar"][data-slot="root"]) {
11
- opacity: 0;
16
+ opacity: var(--cui-action-bar-hidden-opacity);
12
17
  }
13
18
 
14
19
  :where([data-control-family="chat-layout"][data-slot="turn"]:hover [data-control-family="action-bar"][data-slot="root"]) {
15
- opacity: 1;
20
+ opacity: var(--cui-action-bar-visible-opacity);
16
21
  }
17
22
  }
18
23
 
19
24
  :where([data-control-family="chat-layout"][data-slot="turn"]:focus-within [data-control-family="action-bar"][data-slot="root"]) {
20
- opacity: 1;
25
+ opacity: var(--cui-action-bar-visible-opacity);
21
26
  }
27
+
28
+ @media (pointer: coarse) {
29
+ :where([data-control-family="action-bar"][data-slot="root"] [data-control-family="button"]) {
30
+ position: relative;
31
+ }
32
+
33
+ :where([data-control-family="action-bar"][data-slot="root"] [data-control-family="button"])::after {
34
+ content: "";
35
+ position: absolute;
36
+ inset: 50% 50%;
37
+ translate: -50% -50%;
38
+ inline-size: 100%;
39
+ block-size: max(100%, 44px);
40
+ }
41
+ }
42
+ }
43
+
44
+ @property --cui-action-bar-hidden-opacity {
45
+ syntax: "<number>";
46
+ inherits: true;
47
+ initial-value: 0;
48
+ }
49
+
50
+ @property --cui-action-bar-visible-opacity {
51
+ syntax: "<number>";
52
+ inherits: true;
53
+ initial-value: 1;
22
54
  }