@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.
- package/AGENTS.md +36 -12
- package/BREAKING.json +46 -0
- package/MIGRATION.md +35 -0
- package/dist/_chunks/emoji-suggestion.js +124 -0
- package/dist/_chunks/emoji-suggestion.js.map +1 -0
- package/dist/_chunks/emoji.js +1115 -0
- package/dist/_chunks/emoji.js.map +1 -0
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/composed/emoji-picker.d.ts +19 -9
- package/dist/composed/emoji-picker.d.ts.map +1 -1
- package/dist/composed/emoji-picker.js +87 -68
- package/dist/composed/emoji-picker.js.map +1 -1
- package/dist/composed/extensions/emoji-data.d.ts +1 -14
- package/dist/composed/extensions/emoji-data.d.ts.map +1 -1
- package/dist/composed/extensions/emoji-node.d.ts +0 -3
- package/dist/composed/extensions/emoji-node.d.ts.map +1 -1
- package/dist/composed/extensions/emoji-node.js +9 -34
- package/dist/composed/extensions/emoji-node.js.map +1 -1
- package/dist/composed/extensions/emoji-suggestion.d.ts +2 -2
- package/dist/composed/extensions/emoji-suggestion.d.ts.map +1 -1
- package/dist/composed/extensions/emoji-suggestion.js +2 -116
- package/dist/composed/rich-chat-input.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +554 -575
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +167 -190
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/docs/components/composed/emoji-picker.md +19 -17
- package/docs/components/composed/rich-text-editor.md +1 -1
- package/docs/components/ui/table-row-link.md +1 -1
- package/docs/recipes/index.md +1 -1
- package/docs/recipes/install-astro.md +15 -12
- package/docs/recipes/install-next-app-router.md +20 -12
- package/docs/recipes/install-next-pages.md +3 -1
- package/docs/recipes/install-remix.md +16 -13
- package/docs/recipes/install-tanstack-start.md +19 -12
- package/docs/recipes/install-vite.md +18 -15
- package/docs/recipes/troubleshoot.md +7 -8
- package/llms.txt +2 -2
- package/mcp-manifest.json +29 -66
- package/package.json +6 -9
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +2 -2
- package/skill/references/setup-astro.md +15 -12
- package/skill/references/setup-next-app-router.md +20 -12
- package/skill/references/setup-next-pages.md +3 -1
- package/skill/references/setup-remix.md +16 -13
- package/skill/references/setup-tanstack-start.md +19 -12
- package/skill/references/setup-vite.md +18 -15
- package/skill/references/troubleshoot.md +7 -8
- package/dist/_chunks/emoji-data.js +0 -45
- package/dist/_chunks/emoji-data.js.map +0 -1
- 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**
|
|
48
|
-
|
|
49
|
-
| When you import…
|
|
50
|
-
|
|
51
|
-
| `@devalok/shilp-sutra/
|
|
52
|
-
| `@devalok/shilp-sutra/
|
|
53
|
-
| `@devalok/shilp-sutra/composed/
|
|
54
|
-
| `@devalok/shilp-sutra/composed/
|
|
55
|
-
| `@devalok/shilp-sutra/ui/
|
|
56
|
-
| `@devalok/shilp-sutra/
|
|
57
|
-
| `@devalok/shilp-sutra/
|
|
58
|
-
|
|
|
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
|
|
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' / '
|
|
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`
|
|
109
|
-
| `…/
|
|
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-
|
|
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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"}
|