laif-ds 1.1.1 → 1.1.3

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/dist/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable technical changes to the laif-ds core will be documented in this fil
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [laif-ds@1.1.3]
9
+
10
+ ### 🚀 Added
11
+
12
+ - **AppEditor**: Added link support — `[text](url)` in `defaultValue` now renders as a link and round-trips correctly instead of breaking the editor
13
+ - **AppEditor**: Added an opt-in link toolbar with a button that opens a URL + label form, plus an `insertLink` handle
14
+
15
+ ### 🐛 Fixed
16
+
17
+ - **AppEditor**: Fixed underline and strikethrough so they render together when both are applied, instead of one being stripped
18
+ - **AppEditor**: Added an inline code toggle, with inline code now using a readable token in dark mode
19
+ - **AppEditor**: Fixed the font-format toolbar so each format's pressed state follows only its own selection state
20
+
21
+ ## [laif-ds@1.1.2]
22
+
23
+ ### 🐛 Fixed
24
+
25
+ - **AppDataGrid**: Fixed the toolbar search showing two clear ("×") buttons instead of one
26
+ - **Input**: Added a `clearable` prop (default `true`) to control whether the built-in clear button is shown on `type="search"` inputs
27
+
8
28
  ## [laif-ds@1.1.1]
9
29
 
