@neuronection/assistant-ui 0.21.0 → 0.23.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 +35 -0
- package/README.md +1 -1
- package/dist/chunk-7KD4MG75.js +83 -0
- package/dist/chunk-7KD4MG75.js.map +1 -0
- package/dist/{chunk-XUDCCQRN.js → chunk-AY77TWLT.js} +69 -25
- package/dist/chunk-AY77TWLT.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,40 @@
|
|
|
1
1
|
# @neuronection/assistant-ui
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`9be7c37`](https://github.com/neuronection/assistant-ui/commit/9be7c37787b25b658ff01573d13b9c540a9e6c67) Thanks [@constLiakos](https://github.com/constLiakos)! - RichTextEditor becomes hostable by full apps: `extensions` is now a **full
|
|
8
|
+
override** of the built-in `[StarterKit, Markdown]` set (apps declare their
|
|
9
|
+
complete extension set), and three composition props land — `contentClassName`
|
|
10
|
+
(merged onto the editable region), `onReady` (editor instance on create,
|
|
11
|
+
`null` on destroy — the app handle for commands and event wiring), and
|
|
12
|
+
`headingLevels` (one toggle per level; `labels.heading` is now
|
|
13
|
+
`(level) => string`, default `Heading ${level}`). History buttons now reflect
|
|
14
|
+
undo/redo availability and disable while there is nothing to undo/redo. Also
|
|
15
|
+
fixes a spurious mount-time `onValueChange`: the editable-state effect no
|
|
16
|
+
longer calls `setEditable` when it is already correct (tiptap v3 emits an
|
|
17
|
+
update event from `setEditable`, which surfaced the parsed value back to the
|
|
18
|
+
app on mount).
|
|
19
|
+
|
|
20
|
+
## 0.22.0
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- [`7537028`](https://github.com/neuronection/assistant-ui/commit/75370281e944b43b295ff6a315ff4fb7112d471f) Thanks [@constLiakos](https://github.com/constLiakos)! - Combobox and ComboboxMulti gain `allowCreate` (+ optional `createLabel`):
|
|
25
|
+
when the search term matches no option, an `Add "term"` row is offered
|
|
26
|
+
(keyboard included) and picking it reports the raw trimmed term — for
|
|
27
|
+
free-text entry into taxonomy-backed pickers.
|
|
28
|
+
|
|
29
|
+
- [`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
|
|
30
|
+
override** of the built-in `[StarterKit, Markdown]` set (apps declare their
|
|
31
|
+
complete extension set), and three composition props land — `contentClassName`
|
|
32
|
+
(merged onto the editable region), `onReady` (editor instance on create,
|
|
33
|
+
`null` on destroy — the app handle for commands and event wiring), and
|
|
34
|
+
`headingLevels` (one toggle per level; `labels.heading` is now
|
|
35
|
+
`(level) => string`, default `Heading ${level}`). History buttons now reflect
|
|
36
|
+
undo/redo availability and disable while there is nothing to undo/redo.
|
|
37
|
+
|
|
3
38
|
## 0.21.0
|
|
4
39
|
|
|
5
40
|
### 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) |
|
|
@@ -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"]}
|
|
@@ -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;
|
|
@@ -117,11 +138,16 @@ var RichTextEditor = React.forwardRef(
|
|
|
117
138
|
editor.off("update", handler);
|
|
118
139
|
};
|
|
119
140
|
}, [editor, isMounted]);
|
|
141
|
+
const editableRef = React.useRef(!disabled);
|
|
120
142
|
React.useEffect(() => {
|
|
121
143
|
if (editor === null || editor.isDestroyed) {
|
|
122
144
|
return;
|
|
123
145
|
}
|
|
124
|
-
|
|
146
|
+
if (editableRef.current === !disabled) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
editableRef.current = !disabled;
|
|
150
|
+
editor.setEditable(!disabled, false);
|
|
125
151
|
}, [editor, disabled]);
|
|
126
152
|
React.useEffect(() => {
|
|
127
153
|
if (editor === null || editor.isDestroyed) {
|
|
@@ -139,26 +165,47 @@ var RichTextEditor = React.forwardRef(
|
|
|
139
165
|
lastEmittedRef.current = value;
|
|
140
166
|
}, [editor, value, toApp, toDocument]);
|
|
141
167
|
const groups = toolbar === false ? [] : toolbar ?? DEFAULT_TOOLBAR;
|
|
142
|
-
const
|
|
168
|
+
const buttonClass = (active) => cn(
|
|
169
|
+
"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",
|
|
170
|
+
active && "bg-[var(--as-surface-active)] text-[var(--as-fg)]"
|
|
171
|
+
);
|
|
172
|
+
const renderButton = (key, group, onClick, active, buttonDisabled = disabled) => {
|
|
143
173
|
const Icon = mergedIcons[key];
|
|
174
|
+
const label = mergedLabels[key];
|
|
144
175
|
return /* @__PURE__ */ jsx(
|
|
145
176
|
"button",
|
|
146
177
|
{
|
|
147
178
|
type: "button",
|
|
148
|
-
"aria-label":
|
|
179
|
+
"aria-label": label,
|
|
149
180
|
"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
|
-
),
|
|
181
|
+
title: label,
|
|
182
|
+
disabled: buttonDisabled,
|
|
183
|
+
className: buttonClass(active),
|
|
156
184
|
onClick,
|
|
157
185
|
children: /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": true })
|
|
158
186
|
},
|
|
159
187
|
`${group}-${key}`
|
|
160
188
|
);
|
|
161
189
|
};
|
|
190
|
+
const historyDisabled = (can) => disabled || editor === null || editor.can()[can]() !== true;
|
|
191
|
+
const renderHeadingButton = (level) => {
|
|
192
|
+
const Icon = mergedIcons.heading;
|
|
193
|
+
const label = mergedLabels.heading(level);
|
|
194
|
+
return /* @__PURE__ */ jsx(
|
|
195
|
+
"button",
|
|
196
|
+
{
|
|
197
|
+
type: "button",
|
|
198
|
+
"aria-label": label,
|
|
199
|
+
"aria-pressed": editor?.isActive("heading", { level }) === true,
|
|
200
|
+
title: label,
|
|
201
|
+
disabled,
|
|
202
|
+
className: buttonClass(editor?.isActive("heading", { level }) === true),
|
|
203
|
+
onClick: () => editor?.chain().focus().toggleHeading({ level }).run(),
|
|
204
|
+
children: /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": true })
|
|
205
|
+
},
|
|
206
|
+
`heading-${level}`
|
|
207
|
+
);
|
|
208
|
+
};
|
|
162
209
|
return /* @__PURE__ */ jsxs(
|
|
163
210
|
"div",
|
|
164
211
|
{
|
|
@@ -181,20 +228,17 @@ var RichTextEditor = React.forwardRef(
|
|
|
181
228
|
"undo",
|
|
182
229
|
"history",
|
|
183
230
|
() => editor?.chain().focus().undo().run(),
|
|
184
|
-
false
|
|
231
|
+
false,
|
|
232
|
+
historyDisabled("undo")
|
|
185
233
|
) : null,
|
|
186
234
|
groups.includes("history") ? renderButton(
|
|
187
235
|
"redo",
|
|
188
236
|
"history",
|
|
189
237
|
() => 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
|
|
238
|
+
false,
|
|
239
|
+
historyDisabled("redo")
|
|
197
240
|
) : null,
|
|
241
|
+
groups.includes("heading") ? levels.map((level) => renderHeadingButton(level)) : null,
|
|
198
242
|
groups.includes("format") ? renderButton(
|
|
199
243
|
"bold",
|
|
200
244
|
"format",
|
|
@@ -249,5 +293,5 @@ var RichTextEditor = React.forwardRef(
|
|
|
249
293
|
);
|
|
250
294
|
|
|
251
295
|
export { RichTextEditor };
|
|
252
|
-
//# sourceMappingURL=chunk-
|
|
253
|
-
//# sourceMappingURL=chunk-
|
|
296
|
+
//# sourceMappingURL=chunk-AY77TWLT.js.map
|
|
297
|
+
//# sourceMappingURL=chunk-AY77TWLT.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-AY77TWLT.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 const editableRef = React.useRef(!disabled)\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n if (editableRef.current === !disabled) {\n return\n }\n editableRef.current = !disabled\n editor.setEditable(!disabled, false)\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"]}
|
|
@@ -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
|