@devalok/shilp-sutra 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/AGENTS.md +36 -12
  2. package/BREAKING.json +46 -0
  3. package/MIGRATION.md +35 -0
  4. package/dist/_chunks/emoji-suggestion.js +124 -0
  5. package/dist/_chunks/emoji-suggestion.js.map +1 -0
  6. package/dist/_chunks/emoji.js +1115 -0
  7. package/dist/_chunks/emoji.js.map +1 -0
  8. package/dist/_chunks/tiptap.js.map +1 -1
  9. package/dist/composed/emoji-picker.d.ts +19 -9
  10. package/dist/composed/emoji-picker.d.ts.map +1 -1
  11. package/dist/composed/emoji-picker.js +87 -68
  12. package/dist/composed/emoji-picker.js.map +1 -1
  13. package/dist/composed/extensions/emoji-data.d.ts +1 -14
  14. package/dist/composed/extensions/emoji-data.d.ts.map +1 -1
  15. package/dist/composed/extensions/emoji-node.d.ts +0 -3
  16. package/dist/composed/extensions/emoji-node.d.ts.map +1 -1
  17. package/dist/composed/extensions/emoji-node.js +9 -34
  18. package/dist/composed/extensions/emoji-node.js.map +1 -1
  19. package/dist/composed/extensions/emoji-suggestion.d.ts +2 -2
  20. package/dist/composed/extensions/emoji-suggestion.d.ts.map +1 -1
  21. package/dist/composed/extensions/emoji-suggestion.js +2 -116
  22. package/dist/composed/rich-chat-input.d.ts.map +1 -1
  23. package/dist/composed/rich-chat-input.js +554 -575
  24. package/dist/composed/rich-chat-input.js.map +1 -1
  25. package/dist/composed/rich-text-editor.d.ts.map +1 -1
  26. package/dist/composed/rich-text-editor.js +167 -190
  27. package/dist/composed/rich-text-editor.js.map +1 -1
  28. package/docs/components/composed/emoji-picker.md +19 -17
  29. package/docs/components/composed/rich-text-editor.md +1 -1
  30. package/docs/components/ui/table-row-link.md +1 -1
  31. package/docs/recipes/index.md +1 -1
  32. package/docs/recipes/install-astro.md +15 -12
  33. package/docs/recipes/install-next-app-router.md +20 -12
  34. package/docs/recipes/install-next-pages.md +3 -1
  35. package/docs/recipes/install-remix.md +16 -13
  36. package/docs/recipes/install-tanstack-start.md +19 -12
  37. package/docs/recipes/install-vite.md +18 -15
  38. package/docs/recipes/troubleshoot.md +7 -8
  39. package/llms.txt +2 -2
  40. package/mcp-manifest.json +29 -66
  41. package/package.json +6 -9
  42. package/skill/SKILL.md +1 -1
  43. package/skill/references/components.md +2 -2
  44. package/skill/references/setup-astro.md +15 -12
  45. package/skill/references/setup-next-app-router.md +20 -12
  46. package/skill/references/setup-next-pages.md +3 -1
  47. package/skill/references/setup-remix.md +16 -13
  48. package/skill/references/setup-tanstack-start.md +19 -12
  49. package/skill/references/setup-vite.md +18 -15
  50. package/skill/references/troubleshoot.md +7 -8
  51. package/dist/_chunks/emoji-data.js +0 -45
  52. package/dist/_chunks/emoji-data.js.map +0 -1
  53. package/dist/composed/extensions/emoji-suggestion.js.map +0 -1
@@ -44,18 +44,21 @@ pnpm add sonner
44
44
 
45
45
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
46
46
 