10
30
  ### 🔧 Changed
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- var e = { exports: {} };
2
+ var e = {};
3
3
  export {
4
- e as __module
4
+ e as __exports
5
5
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- var e = {};
2
+ var e = { exports: {} };
3
3
  export {
4
- e as __exports
4
+ e as __module
5
5
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-30T14:57:20.989Z",
3
+ "generatedAt": "2026-10-19T16:27:31.329Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "1.1.1"
6
+ "version": "1.1.3"
7
7
  },
8
8
  "summary": {
9
- "scannedFiles": 502,
9
+ "scannedFiles": 503,
10
10
  "deprecatedComponentsCount": 5,
11
11
  "deprecatedComponentsUsedCount": 3,
12
12
  "componentsWithoutExamplesCount": 5,
@@ -8,18 +8,29 @@ Rich text editor powered by Lexical with optional Markdown sync. Supports config
8
8
 
9
9
  ## Props
10
10
 
11
- | Prop | Type | Default | Description |
12
- | ---------------- | ------------------------------------------------------------------ | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
13
- | `defaultValue` | `string` | `undefined` | Initial content. Interpreted as Markdown when `onlyMarkdown=true`, plain text otherwise. |
14
- | `onValueChange` | `(markdown: string, meta: { mentions: MentionItem[] }) => void` | `undefined` | Fires on every edit with the current Markdown and a metadata object. `meta.mentions` is the deduped (by `id`) list of mentions in the text (empty when mentions are disabled). Takes precedence over `onMarkdownEdit`. |
15
- | `onMarkdownEdit` | `(markdown: string) => void` | `undefined` | **Deprecated** — use `onValueChange`. Still honored as a fallback when `onValueChange` is not provided, but never receives mention metadata. |
16
- | `plugins` | `("clear" \| "counter")[]` | `[]` | Enable optional plugins: clear buttons, character counter. |
17
- | `toolbars` | `("block-format" \| "font-format" \| "history")[]` | `[]` | Enable toolbar groups. |
18
- | `placeholder` | `string` | `"Start typing..."` | Placeholder for empty editor. |
19
- | `onlyMarkdown` | `boolean` | `true` | Treat `defaultValue` as Markdown and sync editor to Markdown. If `false`, `defaultValue` is plain text. |
20
- | `className` | `string` | `"overflow-hidden rounded-lg border border-d-border"` | Extra classes for the content editable. |
21
- | `mentions` | `MentionItem[] \| (() => MentionItem[] \| Promise<MentionItem[]>)` | `undefined` | Enables @mention support when provided. Either a ready array (filtered client-side) or a **loader** called once on first menu open (no preload on mount). When omitted, no mention node/plugin/transformer is registered and output is identical to a mention-less editor. |
22
- | `mentionTrigger` | `string` | `"@"` | Single character that opens the mention typeahead menu. |
11
+ | Prop | Type | Default | Description |
12
+ | ---------------- | ---------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ---------------------- |
13
+ | `defaultValue` | `string` | `undefined` | Initial content. Interpreted as Markdown when `onlyMarkdown=true`, plain text otherwise. |
14
+ | `onValueChange` | `(markdown: string, meta: { mentions: MentionItem[] }) => void` | `undefined` | Fires on every edit with the current Markdown and a metadata object. `meta.mentions` is the deduped (by `id`) list of mentions in the text (empty when mentions are disabled). Takes precedence over `onMarkdownEdit`. |
15
+ | `onMarkdownEdit` | `(markdown: string) => void` | `undefined` | **Deprecated** — use `onValueChange`. Still honored as a fallback when `onValueChange` is not provided, but never receives mention metadata. |
16
+ | `plugins` | `("clear" \| "counter")[]` | `[]` | Enable optional plugins: clear buttons, character counter. |
17
+ | `toolbars` | `("block-format" \| "font-format" \| "history" \| "link")[]` | `[]` | Enable toolbar groups. |
18
+ | `placeholder` | `string` | `"Start typing..."` | Placeholder for empty editor. |
19
+ | `onlyMarkdown` | `boolean` | `true` | Treat `defaultValue` as Markdown and sync editor to Markdown. If `false`, `defaultValue` is plain text. |
20
+ | `className` | `string` | `"overflow-hidden rounded-lg border border-d-border"` | Extra classes for the content editable. |
21
+ | `mentions` | `MentionItem[] \| (() => MentionItem[] \| Promise<MentionItem[]>)` | `undefined` | Enables @mention support when provided. Either a ready array (filtered client-side) or a **loader** called once on first menu open (no preload on mount). When omitted, no mention node/plugin/transformer is registered and output is identical to a mention-less editor. |
22
+ | `mentionTrigger` | `string` | `"@"` | Single character that opens the mention typeahead menu. |
23
+ | `ref` | `Ref<AppEditorHandle>` | `undefined` | Imperative handle — see `AppEditorHandle` below. |
24
+
25
+ ### AppEditorHandle
26
+
27
+ ```ts
28
+ interface AppEditorHandle {
29
+ // Inserts a hyperlink at the caret (end of the text when there is no
30
+ // selection) and leaves the caret after it. `text` defaults to `url`.
31
+ insertLink: (url: string, text?: string) => void;
32
+ }
33
+ ```
23
34
 
24
35
  ### MentionItem
25
36
 
@@ -41,12 +52,14 @@ type MentionItem = {
41
52
  - **Toolbars**:
42
53
  - `history`: undo/redo toolbar.
43
54
  - `block-format`: heading levels (h1-h3), numbered/bulleted/check lists, blockquote.
44
- - `font-format`: bold, italic, underline, strikethrough, inline code.
55
+ - `font-format`: bold, italic, underline, strikethrough, inline code. Each button is an independent toggle whose pressed state follows the selection; formats combine freely (underline + strikethrough together render both lines and export as `~~<u>text</u>~~`).
56
+ - `link`: a link button that opens a form with **URL** and **Etichetta** (label; form copy is Italian like the block-format menu). The label is prefilled with the selected text; with the caret inside a link the button shows as pressed and the form edits that link. A URL without a scheme gets `https://` (`example.com` → `https://example.com`); an empty label falls back to the URL.
45
57
  - **Plugins**:
46
58
  - `clear`: clear actions in the footer.
47
59
  - `counter`: UTF-16 character counter in the footer.
48
60
  - **Editing**: Autosave via `onValueChange`. Keyboard navigation and selection per Lexical defaults.
49
61
  - **Markdown Features**: Full support for headings, lists, quotes, links, inline code, bold, italic, strikethrough, and custom underline syntax.
62
+ - **Links**: `[text](url)` in `defaultValue` renders as a link and is emitted back unchanged; links pasted as HTML are kept as links. Enable the `link` toolbar for a user-facing button; to insert a link programmatically (e.g. a "quick insert" action outside the editor) call `ref.current.insertLink(url, text)`. Give the triggering button `onMouseDown={(e) => e.preventDefault()}` so the editor keeps its caret.
50
63
  - **Mentions** (opt-in via `mentions`):
51
64
  - `mentions` is either a ready `MentionItem[]` or a **loader function** `() => MentionItem[] | Promise<MentionItem[]>`. The loader is called **once, the first time the menu opens**, so a large list is never preloaded on mount; while it resolves the menu shows a `Loading…` row, and on failure a `Couldn't load mentions` row (re-opening the menu retries). The resolved list is then filtered client-side like the array form.
52
65
  - With the **loader form**, `meta.mentions` cannot reconcile against a synchronous source list, so its emitted items carry `id`/`label`/`value` from the chip but **not `sublabel`** (which is menu-only metadata). The array form preserves `sublabel`.
@@ -153,6 +166,31 @@ export function UnderlineExample() {
153
166
  }
154
167
  ```
155
168
 
169
+ ### Inserting a link from outside the editor
170
+
171
+ ```tsx
172
+ import { AppEditor, type AppEditorHandle } from "laif-ds";
173
+ import { useRef } from "react";
174
+
175
+ export function ReplyEditor() {
176
+ const editorRef = useRef<AppEditorHandle>(null);
177
+ return (
178
+ <>
179
+ <AppEditor ref={editorRef} onValueChange={console.log} />
180
+ <button
181
+ type="button"
182
+ onMouseDown={(e) => e.preventDefault()}
183
+ onClick={() =>
184
+ editorRef.current?.insertLink("https://example.com", "Example")
185
+ }
186
+ >
187
+ Insert link
188
+ </button>
189
+ </>
190
+ );
191
+ }
192
+ ```
193
+
156
194
  ### Mentions
157
195
 
158
196
  ```tsx
@@ -10,16 +10,17 @@ Text input component with label, sizes, optional left/right icons, custom start/
10
10
 
11
11
  Extends native `<input>` props (except `size` and `label` which are redefined).
12
12
 
13
- | Prop | Type | Default | Description |
14
- | ---------------- | ----------------- | ---------------- | ------------------------------------------------------------- | ---------------------------------- | ------------------------------ |
15
- | `label` | `string | React.ReactNode` | `undefined` | Field label shown above the input. |
16
- | `labelClassName` | `string` | `""` | Extra classes for the label. |
17
- | `size` | `"sm" | "default" | "lg"` | `"default"` | Controls height and font-size. |
18
- | `iconLeft` | `IconName` | `undefined` | Optional left icon (uses `Icon`). |
19
- | `iconRight` | `IconName` | `undefined` | Optional right icon (ignored when `type="password"`). |
20
- | `startContent` | `React.ReactNode` | `undefined` | Custom content before the input (coexists with `iconLeft`). |
21
- | `endContent` | `React.ReactNode` | `undefined` | Custom content after the input (coexists with `iconRight`). |
22
- | `errorMessage` | `string` | `undefined` | Custom error message (shown after interaction/invalid state). |
13
+ | Prop | Type | Default | Description |
14
+ | ---------------- | ----------------- | ---------------- | -------------------------------------------------------------------------------------- | ---------------------------------- | ------------------------------ |
15
+ | `label` | `string | React.ReactNode` | `undefined` | Field label shown above the input. |
16
+ | `labelClassName` | `string` | `""` | Extra classes for the label. |
17
+ | `size` | `"sm" | "default" | "lg"` | `"default"` | Controls height and font-size. |
18
+ | `iconLeft` | `IconName` | `undefined` | Optional left icon (uses `Icon`). |
19
+ | `iconRight` | `IconName` | `undefined` | Optional right icon (ignored when `type="password"`). |
20
+ | `startContent` | `React.ReactNode` | `undefined` | Custom content before the input (coexists with `iconLeft`). |
21
+ | `endContent` | `React.ReactNode` | `undefined` | Custom content after the input (coexists with `iconRight`). |
22
+ | `clearable` | `boolean` | `true` | `type="search"` only: built-in clear «×». Set `false` if `endContent` renders its own. |
23
+ | `errorMessage` | `string` | `undefined` | Custom error message (shown after interaction/invalid state). |
23
24
 
24
25
  All other standard input attributes (e.g., `type`, `placeholder`, `required`, `min`, `max`, `pattern`, etc.) are supported.
25
26
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": "1.1.0",
3
- "generatedAt": "2026-09-30T14:57:20.437Z",
3
+ "generatedAt": "2026-10-19T16:27:30.775Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "1.1.1"
6
+ "version": "1.1.3"
7
7
  },
8
8
  "stats": {
9
9
  "documentedComponentCount": 97,
@@ -702,6 +702,7 @@
702
702
  "hasPropsTable": true,
703
703
  "hasExamples": true,
704
704
  "exampleTitles": [
705
+ "AppEditorHandle",
705
706
  "MentionItem",
706
707
  "Mention markdown serialization",
707
708
  "Dedup, reconciliation, and id types",
@@ -709,6 +710,7 @@
709
710
  "Full Toolbar + Plugins",
710
711
  "Markdown Default Value",
711
712
  "Underline Support",
713
+ "Inserting a link from outside the editor",
712
714
  "Mentions",
713
715
  "Async mentions (lazy loader)"
714
716
  ],
@@ -717,10 +719,10 @@
717
719
  },
718
720
  "metadata": {
719
721
  "props": {
720
- "totalProps": 10,
722
+ "totalProps": 11,
721
723
  "requiredPropsCount": 0,
722
- "typedPropsCount": 10,
723
- "describedPropsCount": 10
724
+ "typedPropsCount": 11,
725
+ "describedPropsCount": 11
724
726
  },
725
727
  "accessibility": {
726
728
  "hasCoverage": true
@@ -741,9 +743,10 @@
741
743
  },
742
744
  "typeReferences": [
743
745
  "interface AppEditorChangeMeta {\r",
746
+ "interface AppEditorHandle {\r",
744
747
  "interface AppEditorProps {\r",
745
748
  "type AppEditorPlugin = \"clear\" | \"counter\";\r",
746
- "type AppEditorToolbar = \"block-format\" | \"font-format\" | \"history\";\r"
749
+ "type AppEditorToolbar = \"block-format\" | \"font-format\" | \"history\" | \"link\";\r"
747
750
  ]
748
751
  },
749
752
  {
@@ -3866,10 +3869,10 @@
3866
3869
  },
3867
3870
  "metadata": {
3868
3871
  "props": {
3869
- "totalProps": 8,
3872
+ "totalProps": 9,
3870
3873
  "requiredPropsCount": 0,
3871
- "typedPropsCount": 8,
3872
- "describedPropsCount": 8
3874
+ "typedPropsCount": 9,
3875
+ "describedPropsCount": 9
3873
3876
  },
3874
3877
  "accessibility": {
3875
3878
  "hasCoverage": true
@@ -6536,5 +6539,5 @@
6536
6539
  ]
6537
6540
  }
6538
6541
  ],
6539
- "checksum": "42274993231bb66b79f2d2710734b3e28a70417744ddd7b9b9b197532ea72713"
6542
+ "checksum": "b0ed5b1350ee2fc4bbde0cb81a833109b4df2630d283a810457c8c38d2aec823"
6540
6543
  }
