@neuronection/assistant-ui 0.21.0 → 0.22.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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/dist/{chunk-XUDCCQRN.js → chunk-4UJKXTWY.js} +63 -24
- package/dist/chunk-4UJKXTWY.js.map +1 -0
- package/dist/chunk-7KD4MG75.js +83 -0
- package/dist/chunk-7KD4MG75.js.map +1 -0
- package/dist/{chunk-RBEPQY2A.js → chunk-BHHDCY2B.js} +3 -3
- package/dist/{chunk-RBEPQY2A.js.map → chunk-BHHDCY2B.js.map} +1 -1
- package/dist/{chunk-VULOVVKF.js → chunk-Q5THPPNL.js} +3 -3
- package/dist/{chunk-VULOVVKF.js.map → chunk-Q5THPPNL.js.map} +1 -1
- package/dist/{chunk-SVQK7TXU.js → chunk-S4WHBQJ2.js} +3 -3
- package/dist/{chunk-SVQK7TXU.js.map → chunk-S4WHBQJ2.js.map} +1 -1
- package/dist/{chunk-AATZUVW4.js → chunk-WDLUZS2G.js} +25 -4
- package/dist/chunk-WDLUZS2G.js.map +1 -0
- package/dist/combobox.d.ts +8 -0
- package/dist/combobox.js +1 -1
- package/dist/index.js +6 -6
- package/dist/model-picker.js +1 -1
- package/dist/model-registry.js +1 -1
- package/dist/rich-text-editor.d.ts +10 -3
- package/dist/rich-text-editor.js +1 -1
- package/dist/settings-shell.d.ts +2 -0
- package/dist/settings-shell.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/task-assignment-picker.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AATZUVW4.js.map +0 -1
- package/dist/chunk-UJVNCZ5Z.js +0 -75
- package/dist/chunk-UJVNCZ5Z.js.map +0 -1
- package/dist/chunk-XUDCCQRN.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @neuronection/assistant-ui
|
|
2
2
|
|
|
3
|
+
## 0.22.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`7537028`](https://github.com/neuronection/assistant-ui/commit/75370281e944b43b295ff6a315ff4fb7112d471f) Thanks [@constLiakos](https://github.com/constLiakos)! - Combobox and ComboboxMulti gain `allowCreate` (+ optional `createLabel`):
|
|
8
|
+
when the search term matches no option, an `Add "term"` row is offered
|
|
9
|
+
(keyboard included) and picking it reports the raw trimmed term — for
|
|
10
|
+
free-text entry into taxonomy-backed pickers.
|
|
11
|
+
|
|
12
|
+
- [`2b7e756`](https://github.com/neuronection/assistant-ui/commit/2b7e7566529af6e43528b63908ab590c04085864) Thanks [@constLiakos](https://github.com/constLiakos)! - RichTextEditor becomes hostable by full apps: `extensions` is now a **full
|
|
13
|
+
override** of the built-in `[StarterKit, Markdown]` set (apps declare their
|
|
14
|
+
complete extension set), and three composition props land — `contentClassName`
|
|
15
|
+
(merged onto the editable region), `onReady` (editor instance on create,
|
|
16
|
+
`null` on destroy — the app handle for commands and event wiring), and
|
|
17
|
+
`headingLevels` (one toggle per level; `labels.heading` is now
|
|
18
|
+
`(level) => string`, default `Heading ${level}`). History buttons now reflect
|
|
19
|
+
undo/redo availability and disable while there is nothing to undo/redo.
|
|
20
|
+
|
|
3
21
|
## 0.21.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -76,7 +76,7 @@ Visual reference: [gallery](https://neuronection.github.io/assistant-ui/).
|
|
|
76
76
|
| [`tooltip`](./docs/components/tooltip.md) | `Tooltip` + parts, `InfoTooltip` | [stories](https://neuronection.github.io/assistant-ui/?story=overlay--tooltips) |
|
|
77
77
|
| [`wizard`](./docs/components/wizard.md) | `Wizard` (steps config + `renderStep`, per-step validation gates, modal/drawer variants), `Stepper` (dots/labels) | [stories](https://neuronection.github.io/assistant-ui/?story=wizard--modal-wizard) |
|
|
78
78
|
| [`input`](./docs/components/input.md) / [`textarea`](./docs/components/textarea.md) / [`search-input`](./docs/components/search-input.md) / [`expandable-search`](./docs/components/expandable-search.md) | `Input` (label/hint/error wiring) · `Textarea` · `SearchInput` · `ExpandableSearch` | [stories](https://neuronection.github.io/assistant-ui/?story=misc--inputs) |
|
|
79
|
-
| [`rich-text-editor`](./docs/components/rich-text-editor.md) | `RichTextEditor` — controlled tiptap markdown editor: configurable toolbar groups + `toolbarExtra` slot, label/icon props, caret-preserving external sync | [stories](https://neuronection.github.io/assistant-ui/?story=rich-text-editor--default) |
|
|
79
|
+
| [`rich-text-editor`](./docs/components/rich-text-editor.md) | `RichTextEditor` — controlled tiptap markdown editor: full-override `extensions`, configurable toolbar groups + per-level headings + `toolbarExtra` slot, `onReady`/`contentClassName` composition props, label/icon props, caret-preserving external sync | [stories](https://neuronection.github.io/assistant-ui/?story=rich-text-editor--default) |
|
|
80
80
|
| [`dictation`](./docs/components/dictation.md) / [`ai-text-transform`](./docs/components/ai-text-transform.md) | `useDictation` + `DictationButton`/`DictationStrip` (transport-injected STT) · `useAiTextTransform` (streaming transform state machine) | [stories](https://neuronection.github.io/assistant-ui/?story=dictation--dictation) |
|
|
81
81
|
| [`text-diff-view`](./docs/components/text-diff-view.md) | `TextDiffView` — side-by-side diff with word-level highlights, line numbers, change navigation, folds, virtualization (+ exported `computeLineDiff`/`wordSegments`) | [stories](https://neuronection.github.io/assistant-ui/?story=text-diff-view--default) |
|
|
82
82
|
| [`chip-input`](./docs/components/chip-input.md) / [`chip-list`](./docs/components/chip-list.md) | `ChipInput` (Enter/comma commit, paste-splits, Backspace-removes) · `ChipList` (variant pills, clickable, removable) | [stories](https://neuronection.github.io/assistant-ui/?story=phase2--chip-editing) |
|
|
@@ -13,13 +13,15 @@ var DEFAULT_TOOLBAR = [
|
|
|
13
13
|
"list",
|
|
14
14
|
"quote"
|
|
15
15
|
];
|
|
16
|
+
var DEFAULT_HEADING_LEVELS = [2];
|
|
17
|
+
var DEFAULT_EXTENSIONS = [StarterKit, Markdown];
|
|
16
18
|
var DEFAULT_LABELS = {
|
|
17
19
|
toolbar: "Formatting",
|
|
18
20
|
bold: "Bold",
|
|
19
21
|
italic: "Italic",
|
|
20
22
|
strike: "Strikethrough",
|
|
21
23
|
code: "Code",
|
|
22
|
-
heading:
|
|
24
|
+
heading: (level) => `Heading ${level}`,
|
|
23
25
|
bulletList: "Bulleted list",
|
|
24
26
|
orderedList: "Numbered list",
|
|
25
27
|
blockquote: "Quote",
|
|
@@ -60,6 +62,9 @@ var RichTextEditor = React.forwardRef(
|
|
|
60
62
|
toolbar = DEFAULT_TOOLBAR,
|
|
61
63
|
toolbarExtra,
|
|
62
64
|
extensions,
|
|
65
|
+
contentClassName,
|
|
66
|
+
onReady,
|
|
67
|
+
headingLevels,
|
|
63
68
|
parseMarkdown,
|
|
64
69
|
serializeMarkdown,
|
|
65
70
|
labels,
|
|
@@ -68,9 +73,16 @@ var RichTextEditor = React.forwardRef(
|
|
|
68
73
|
}, ref) {
|
|
69
74
|
const mergedLabels = { ...DEFAULT_LABELS, ...labels };
|
|
70
75
|
const mergedIcons = { ...DEFAULT_ICONS, ...icons };
|
|
76
|
+
const resolvedExtensions = React.useMemo(
|
|
77
|
+
() => extensions ?? DEFAULT_EXTENSIONS,
|
|
78
|
+
[extensions]
|
|
79
|
+
);
|
|
80
|
+
const levels = headingLevels ?? DEFAULT_HEADING_LEVELS;
|
|
71
81
|
const lastEmittedRef = React.useRef(value);
|
|
72
82
|
const onValueChangeRef = React.useRef(onValueChange);
|
|
73
83
|
onValueChangeRef.current = onValueChange;
|
|
84
|
+
const onReadyRef = React.useRef(onReady);
|
|
85
|
+
onReadyRef.current = onReady;
|
|
74
86
|
const hooksRef = React.useRef({ parseMarkdown, serializeMarkdown });
|
|
75
87
|
hooksRef.current = { parseMarkdown, serializeMarkdown };
|
|
76
88
|
const [, bump] = React.useReducer((count) => count + 1, 0);
|
|
@@ -84,17 +96,17 @@ var RichTextEditor = React.forwardRef(
|
|
|
84
96
|
);
|
|
85
97
|
const editor = useEditor(
|
|
86
98
|
{
|
|
87
|
-
extensions:
|
|
88
|
-
() => [StarterKit, Markdown, ...extensions ?? []],
|
|
89
|
-
[extensions]
|
|
90
|
-
),
|
|
99
|
+
extensions: resolvedExtensions,
|
|
91
100
|
content: toDocument(value),
|
|
92
101
|
editable: !disabled,
|
|
93
102
|
immediatelyRender: false,
|
|
94
103
|
editorProps: {
|
|
95
104
|
attributes: {
|
|
96
105
|
"aria-label": ariaLabel,
|
|
97
|
-
class:
|
|
106
|
+
class: cn(
|
|
107
|
+
"as-rich-text-editor__content min-h-24 w-full bg-transparent px-3 py-2 text-sm text-[var(--as-fg)] outline-none",
|
|
108
|
+
contentClassName
|
|
109
|
+
)
|
|
98
110
|
}
|
|
99
111
|
},
|
|
100
112
|
onUpdate: ({ editor: current }) => {
|
|
@@ -105,6 +117,15 @@ var RichTextEditor = React.forwardRef(
|
|
|
105
117
|
}
|
|
106
118
|
);
|
|
107
119
|
const isMounted = editor !== null;
|
|
120
|
+
React.useEffect(() => {
|
|
121
|
+
if (editor === null) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
onReadyRef.current?.(editor);
|
|
125
|
+
return () => {
|
|
126
|
+
onReadyRef.current?.(null);
|
|
127
|
+
};
|
|
128
|
+
}, [editor]);
|
|
108
129
|
React.useEffect(() => {
|
|
109
130
|
if (!isMounted || editor === null) {
|
|
110
131
|
return;
|
|
@@ -139,26 +160,47 @@ var RichTextEditor = React.forwardRef(
|
|
|
139
160
|
lastEmittedRef.current = value;
|
|
140
161
|
}, [editor, value, toApp, toDocument]);
|
|
141
162
|
const groups = toolbar === false ? [] : toolbar ?? DEFAULT_TOOLBAR;
|
|
142
|
-
const
|
|
163
|
+
const buttonClass = (active) => cn(
|
|
164
|
+
"rounded p-1.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50",
|
|
165
|
+
active && "bg-[var(--as-surface-active)] text-[var(--as-fg)]"
|
|
166
|
+
);
|
|
167
|
+
const renderButton = (key, group, onClick, active, buttonDisabled = disabled) => {
|
|
143
168
|
const Icon = mergedIcons[key];
|
|
169
|
+
const label = mergedLabels[key];
|
|
144
170
|
return /* @__PURE__ */ jsx(
|
|
145
171
|
"button",
|
|
146
172
|
{
|
|
147
173
|
type: "button",
|
|
148
|
-
"aria-label":
|
|
174
|
+
"aria-label": label,
|
|
149
175
|
"aria-pressed": active,
|
|
150
|
-
title:
|
|
151
|
-
disabled,
|
|
152
|
-
className:
|
|
153
|
-
"rounded p-1.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50",
|
|
154
|
-
active && "bg-[var(--as-surface-active)] text-[var(--as-fg)]"
|
|
155
|
-
),
|
|
176
|
+
title: label,
|
|
177
|
+
disabled: buttonDisabled,
|
|
178
|
+
className: buttonClass(active),
|
|
156
179
|
onClick,
|
|
157
180
|
children: /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": true })
|
|
158
181
|
},
|
|
159
182
|
`${group}-${key}`
|
|
160
183
|
);
|
|
161
184
|
};
|
|
185
|
+
const historyDisabled = (can) => disabled || editor === null || editor.can()[can]() !== true;
|
|
186
|
+
const renderHeadingButton = (level) => {
|
|
187
|
+
const Icon = mergedIcons.heading;
|
|
188
|
+
const label = mergedLabels.heading(level);
|
|
189
|
+
return /* @__PURE__ */ jsx(
|
|
190
|
+
"button",
|
|
191
|
+
{
|
|
192
|
+
type: "button",
|
|
193
|
+
"aria-label": label,
|
|
194
|
+
"aria-pressed": editor?.isActive("heading", { level }) === true,
|
|
195
|
+
title: label,
|
|
196
|
+
disabled,
|
|
197
|
+
className: buttonClass(editor?.isActive("heading", { level }) === true),
|
|
198
|
+
onClick: () => editor?.chain().focus().toggleHeading({ level }).run(),
|
|
199
|
+
children: /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": true })
|
|
200
|
+
},
|
|
201
|
+
`heading-${level}`
|
|
202
|
+
);
|
|
203
|
+
};
|
|
162
204
|
return /* @__PURE__ */ jsxs(
|
|
163
205
|
"div",
|
|
164
206
|
{
|
|
@@ -181,20 +223,17 @@ var RichTextEditor = React.forwardRef(
|
|
|
181
223
|
"undo",
|
|
182
224
|
"history",
|
|
183
225
|
() => editor?.chain().focus().undo().run(),
|
|
184
|
-
false
|
|
226
|
+
false,
|
|
227
|
+
historyDisabled("undo")
|
|
185
228
|
) : null,
|
|
186
229
|
groups.includes("history") ? renderButton(
|
|
187
230
|
"redo",
|
|
188
231
|
"history",
|
|
189
232
|
() => editor?.chain().focus().redo().run(),
|
|
190
|
-
false
|
|
191
|
-
|
|
192
|
-
groups.includes("heading") ? renderButton(
|
|
193
|
-
"heading",
|
|
194
|
-
"heading",
|
|
195
|
-
() => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
|
|
196
|
-
editor?.isActive("heading", { level: 2 }) === true
|
|
233
|
+
false,
|
|
234
|
+
historyDisabled("redo")
|
|
197
235
|
) : null,
|
|
236
|
+
groups.includes("heading") ? levels.map((level) => renderHeadingButton(level)) : null,
|
|
198
237
|
groups.includes("format") ? renderButton(
|
|
199
238
|
"bold",
|
|
200
239
|
"format",
|
|
@@ -249,5 +288,5 @@ var RichTextEditor = React.forwardRef(
|
|
|
249
288
|
);
|
|
250
289
|
|
|
251
290
|
export { RichTextEditor };
|
|
252
|
-
//# sourceMappingURL=chunk-
|
|
253
|
-
//# sourceMappingURL=chunk-
|
|
291
|
+
//# sourceMappingURL=chunk-4UJKXTWY.js.map
|
|
292
|
+
//# sourceMappingURL=chunk-4UJKXTWY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/rich-text-editor/RichTextEditor.tsx"],"names":["RichTextEditor"],"mappings":"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","file":"chunk-4UJKXTWY.js","sourcesContent":["import * as React from 'react'\nimport { Editor, EditorContent, useEditor, type Extensions } from '@tiptap/react'\nimport StarterKit from '@tiptap/starter-kit'\nimport {\n Bold,\n Code,\n Heading2,\n Italic,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Strikethrough,\n Undo2,\n type LucideIcon,\n} from 'lucide-react'\nimport { Markdown } from 'tiptap-markdown'\n\nimport { cn } from '../../lib/utils'\n\nexport type RichTextToolbarGroup = 'history' | 'heading' | 'format' | 'list' | 'quote'\n\nexport type RichTextHeadingLevel = 1 | 2 | 3 | 4\n\nconst DEFAULT_TOOLBAR: RichTextToolbarGroup[] = [\n 'history',\n 'heading',\n 'format',\n 'list',\n 'quote',\n]\n\nconst DEFAULT_HEADING_LEVELS: RichTextHeadingLevel[] = [2]\n\nconst DEFAULT_EXTENSIONS: Extensions = [StarterKit, Markdown]\n\nexport interface RichTextEditorLabels {\n toolbar?: string\n bold?: string\n italic?: string\n strike?: string\n code?: string\n heading?: (level: number) => string\n bulletList?: string\n orderedList?: string\n blockquote?: string\n undo?: string\n redo?: string\n}\n\nexport interface RichTextEditorIcons {\n bold?: LucideIcon\n italic?: LucideIcon\n strike?: LucideIcon\n code?: LucideIcon\n heading?: LucideIcon\n bulletList?: LucideIcon\n orderedList?: LucideIcon\n blockquote?: LucideIcon\n undo?: LucideIcon\n redo?: LucideIcon\n}\n\nconst DEFAULT_LABELS: Required<RichTextEditorLabels> = {\n toolbar: 'Formatting',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n code: 'Code',\n heading: (level) => `Heading ${level}`,\n bulletList: 'Bulleted list',\n orderedList: 'Numbered list',\n blockquote: 'Quote',\n undo: 'Undo',\n redo: 'Redo',\n}\n\nconst DEFAULT_ICONS: Required<RichTextEditorIcons> = {\n bold: Bold,\n italic: Italic,\n strike: Strikethrough,\n code: Code,\n heading: Heading2,\n bulletList: List,\n orderedList: ListOrdered,\n blockquote: Quote,\n undo: Undo2,\n redo: Redo2,\n}\n\ntype FormatKey =\n | 'bold'\n | 'italic'\n | 'strike'\n | 'code'\n | 'bulletList'\n | 'orderedList'\n | 'blockquote'\n | 'undo'\n | 'redo'\n\nexport interface RichTextEditorProps {\n value: string\n onValueChange: (markdown: string) => void\n ariaLabel: string\n disabled?: boolean\n toolbar?: RichTextToolbarGroup[] | false\n /** App-owned controls at the end of the toolbar; render-prop form receives the editor. */\n toolbarExtra?: React.ReactNode | ((editor: Editor | null) => React.ReactNode)\n /** Full override of the document extension set; default is `[StarterKit, Markdown]`. Apps declare their complete set. */\n extensions?: Extensions\n /** Extra classes for the editable region (merged after the built-ins via tailwind-merge). */\n contentClassName?: string\n /** Called once when the editor instance is created and again with `null` on destroy/unmount. */\n onReady?: (editor: Editor | null) => void\n /** Heading toggles rendered for the `heading` toolbar group, one button per level. */\n headingLevels?: RichTextHeadingLevel[]\n /** Map incoming app-domain markdown before it reaches the document. */\n parseMarkdown?: (markdown: string) => string\n /** Map the serialized document before it is emitted / echo-compared. */\n serializeMarkdown?: (markdown: string) => string\n labels?: Partial<RichTextEditorLabels>\n icons?: Partial<RichTextEditorIcons>\n className?: string\n}\n\nfunction getMarkdown(editor: Editor): string {\n const storage = editor.storage as { markdown?: { getMarkdown?: () => string } }\n return storage.markdown?.getMarkdown?.() ?? ''\n}\n\nfunction applyExternalValue(editor: Editor, markdown: string): void {\n const hadFocus = editor.isFocused\n const caret = editor.state.selection.head\n editor.commands.setContent(markdown, { emitUpdate: false })\n if (hadFocus) {\n editor.commands.setTextSelection(Math.min(caret, editor.state.doc.content.size))\n editor.commands.focus()\n }\n}\n\nexport const RichTextEditor = React.forwardRef<HTMLDivElement, RichTextEditorProps>(\n function RichTextEditor(\n {\n value,\n onValueChange,\n ariaLabel,\n disabled = false,\n toolbar = DEFAULT_TOOLBAR,\n toolbarExtra,\n extensions,\n contentClassName,\n onReady,\n headingLevels,\n parseMarkdown,\n serializeMarkdown,\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const mergedLabels = { ...DEFAULT_LABELS, ...labels }\n const mergedIcons = { ...DEFAULT_ICONS, ...icons }\n const resolvedExtensions = React.useMemo(\n () => extensions ?? DEFAULT_EXTENSIONS,\n [extensions],\n )\n const levels = headingLevels ?? DEFAULT_HEADING_LEVELS\n const lastEmittedRef = React.useRef<string>(value)\n const onValueChangeRef = React.useRef(onValueChange)\n onValueChangeRef.current = onValueChange\n const onReadyRef = React.useRef(onReady)\n onReadyRef.current = onReady\n const hooksRef = React.useRef({ parseMarkdown, serializeMarkdown })\n hooksRef.current = { parseMarkdown, serializeMarkdown }\n const [, bump] = React.useReducer((count: number) => count + 1, 0)\n\n const toDocument = React.useCallback(\n (markdown: string) => (parseMarkdown ? parseMarkdown(markdown) : markdown),\n [parseMarkdown],\n )\n const toApp = React.useCallback(\n (markdown: string) => (serializeMarkdown ? serializeMarkdown(markdown) : markdown),\n [serializeMarkdown],\n )\n\n const editor = useEditor(\n {\n extensions: resolvedExtensions,\n content: toDocument(value),\n editable: !disabled,\n immediatelyRender: false,\n editorProps: {\n attributes: {\n 'aria-label': ariaLabel,\n class: cn(\n 'as-rich-text-editor__content min-h-24 w-full bg-transparent px-3 py-2 text-sm text-[var(--as-fg)] outline-none',\n contentClassName,\n ),\n },\n },\n onUpdate: ({ editor: current }) => {\n const markdown = toApp(getMarkdown(current))\n lastEmittedRef.current = markdown\n onValueChangeRef.current(markdown)\n },\n },\n )\n\n const isMounted = editor !== null\n\n React.useEffect(() => {\n if (editor === null) {\n return\n }\n onReadyRef.current?.(editor)\n return () => {\n onReadyRef.current?.(null)\n }\n }, [editor])\n\n React.useEffect(() => {\n if (!isMounted || editor === null) {\n return\n }\n const handler = () => bump()\n editor.on('transaction', handler)\n editor.on('update', handler)\n return () => {\n editor.off('transaction', handler)\n editor.off('update', handler)\n }\n }, [editor, isMounted])\n\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n editor.setEditable(!disabled)\n }, [editor, disabled])\n\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n if (value === lastEmittedRef.current) {\n return\n }\n const current = toApp(getMarkdown(editor))\n if (value === current) {\n lastEmittedRef.current = value\n return\n }\n applyExternalValue(editor, toDocument(value))\n lastEmittedRef.current = value\n }, [editor, value, toApp, toDocument])\n\n const groups = toolbar === false ? [] : (toolbar ?? DEFAULT_TOOLBAR)\n\n const buttonClass = (active: boolean) =>\n cn(\n 'rounded p-1.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n active && 'bg-[var(--as-surface-active)] text-[var(--as-fg)]',\n )\n\n const renderButton = (\n key: FormatKey,\n group: RichTextToolbarGroup,\n onClick: () => void,\n active: boolean,\n buttonDisabled = disabled,\n ) => {\n const Icon = mergedIcons[key]\n const label = mergedLabels[key]\n return (\n <button\n key={`${group}-${key}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n title={label}\n disabled={buttonDisabled}\n className={buttonClass(active)}\n onClick={onClick}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n const historyDisabled = (can: 'undo' | 'redo') =>\n disabled || editor === null || editor.can()[can]() !== true\n\n const renderHeadingButton = (level: RichTextHeadingLevel) => {\n const Icon = mergedIcons.heading\n const label = mergedLabels.heading(level)\n return (\n <button\n key={`heading-${level}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={editor?.isActive('heading', { level }) === true}\n title={label}\n disabled={disabled}\n className={buttonClass(editor?.isActive('heading', { level }) === true)}\n onClick={() => editor?.chain().focus().toggleHeading({ level }).run()}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n return (\n <div\n ref={ref}\n data-as=\"rich-text-editor\"\n className={cn(\n 'w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] focus-within:border-[var(--as-focus-ring)]',\n disabled && 'opacity-50',\n className,\n )}\n >\n {groups.length > 0 || toolbarExtra ? (\n <div\n role=\"toolbar\"\n aria-label={mergedLabels.toolbar}\n className=\"flex flex-wrap items-center gap-0.5 border-b border-[var(--as-border)] p-1\"\n >\n {groups.includes('history')\n ? renderButton(\n 'undo',\n 'history',\n () => editor?.chain().focus().undo().run(),\n false,\n historyDisabled('undo'),\n )\n : null}\n {groups.includes('history')\n ? renderButton(\n 'redo',\n 'history',\n () => editor?.chain().focus().redo().run(),\n false,\n historyDisabled('redo'),\n )\n : null}\n {groups.includes('heading') ? levels.map((level) => renderHeadingButton(level)) : null}\n {groups.includes('format')\n ? renderButton(\n 'bold',\n 'format',\n () => editor?.chain().focus().toggleBold().run(),\n editor?.isActive('bold') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'italic',\n 'format',\n () => editor?.chain().focus().toggleItalic().run(),\n editor?.isActive('italic') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'strike',\n 'format',\n () => editor?.chain().focus().toggleStrike().run(),\n editor?.isActive('strike') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'code',\n 'format',\n () => editor?.chain().focus().toggleCode().run(),\n editor?.isActive('code') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'bulletList',\n 'list',\n () => editor?.chain().focus().toggleBulletList().run(),\n editor?.isActive('bulletList') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'orderedList',\n 'list',\n () => editor?.chain().focus().toggleOrderedList().run(),\n editor?.isActive('orderedList') === true,\n )\n : null}\n {groups.includes('quote')\n ? renderButton(\n 'blockquote',\n 'quote',\n () => editor?.chain().focus().toggleBlockquote().run(),\n editor?.isActive('blockquote') === true,\n )\n : null}\n {typeof toolbarExtra === 'function' ? toolbarExtra(editor) : toolbarExtra}\n </div>\n ) : null}\n <EditorContent editor={editor} />\n </div>\n )\n },\n)\n"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var SettingsShell = React.forwardRef(
|
|
6
|
+
function SettingsShell2({ nav, active, onNavigate, header, children, className, navClassName, navTestId }, ref) {
|
|
7
|
+
const HeaderIcon = header?.icon;
|
|
8
|
+
return /* @__PURE__ */ jsxs(
|
|
9
|
+
"div",
|
|
10
|
+
{
|
|
11
|
+
ref,
|
|
12
|
+
"data-as": "settings-shell",
|
|
13
|
+
className: cn("grid grid-cols-1 gap-8 lg:grid-cols-4", className),
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ jsx(
|
|
16
|
+
"nav",
|
|
17
|
+
{
|
|
18
|
+
className: "lg:col-span-1",
|
|
19
|
+
"aria-label": "Settings sections",
|
|
20
|
+
"data-testid": navTestId,
|
|
21
|
+
children: /* @__PURE__ */ jsxs(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: cn(
|
|
25
|
+
"space-y-1 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-3 lg:sticky lg:top-24",
|
|
26
|
+
navClassName
|
|
27
|
+
),
|
|
28
|
+
children: [
|
|
29
|
+
header ? /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2.5 border-b border-[var(--as-border)] px-3 py-2", children: [
|
|
30
|
+
HeaderIcon ? /* @__PURE__ */ jsx(
|
|
31
|
+
HeaderIcon,
|
|
32
|
+
{
|
|
33
|
+
className: "size-5 shrink-0 text-[var(--as-primary)]",
|
|
34
|
+
"aria-hidden": true
|
|
35
|
+
}
|
|
36
|
+
) : null,
|
|
37
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-bold text-[var(--as-fg)]", children: header.title })
|
|
38
|
+
] }) : null,
|
|
39
|
+
nav.map(({ id, label, description, icon: Icon, trailing }) => {
|
|
40
|
+
const isActive = id === active;
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"button",
|
|
43
|
+
{
|
|
44
|
+
type: "button",
|
|
45
|
+
"aria-current": isActive ? "page" : void 0,
|
|
46
|
+
onClick: () => onNavigate(id),
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex w-full cursor-pointer items-start rounded-[var(--as-radius)] px-3 py-2.5 text-left text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
49
|
+
isActive ? "bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]" : "font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
|
|
50
|
+
),
|
|
51
|
+
children: [
|
|
52
|
+
Icon ? /* @__PURE__ */ jsx(
|
|
53
|
+
Icon,
|
|
54
|
+
{
|
|
55
|
+
className: "mr-3 mt-0.5 size-4 shrink-0",
|
|
56
|
+
"aria-hidden": true
|
|
57
|
+
}
|
|
58
|
+
) : null,
|
|
59
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label }),
|
|
61
|
+
description ? /* @__PURE__ */ jsx("span", { className: "text-[11px] font-normal text-[var(--as-muted-fg)]", children: description }) : null
|
|
62
|
+
] }),
|
|
63
|
+
trailing ? /* @__PURE__ */ jsx("span", { className: "ml-auto flex items-center self-center pl-2", children: trailing }) : null
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
id
|
|
67
|
+
);
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 lg:col-span-3", children })
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
export { SettingsShell };
|
|
82
|
+
//# sourceMappingURL=chunk-7KD4MG75.js.map
|
|
83
|
+
//# sourceMappingURL=chunk-7KD4MG75.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/settings-shell/SettingsShell.tsx"],"names":["SettingsShell"],"mappings":";;;;AAyBO,IAAM,aAAA,GAAsB,KAAA,CAAA,UAAA;AAAA,EACjC,SAASA,cAAAA,CACP,EAAE,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,SAAA,EAAW,YAAA,EAAc,SAAA,EAAU,EAChF,GAAA,EACA;AACA,IAAA,MAAM,aAAa,MAAA,EAAQ,IAAA;AAC3B,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAQ,gBAAA;AAAA,QACR,SAAA,EAAW,EAAA,CAAG,uCAAA,EAAyC,SAAS,CAAA;AAAA,QAEhE,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,eAAA;AAAA,cACV,YAAA,EAAW,mBAAA;AAAA,cACX,aAAA,EAAa,SAAA;AAAA,cAEb,QAAA,kBAAA,IAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAW,EAAA;AAAA,oBACT,gIAAA;AAAA,oBACA;AAAA,mBACF;AAAA,kBAEC,QAAA,EAAA;AAAA,oBAAA,MAAA,mBACC,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6EAAA,EACZ,QAAA,EAAA;AAAA,sBAAA,UAAA,mBACC,GAAA;AAAA,wBAAC,UAAA;AAAA,wBAAA;AAAA,0BACC,SAAA,EAAU,0CAAA;AAAA,0BACV,aAAA,EAAW;AAAA;AAAA,uBACb,GACE,IAAA;AAAA,sCACJ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gDAAA,EACb,iBAAO,KAAA,EACV;AAAA,qBAAA,EACF,CAAA,GACE,IAAA;AAAA,oBACH,GAAA,CAAI,GAAA,CAAI,CAAC,EAAE,EAAA,EAAI,OAAO,WAAA,EAAa,IAAA,EAAM,IAAA,EAAM,QAAA,EAAS,KAAM;AAC7D,sBAAA,MAAM,WAAW,EAAA,KAAO,MAAA;AACxB,sBAAA,uBACE,IAAA;AAAA,wBAAC,QAAA;AAAA,wBAAA;AAAA,0BAEC,IAAA,EAAK,QAAA;AAAA,0BACL,cAAA,EAAc,WAAW,MAAA,GAAS,MAAA;AAAA,0BAClC,OAAA,EAAS,MAAM,UAAA,CAAW,EAAE,CAAA;AAAA,0BAC5B,SAAA,EAAW,EAAA;AAAA,4BACT,uNAAA;AAAA,4BACA,WACI,8FAAA,GACA;AAAA,2BACN;AAAA,0BAEC,QAAA,EAAA;AAAA,4BAAA,IAAA,mBACC,GAAA;AAAA,8BAAC,IAAA;AAAA,8BAAA;AAAA,gCACC,SAAA,EAAU,6BAAA;AAAA,gCACV,aAAA,EAAW;AAAA;AAAA,6BACb,GACE,IAAA;AAAA,4CACJ,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EACd,QAAA,EAAA;AAAA,8CAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,8BACjC,8BACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mDAAA,EACb,uBACH,CAAA,GACE;AAAA,6BAAA,EACN,CAAA;AAAA,4BACC,2BACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4CAAA,EACb,oBACH,CAAA,GACE;AAAA;AAAA,yBAAA;AAAA,wBA7BC;AAAA,uBA8BP;AAAA,oBAEJ,CAAC;AAAA;AAAA;AAAA;AACH;AAAA,WACF;AAAA,0BACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAS;AAAA;AAAA;AAAA,KACnD;AAAA,EAEJ;AACF","file":"chunk-7KD4MG75.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\n\nexport interface SettingsNavItem {\n id: string\n label: string\n description?: string\n icon?: LucideIcon\n /** Optional trailing node (status dot, count, badge) at the row edge. */\n trailing?: React.ReactNode\n}\n\nexport interface SettingsShellProps {\n nav: SettingsNavItem[]\n active: string\n onNavigate: (id: string) => void\n header?: { icon?: LucideIcon; title: string }\n children: React.ReactNode\n className?: string\n navClassName?: string\n /** Test hook: data-testid for the `<nav>` element. */\n navTestId?: string\n}\n\nexport const SettingsShell = React.forwardRef<HTMLDivElement, SettingsShellProps>(\n function SettingsShell(\n { nav, active, onNavigate, header, children, className, navClassName, navTestId },\n ref,\n ) {\n const HeaderIcon = header?.icon\n return (\n <div\n ref={ref}\n data-as=\"settings-shell\"\n className={cn('grid grid-cols-1 gap-8 lg:grid-cols-4', className)}\n >\n <nav\n className=\"lg:col-span-1\"\n aria-label=\"Settings sections\"\n data-testid={navTestId}\n >\n <div\n className={cn(\n 'space-y-1 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-3 lg:sticky lg:top-24',\n navClassName,\n )}\n >\n {header ? (\n <div className=\"mb-2 flex items-center gap-2.5 border-b border-[var(--as-border)] px-3 py-2\">\n {HeaderIcon ? (\n <HeaderIcon\n className=\"size-5 shrink-0 text-[var(--as-primary)]\"\n aria-hidden\n />\n ) : null}\n <span className=\"truncate text-sm font-bold text-[var(--as-fg)]\">\n {header.title}\n </span>\n </div>\n ) : null}\n {nav.map(({ id, label, description, icon: Icon, trailing }) => {\n const isActive = id === active\n return (\n <button\n key={id}\n type=\"button\"\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onNavigate(id)}\n className={cn(\n 'flex w-full cursor-pointer items-start rounded-[var(--as-radius)] px-3 py-2.5 text-left text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n isActive\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]'\n : 'font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {Icon ? (\n <Icon\n className=\"mr-3 mt-0.5 size-4 shrink-0\"\n aria-hidden\n />\n ) : null}\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"truncate\">{label}</span>\n {description ? (\n <span className=\"text-[11px] font-normal text-[var(--as-muted-fg)]\">\n {description}\n </span>\n ) : null}\n </span>\n {trailing ? (\n <span className=\"ml-auto flex items-center self-center pl-2\">\n {trailing}\n </span>\n ) : null}\n </button>\n )\n })}\n </div>\n </nav>\n <div className=\"min-w-0 lg:col-span-3\">{children}</div>\n </div>\n )\n },\n)\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CapabilityChips } from './chunk-G3DWN2DJ.js';
|
|
2
|
-
import { ModelPicker } from './chunk-
|
|
2
|
+
import { ModelPicker } from './chunk-S4WHBQJ2.js';
|
|
3
3
|
import { beautifyId } from './chunk-B2G66OSQ.js';
|
|
4
4
|
import { Modal, ModalContent, ModalHeader, ModalTitle, ModalFooter } from './chunk-Y7BKBG57.js';
|
|
5
5
|
import { Button } from './chunk-GTXGTQ6F.js';
|
|
@@ -616,5 +616,5 @@ var ModelRegistry = React.forwardRef(
|
|
|
616
616
|
);
|
|
617
617
|
|
|
618
618
|
export { ModelRegistry };
|
|
619
|
-
//# sourceMappingURL=chunk-
|
|
620
|
-
//# sourceMappingURL=chunk-
|
|
619
|
+
//# sourceMappingURL=chunk-BHHDCY2B.js.map
|
|
620
|
+
//# sourceMappingURL=chunk-BHHDCY2B.js.map
|