47
- Some components ship hard peers as optional. **Install BEFORE first import** or `vite dev` / `vite build` will fail with `Failed to resolve import`. Skip if you only use core components.
48
-
49
- | When you import… | Install |
50
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
51
- | `@devalok/shilp-sutra/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
52
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
53
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
54
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
55
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
56
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
57
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
58
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
47
+ Some components ship hard peers as optional. **Install BEFORE first import.** ⚠ On Vite 8 / Rolldown a missing peer does **not** fail the build — Rolldown silently replaces the import with a stub that throws `Could not resolve "…"` in the browser at runtime, while `vite build` still exits 0. A green build is therefore **not** proof the app works. Confirm coverage with the MCP `verify_setup` / `preflight` tools or the table below. Skip only if you use core components.
48
+
49
+ | When you import… | Install |
50
+ |---|---|
51
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
52
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
53
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
54
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
55
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
56
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
57
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
58
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
59
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
60
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
61
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
59
62
 
60
63
  ## 3. Wire Tailwind 4 in `vite.config.ts`
61
64
 
@@ -138,7 +141,7 @@ If you installed `sonner`, mount the Toaster once near the app root:
138
141
  import { StrictMode } from "react";
139
142
  import { createRoot } from "react-dom/client";
140
143
  import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
141
- import { App } from "./App";
144
+ import App from "./App";
142
145
  import "./index.css";
143
146
 
144
147
  createRoot(document.getElementById("root")!).render(
@@ -151,14 +154,14 @@ createRoot(document.getElementById("root")!).render(
151
154
 
152
155
  ## 7. Verify
153
156
 
154
- Replace `src/App.tsx`:
157
+ Replace `src/App.tsx` (keep the **default export** — the `create-vite` template's `main.tsx` imports it as `import App from "./App"`, so a named export would break the build with `TS2613: Module has no default export`):
155
158
 
156
159
  ```tsx
157
160
  import { Button } from "@devalok/shilp-sutra/ui/button";
158
161
  import { Stack } from "@devalok/shilp-sutra/ui/stack";
159
162
  import { Text } from "@devalok/shilp-sutra/ui/text";
160
163
 