@@ -1,47 +1,51 @@
1
1
  "use client";
2
- import { jsx as i } from "react/jsx-runtime";
3
- import { $isTableSelection as m } from "../../../../node_modules/@lexical/table/dist/LexicalTable.prod.js";
4
- import { FORMAT_TEXT_COMMAND as l, $isRangeSelection as n } from "../../../../node_modules/lexical/dist/Lexical.prod.js";
5
- import { useState as d } from "react";
6
- import { useToolbarContext as c } from "../../context/toolbar-context.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import { $isTableSelection as n } from "../../../../node_modules/@lexical/table/dist/LexicalTable.prod.js";
4
+ import { FORMAT_TEXT_COMMAND as s, $isRangeSelection as m } from "../../../../node_modules/lexical/dist/Lexical.prod.js";
5
+ import { useState as c } from "react";
6
+ import { useToolbarContext as d } from "../../context/toolbar-context.js";
7
7
  import { useUpdateToolbarHandler as p } from "../../editor-hooks/use-update-toolbar.js";
8
- import { Toggle as f } from "../../../ui/toggle.js";
9
- import u from "../../../../node_modules/lucide-react/dist/esm/icons/code.js";
10
- import T from "../../../../node_modules/lucide-react/dist/esm/icons/strikethrough.js";
11
- import h from "../../../../node_modules/lucide-react/dist/esm/icons/underline.js";
12
- import b from "../../../../node_modules/lucide-react/dist/esm/icons/italic.js";
8
+ import { Toggle as u } from "../../../ui/toggle.js";
9
+ import f from "../../../../node_modules/lucide-react/dist/esm/icons/code.js";
10
+ import h from "../../../../node_modules/lucide-react/dist/esm/icons/strikethrough.js";
11
+ import b from "../../../../node_modules/lucide-react/dist/esm/icons/underline.js";
12
+ import T from "../../../../node_modules/lucide-react/dist/esm/icons/italic.js";
13
13
  import g from "../../../../node_modules/lucide-react/dist/esm/icons/bold.js";