161
- export function App() {
164
+ export default function App() {
162
165
  return (
163
166
  <Stack className="p-ds-08" gap="ds-04">
164
167
  <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
@@ -97,26 +97,25 @@ Add:
97
97
  transpilePackages: ["@devalok/shilp-sutra"],
98
98
  ```
99
99
 
100
- ## Symptom: Build error `Cannot find module 'sonner' / 'input-otp' / 'date-fns' / '@tiptap/react' / 'react-pdf' / 'react-markdown' / '@emoji-mart/react'`
100
+ ## Symptom: Build error `Cannot find module 'sonner' / 'input-otp' / 'date-fns' / 'react-pdf' / 'react-markdown'` OR (on Vite 8) a runtime `Could not resolve "…"` from a green build
101
101
 
102
- **Diagnosis:** an optional peer dependency is missing. Each component below has a peer it pulls only when imported. Install the matching peer (always BEFORE the first import):
102
+ **Diagnosis:** an optional peer dependency is missing. Each component below has a peer it pulls only when imported. Install the matching peer (always BEFORE the first import). On Vite 8 / Rolldown this does **not** fail the build — it throws at runtime — so run the MCP `verify_setup` tool to catch it early.
103
103
 
104
104
  | You imported (per-component subpath) | Install |
105
105
  |--------------------------------------|-----------------------------------------------------------------------------------------------|
106
106
  | `…/ui/toaster` or `…/ui/toast` | `pnpm add sonner` |
107
107
  | `…/ui/input-otp` | `pnpm add input-otp` |
108
- | `…/composed/date-picker` | `pnpm add date-fns` |
109
- | `…/composed/emoji-picker` | `pnpm add @emoji-mart/data @emoji-mart/react` |
110
- | `…/composed/extensions/emoji-node` or `…/extensions/emoji-suggestion` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
111
- | `…/composed/rich-text-editor` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
112
- | `…/composed/rich-chat-input` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
108
+ | `…/composed/date-picker` or `…/composed/schedule-view` | `pnpm add date-fns` |
109
+ | `…/ui/data-table` or `…/ui/data-table-toolbar` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
113
110
  | `…/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
114
111
  | `…/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
115
112
  | `…/ai/block-renderer`, `…/ai/blocks/text`, `…/ai/blocks/error` | `pnpm add react-markdown remark-gfm` |
116
- | Any `…/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
113
+ | Any `…/ui/charts/*` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
117
114
 
118
115
  These ship as **optional** peers so consumers who never render the matching component don't pay the install cost. Once you import the component, the peer becomes required. Each affected component's JSDoc carries the same install hint — hover the import in your editor to see it inline.
119
116
 
117
+ **No longer peers (bundled since the frimousse migration):** the emoji picker (`…/composed/emoji-picker`) and the rich-text editors (`…/composed/rich-text-editor`, `…/composed/rich-chat-input`) bundle their dependencies (frimousse, `@emoji-mart/data`, TipTap) into a lazy chunk — you do **not** install anything for them. `@tabler/icons-react` is a required peer that most package managers auto-install.
118
+
120
119
  **Catch this at edit time, not build time:** install `@devalok/eslint-plugin-shilp-sutra` (`pnpm add -D @devalok/eslint-plugin-shilp-sutra`, then `shilpSutra.configs['flat/recommended']`). Its `prefer-per-component-import` rule flags peer-cliff symbols imported from a barrel and autofixes the path — surfacing the cliff in your editor before the bundler ever fails.
121
120
 
122
121
  For the full table in your framework's install recipe, see `install-<framework>.md → §2a. Optional peer dependencies`.
@@ -1,45 +0,0 @@
1
- "use client";
2
- import { emojiDataLoaders as e } from "../composed/emoji-picker.js";
3
- //#region src/composed/extensions/emoji-data.ts
4
- var t = (e) => `https://cdn.jsdelivr.net/npm/emoji-datasource-${e}@15.0.1/img/${e}/sheets-256/64.png`, n = null, r = null;
5
- async function i(t) {
6
- if (n === t && r) return r;
7
- let i = await (e[t] ?? e.native)();
8
- return r = i.default ?? i, n = t, r;
9
- }
10
- function a(e, t) {
11
- let n = e.emojis[t];
12
- if (!n) return null;
13
- let r = n.skins[0];
14
- return r ? {
15
- id: n.id,
16
- name: n.name,
17
- native: r.native,
18
- x: r.x ?? 0,
19
- y: r.y ?? 0
20
- } : null;
21
- }
22
- function o(e, t, n = 8) {
23
- let r = Object.values(e.emojis);
24
- if (!t) return r.slice(0, n).map((e) => ({
25
- id: e.id,
26
- name: e.name,
27
- native: e.skins[0]?.native ?? "",
28
- x: e.skins[0]?.x ?? 0,
29
- y: e.skins[0]?.y ?? 0
30
- }));
31
- let i = t.toLowerCase(), a = [];
32
- for (let e of r) {
33
- if (a.length >= n) break;
34
- (e.id.includes(i) || e.name.toLowerCase().includes(i) || e.keywords?.some((e) => e.includes(i))) && a.push({
35
- id: e.id,
36
- name: e.name,
37
- native: e.skins[0]?.native ?? "",
38
- x: e.skins[0]?.x ?? 0,
39
- y: e.skins[0]?.y ?? 0
40
- });
41
- }
42
- return a;
43
- }
44
- //#endregion
45
- export { o as i, i as n, a as r, t };
@@ -1 +0,0 @@
1
- {"version":3,"file":"emoji-data.js","names":[],"sources":["../../src/composed/extensions/emoji-data.ts"],"sourcesContent":["import { emojiDataLoaders } from '../emoji-picker'\n\n// Spritesheet constants — must match emoji-mart's rendering (emoji-datasource v15.0.1)\nexport const SPRITESHEET_URL = (set: string) =>\n `https://cdn.jsdelivr.net/npm/emoji-datasource-${set}@15.0.1/img/${set}/sheets-256/64.png`\nexport const SHEET_COLS = 61\nexport const SHEET_ROWS = 61\n\ninterface EmojiSkin {\n unified: string\n native: string\n x?: number\n y?: number\n}\n\ninterface EmojiEntry {\n id: string\n name: string\n keywords?: string[]\n skins: EmojiSkin[]\n}\n\nexport interface EmojiDataset {\n emojis: Record<string, EmojiEntry>\n sheet?: { cols: number; rows: number }\n}\n\nexport interface ResolvedEmoji {\n id: string\n name: string\n native: string\n x: number\n y: number\n}\n\nlet cachedSet: string | null = null\nlet cachedData: EmojiDataset | null = null\n\nexport async function loadEmojiData(set: string): Promise<EmojiDataset> {\n if (cachedSet === set && cachedData) return cachedData\n const loader = emojiDataLoaders[set] ?? emojiDataLoaders.native\n const mod = await loader()\n cachedData = (mod.default ?? mod) as EmojiDataset\n cachedSet = set\n return cachedData\n}\n\nexport function lookupEmoji(data: EmojiDataset, id: string): ResolvedEmoji | null {\n const entry = data.emojis[id]\n if (!entry) return null\n const skin = entry.skins[0]\n if (!skin) return null\n return {\n id: entry.id,\n name: entry.name,\n native: skin.native,\n x: skin.x ?? 0,\n y: skin.y ?? 0,\n }\n}\n\nexport function searchEmoji(data: EmojiDataset, query: string, limit = 8): ResolvedEmoji[] {\n const entries = Object.values(data.emojis)\n if (!query) {\n return entries.slice(0, limit).map((e) => ({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n }))\n }\n const q = query.toLowerCase()\n const results: ResolvedEmoji[] = []\n for (const e of entries) {\n if (results.length >= limit) break\n if (\n e.id.includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.keywords?.some((k) => k.includes(q))\n ) {\n results.push({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n })\n }\n }\n return results\n}\n"],"mappings":";;AAGA,IAAa,KAAmB,MAC9B,iDAAiD,EAAI,cAAc,EAAI,qBA+BrE,IAA2B,MAC3B,IAAkC;AAEtC,eAAsB,EAAc,GAAoC;AACtE,KAAI,MAAc,KAAO,EAAY,QAAO;CAE5C,IAAM,IAAM,OADG,EAAiB,MAAQ,EAAiB,SAC/B;AAG1B,QAFA,IAAc,EAAI,WAAW,GAC7B,IAAY,GACL;;AAGT,SAAgB,EAAY,GAAoB,GAAkC;CAChF,IAAM,IAAQ,EAAK,OAAO;AAC1B,KAAI,CAAC,EAAO,QAAO;CACnB,IAAM,IAAO,EAAM,MAAM;AAEzB,QADK,IACE;EACL,IAAI,EAAM;EACV,MAAM,EAAM;EACZ,QAAQ,EAAK;EACb,GAAG,EAAK,KAAK;EACb,GAAG,EAAK,KAAK;EACd,GAPiB;;AAUpB,SAAgB,EAAY,GAAoB,GAAe,IAAQ,GAAoB;CACzF,IAAM,IAAU,OAAO,OAAO,EAAK,OAAO;AAC1C,KAAI,CAAC,EACH,QAAO,EAAQ,MAAM,GAAG,EAAM,CAAC,KAAK,OAAO;EACzC,IAAI,EAAE;EACN,MAAM,EAAE;EACR,QAAQ,EAAE,MAAM,IAAI,UAAU;EAC9B,GAAG,EAAE,MAAM,IAAI,KAAK;EACpB,GAAG,EAAE,MAAM,IAAI,KAAK;EACrB,EAAE;CAEL,IAAM,IAAI,EAAM,aAAa,EACvB,IAA2B,EAAE;AACnC,MAAK,IAAM,KAAK,GAAS;AACvB,MAAI,EAAQ,UAAU,EAAO;AAC7B,GACE,EAAE,GAAG,SAAS,EAAE,IAChB,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,UAAU,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,KAEtC,EAAQ,KAAK;GACX,IAAI,EAAE;GACN,MAAM,EAAE;GACR,QAAQ,EAAE,MAAM,IAAI,UAAU;GAC9B,GAAG,EAAE,MAAM,IAAI,KAAK;GACpB,GAAG,EAAE,MAAM,IAAI,KAAK;GACrB,CAAC;;AAGN,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"emoji-suggestion.js","names":[],"sources":["../../../src/composed/extensions/emoji-suggestion.tsx"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport Suggestion, { type SuggestionKeyDownProps,type SuggestionProps } from '@tiptap/suggestion'\nimport { PluginKey } from 'prosemirror-state'\nimport * as React from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\n\nimport { cn } from '../../ui/lib/utils'\nimport { loadEmojiData, type ResolvedEmoji, searchEmoji, SHEET_COLS, SHEET_ROWS,SPRITESHEET_URL } from './emoji-data'\n\n// Re-export for external consumers\nexport type { ResolvedEmoji as EmojiSuggestionItem }\n\nfunction EmojiImage({ emoji, set, size = '1.2em' }: { emoji: ResolvedEmoji; set: string; size?: string }) {\n if (set === 'native') {\n return <span style={{ fontSize: size }}>{emoji.native}</span>\n }\n return (\n <span\n role=\"img\"\n aria-label={emoji.native}\n className=\"inline-block\"\n style={{\n width: size,\n height: size,\n backgroundImage: `url(${SPRITESHEET_URL(set)})`,\n backgroundSize: `${100 * SHEET_COLS}% ${100 * SHEET_ROWS}%`,\n backgroundPosition: `${(100 / (SHEET_COLS - 1)) * emoji.x}% ${(100 / (SHEET_ROWS - 1)) * emoji.y}%`,\n }}\n />\n )\n}\n\ninterface EmojiListRef {\n onKeyDown: (props: SuggestionKeyDownProps) => boolean\n}\n\ninterface EmojiListProps {\n items: ResolvedEmoji[]\n set: string\n command: (item: ResolvedEmoji) => void\n}\n\nconst EmojiList = React.forwardRef<EmojiListRef, EmojiListProps>(\n ({ items, set, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n\n React.useEffect(() => setSelectedIndex(0), [items])\n\n React.useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: SuggestionKeyDownProps) => {\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length)\n return true\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length)\n return true\n }\n if (event.key === 'Enter') {\n if (items[selectedIndex]) command(items[selectedIndex])\n return true\n }\n return false\n },\n }))\n\n if (!items.length) return null\n\n return (\n <div role=\"listbox\" aria-label=\"Emoji suggestions\" className=\"z-popover max-h-[200px] overflow-x-hidden overflow-y-auto rounded-control bg-surface-overlay shadow-raised-hover\">\n {items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n className={cn(\n 'flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm',\n index === selectedIndex ? 'bg-surface-raised text-surface-fg' : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n <EmojiImage emoji={item} set={set} size=\"1.25em\" />\n <span className=\"truncate\">:{item.id}:</span>\n </button>\n ))}\n </div>\n )\n },\n)\nEmojiList.displayName = 'EmojiList'\n\nfunction createEmojiSuggestionRenderer(set: string) {\n return () => {\n let root: Root | null = null\n let container: HTMLDivElement | null = null\n let componentRef: EmojiListRef | null = null\n\n return {\n onStart: (props: SuggestionProps<ResolvedEmoji>) => {\n container = document.createElement('div')\n container.style.position = 'absolute'\n container.style.zIndex = '1400'\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n document.body.appendChild(container)\n root = createRoot(container)\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onUpdate: (props: SuggestionProps<ResolvedEmoji>) => {\n if (!root || !container) return\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (props.event.key === 'Escape') {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n return true\n }\n return componentRef?.onKeyDown(props) ?? false\n },\n\n onExit: () => {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n },\n }\n }\n}\n\n/** Factory: call with the emoji set to get a configured extension. */\nexport function createEmojiSuggestion(set = 'native') {\n return Extension.create({\n name: 'emojiSuggestion',\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n pluginKey: new PluginKey('emojiSuggestion'),\n editor: this.editor,\n char: ':',\n items: async ({ query }) => {\n const data = await loadEmojiData(set)\n return searchEmoji(data, query, 8)\n },\n command: ({ editor, range, props: item }) => {\n const emoji = item as ResolvedEmoji\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({\n type: 'emojiNode',\n attrs: { id: emoji.id, native: emoji.native, set, x: emoji.x, y: emoji.y },\n })\n .run()\n },\n render: createEmojiSuggestionRenderer(set),\n }),\n ]\n },\n })\n}\n"],"mappings":"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"}