14
- const C = {
14
+ const S = {
15
15
  bold: g,
16
- italic: b,
17
- underline: h,
18
- strikethrough: T,
19
- code: u
16
+ italic: T,
17
+ underline: b,
18
+ strikethrough: h,
19
+ code: f
20
+ }, C = {
21
+ bold: "Bold",
22
+ italic: "Italic",
23
+ underline: "Underline",
24
+ strikethrough: "Strikethrough",
25
+ code: "Code"
20
26
  };
21
27
  function R({
22
- format: r
28
+ format: o
23
29
  }) {
24
- const { activeEditor: a } = c(), [e, t] = d(!1);
25
- p((o) => {
26
- (n(o) || m(o)) && "hasFormat" in o && t(o.hasFormat(r));
30
+ const { activeEditor: e } = d(), [i, a] = c(!1);
31
+ p((r) => {
32
+ (m(r) || n(r)) && "hasFormat" in r && a(r.hasFormat(o));
27
33
  });
28
- const s = C[r];
29
- return /* @__PURE__ */ i(
30
- f,
34
+ const l = S[o];
35
+ return /* @__PURE__ */ t(
36
+ u,
31
37
  {
32
- "aria-label": "Toggle bold",
38
+ "aria-label": C[o],
33
39
  variant: "outline",
34
40
  size: "sm",
35
- defaultPressed: e,
36
- pressed: e,
37
- onPressedChange: t,
41
+ pressed: i,
38
42
  onClick: () => {
39
- a.dispatchCommand(
40
- l,
41
- r
43
+ e.dispatchCommand(
44
+ s,
45
+ o
42
46
  );
43
47
  },
44
- children: /* @__PURE__ */ i(s, { className: "h-4 w-4" })
48
+ children: /* @__PURE__ */ t(l, { className: "h-4 w-4" })
45
49
  }
46
50
  );
47
51
  }
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { jsxs as u, jsx as i } from "react/jsx-runtime";
3
+ import { $createLinkNode as S, $isLinkNode as $ } from "../../../../node_modules/@lexical/link/dist/LexicalLink.prod.js";
4
+ import { $getSelection as m, $isRangeSelection as p, $getRoot as N, $createTextNode as b, $setSelection as T, $findMatchingParent as z } from "../../../../node_modules/lexical/dist/Lexical.prod.js";
5
+ import { useState as s } from "react";
6
+ import { useToolbarContext as U } from "../../context/toolbar-context.js";
7
+ import { useUpdateToolbarHandler as E } from "../../editor-hooks/use-update-toolbar.js";
8
+ import { Button as L } from "../../../ui/button.js";
9
+ import { Input as x } from "../../../ui/input.js";
10
+ import { Popover as P, PopoverTrigger as R, PopoverContent as y } from "../../../ui/popover.js";
11
+ import { Toggle as I } from "../../../ui/toggle.js";
12
+ import O from "../../../../node_modules/lucide-react/dist/esm/icons/link.js";
13
+ function f(e) {
14
+ return p(e) ? z(e.anchor.getNode(), $) : null;
15
+ }
16
+ function j(e, n) {
17
+ let o = m();
18
+ if (p(o) || (N().selectEnd(), o = m()), !p(o)) return;
19
+ const l = S(e).append(b(n || e)), r = f(o);
20
+ if (r) {
21
+ r.replace(l), l.selectNext(0, 0);
22
+ return;
23
+ }
24
+ o.insertNodes(
25
+ o.isCollapsed() ? [l, b(" ")] : [l]
26
+ );
27
+ }
28
+ function w(e) {
29
+ const n = e.trim();
30
+ return /^[a-z][a-z\d+.-]*:/i.test(n) ? n : `https://${n}`;
31
+ }
32
+ function W() {
33
+ const { activeEditor: e } = U(), [n, o] = s(!1), [l, r] = s(!1), [a, g] = s(""), [c, h] = s(""), [k, C] = s(
34
+ null
35
+ );
36
+ return E((t) => {
37
+ o(f(t) !== null);
38
+ }), /* @__PURE__ */ u(P, { open: l, onOpenChange: (t) => {
39
+ t && e.getEditorState().read(() => {
40
+ const d = m(), v = f(d);
41
+ C(d?.clone() ?? null), g(v?.getURL() ?? ""), h(v?.getTextContent() ?? d?.getTextContent() ?? "");
42
+ }), r(t);
43
+ }, children: [
44
+ /* @__PURE__ */ i(R, { asChild: !0, children: /* @__PURE__ */ i(
45
+ I,
46
+ {
47
+ "aria-label": n ? "Edit link" : "Insert link",
48
+ variant: "outline",
49
+ size: "sm",
50
+ pressed: n,
51
+ children: /* @__PURE__ */ i(O, { className: "h-4 w-4" })
52
+ }
53
+ ) }),
54
+ /* @__PURE__ */ i(y, { align: "start", className: "w-80 p-3", children: /* @__PURE__ */ u("form", { onSubmit: (t) => {
55
+ t.preventDefault(), a.trim() && (e.focus(), e.update(() => {
56
+ k && T(k.clone()), j(w(a), c.trim() ? c : void 0);
57
+ }), r(!1));
58
+ }, className: "flex flex-col gap-2", children: [
59
+ /* @__PURE__ */ i(
60
+ x,
61
+ {
62
+ label: "URL",
63
+ type: "text",
64
+ inputMode: "url",
65
+ placeholder: "https://",
66
+ value: a,
67
+ onChange: (t) => g(t.target.value),
68
+ autoFocus: !0
69
+ }
70
+ ),
71
+ /* @__PURE__ */ i(
72
+ x,
73
+ {
74
+ label: "Etichetta",
75
+ placeholder: "Testo mostrato al posto dell'URL",
76
+ value: c,
77
+ onChange: (t) => h(t.target.value)
78
+ }
79
+ ),
80
+ /* @__PURE__ */ u("div", { className: "flex justify-end gap-2", children: [
81
+ /* @__PURE__ */ i(
82
+ L,
83
+ {
84
+ type: "button",
85
+ variant: "ghost",
86
+ size: "sm",
87
+ onClick: () => r(!1),
88
+ children: "Annulla"
89
+ }
90
+ ),
91
+ /* @__PURE__ */ i(L, { type: "submit", size: "sm", disabled: !a.trim(), children: n ? "Aggiorna link" : "Inserisci link" })
92
+ ] })
93
+ ] }) })
94
+ ] });
95
+ }
96
+ export {
97
+ j as $insertLink,
98
+ W as LinkToolbarPlugin
99
+ };
@@ -35,13 +35,16 @@ const t = {
35
35
  hashtag: "text-blue-600 bg-blue-100 rounded-md px-1",
36
36
  text: {
37
37
  bold: "font-bold",
38
- code: "bg-gray-100 p-1 rounded-md",
38
+ code: "bg-d-muted p-1 rounded-md",
39
39
  italic: "italic",
40
40
  strikethrough: "line-through",
41
41
  subscript: "sub",
42
42
  superscript: "sup",
43
43
  underline: "underline",
44
- underlineStrikethrough: "underline line-through"
44
+ // Single token, disjoint from `underline`/`line-through`: Lexical removes the
45
+ // individual format classes when both are set, and both utilities would
46
+ // otherwise override each other's `text-decoration-line`.
47
+ underlineStrikethrough: "[text-decoration-line:underline_line-through]"
45
48
  },
46
49
  image: "relative inline-block user-select-none cursor-default editor-image",
47
50
  inlineImage: "relative inline-block user-select-none cursor-default inline-editor-image",
@@ -625,6 +625,7 @@ const Pt = [
625
625
  ),
626
626
  iconLeft: "Search",
627
627
  size: "sm",
628
+ clearable: !1,
628
629
  endContent: o.state.query.search === "" ? void 0 : /* @__PURE__ */ n(
629
630
  "button",
630
631
  {