pinyin-ime 0.3.0 → 0.5.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/README.md CHANGED
@@ -4,11 +4,9 @@
4
4
 
5
5
  **pinyin-ime** 是一套在浏览器内实现的 **拼音 → 汉字** 输入法能力:在无法使用系统输入法的场景(全屏游戏、内嵌 WebView、远程桌面、部分浏览器环境等),于 `<input>` / `<textarea>` 上用 **a–z** 输入拼音,通过 **候选框选词上屏**。
6
6
 
7
- - **React**:提供 `PinyinField`、`PinyinInput`、`PinyinTextarea` `usePinyinIME` API。
8
- - **任意框架 / 无框架**:可通过子路径 **`pinyin-ime/element`** 使用 Lit 实现的 **`<pinyin-ime-editor>`** 自定义元素(`lit` 已打入该入口,无需单独安装)。
9
- - **Vue**:无官方 Vue 组件;推荐在模板中直接使用 `<pinyin-ime-editor>`,并在构建工具中将该标签识别为自定义元素(示例见本仓库 [`site/`](site/))。
7
+ 统一入口为 Lit 实现的 **`<pinyin-ime-editor>`** 自定义元素(`lit` 已打入产物,无需单独安装),可在 **React**、**Vue**、**任意框架或纯 HTML/JS** 中使用。
10
8
 
11
- 在线演示:将 [`site/vite.config.ts`](site/vite.config.ts) 的 `base` 与仓库的 GitHub Pages 路径对齐后部署 `site/dist`。演示站通过 [`site/package.json`](site/package.json) 从 **npm** 安装 `pinyin-ime`(`npm:` 协议,避免与仓库根包 workspace 链接),发新版库后如需固定演示版本可收紧该依赖范围。多页 HTML 入口在 `site` 根目录与各子目录([`site/index.html`](site/index.html)、[`site/react/`](site/react/)、[`site/vue/`](site/vue/)、[`site/web_component/`](site/web_component/)),与 `base: '/pinyin-ime/'` 一致;本地开发请打开 **`http://localhost:5173/pinyin-ime/`**(勿省略前缀)。
9
+ 在线演示:将 [`site/vite.config.ts`](site/vite.config.ts) 的 `base` 与仓库的 GitHub Pages 路径对齐后部署 `site/dist`。演示站通过 [`site/package.json`](site/package.json) 从 **npm** 安装 `pinyin-ime`(`npm:` 协议,避免与仓库根包 workspace 链接),发新版库后如需固定演示版本可收紧该依赖范围。多页 HTML 入口在 `site` 根目录与各子目录([`site/index.html`](site/index.html)、[`site/react/`](site/react/)、[`site/vue/`](site/vue/)、[`site/web_component/`](site/web_component/));本地开发请打开 **`http://localhost:5173/pinyinime/`**(与 `base` 一致,勿省略前缀)。
12
10
 
13
11
  ---
14
12
 
@@ -19,209 +17,220 @@ pnpm add pinyin-ime
19
17
  # 或 npm install pinyin-ime / yarn add pinyin-ime
20
18
  ```
21
19
 
22
- **对等依赖**:主入口 `pinyin-ime` 声明 `react`、`react-dom`(建议 18+)。若项目 **仅** 使用 `pinyin-ime/element` 与样式子路径、不装 React,安装器可能对 peer 给出警告,可按包管理器文档选择忽略或配置(例如 pnpm 的 `peerDependencyRules`)。
23
-
24
20
  **构建产物**:发布包以 `dist/` 下的 **编译后 ESM + `.d.ts`** 为主;在仓库里开发库时请执行 `pnpm run build` 保证 `dist` 存在。**演示站** `site/` 默认从 **npm** 解析 `pinyin-ime`,本地改库后若要演示站跟本地 `dist` 一致,需改回 workspace 链接或发版后再装新版本。
25
21
 
26
- ### 1.1 React
27
-
28
- 入口安装样式(与组件配套使用):
22
+ ### 1.1 引入与注册
29
23
 
30
24
  ```ts
25
+ import "pinyin-ime";
31
26
  import "pinyin-ime/pinyin-ime.css";
32
27
  ```
33
28
 
34
- **`PinyinInput` / `PinyinTextarea`**(单行 / 多行,API 与原生控件接近):
29
+ ### 1.2 React
35
30
 
36
- ```tsx
37
- import { useState } from "react";
38
- import { PinyinInput, PinyinTextarea } from "pinyin-ime";
39
- import "pinyin-ime/pinyin-ime.css";
40
-
41
- export function Demo() {
42
- const [title, setTitle] = useState("");
43
- const [body, setBody] = useState("");
44
- return (
45
- <>
46
- <PinyinInput value={title} onChange={setTitle} placeholder="标题" />
47
- <PinyinTextarea value={body} onChange={setBody} rows={6} />
48
- </>
49
- );
50
- }
51
- ```
52
-
53
- **`PinyinField`**(推荐):用 `variant="input" | "textarea"` 切换宿主,其余原生属性放进 `inputProps` / `textareaProps`,避免与 IME 内部绑定的属性冲突。
31
+ 在 React 中使用 `<pinyin-ime-editor>`,需封装受控逻辑(监听 `change`、同步 `value`):
54
32
 
55
33
  ```tsx
56
- import { PinyinField } from "pinyin-ime";
34
+ import { useRef, useEffect, useLayoutEffect } from "react";
35
+ import "pinyin-ime";
57
36
  import "pinyin-ime/pinyin-ime.css";
58
37
 
59
- <PinyinField
60
- variant="textarea"
61
- value={body}
62
- onChange={setBody}
63
- textareaProps={{ id: "body", placeholder: "正文", rows: 6 }}
64
- />;
38
+ function PinyinEditor({ value, onChange, editorType = "input" }) {
39
+ const ref = useRef(null);
40
+ useEffect(() => {
41
+ const el = ref.current;
42
+ if (!el) return;
43
+ const handler = (e) => onChange(e.detail.value);
44
+ el.addEventListener("change", handler);
45
+ return () => el.removeEventListener("change", handler);
46
+ }, [onChange]);
47
+ useLayoutEffect(() => {
48
+ const el = ref.current;
49
+ if (el && el.value !== value) el.value = value;
50
+ }, [value]);
51
+ return <pinyin-ime-editor ref={ref} editor-type={editorType} />;
52
+ }
65
53
  ```
66
54
 
67
- ### 1.2 Vue 3
55
+ 完整示例见 **[`site/src/react/react-page.tsx`](site/src/react/react-page.tsx)**。
68
56
 
69
- 本包不提供 `.vue` 单文件组件。做法是:
57
+ ### 1.3 Vue 3
70
58
 
71
59
  1. 安装依赖并 **build 本库**(workspace 或从 npm 安装已发布版本)。
72
- 2. 在入口引入 **`import "pinyin-ime/element"`** 与 **`import "pinyin-ime/pinyin-ime.css"`**。
73
- 3. 在模板里写 **`<pinyin-ime-editor>`**,监听 **`pinyin-ime-change`**,`event.detail.value` 为字符串。
60
+ 2. 在入口引入 **`import "pinyin-ime"`** 与 **`import "pinyin-ime/pinyin-ime.css"`**。
61
+ 3. 在模板里写 **`<pinyin-ime-editor>`**,监听 **`change`**,`event.detail.value` 为字符串。
74
62
  4. 使用 **Vite** 时,在 `@vitejs/plugin-vue` 中配置 **`compilerOptions.isCustomElement`**,例如 `(tag) => tag === "pinyin-ime-editor"`,避免 Vue 把未知标签当普通组件解析。
75
63
 
76
- 完整可运行示例见 **[`site/src/vue/VuePage.vue`](site/src/vue/VuePage.vue)** 与 **[`site/vite.config.ts`](site/vite.config.ts)**。
77
-
78
64
  ```vue
79
65
  <script setup lang="ts">
80
66
  import { ref } from "vue";
81
- import "pinyin-ime/element";
67
+ import "pinyin-ime";
82
68
  import "pinyin-ime/pinyin-ime.css";
83
69
 
84
70
  const text = ref("");
85
- function onPinyinChange(e: Event) {
71
+ function onChange(e: Event) {
86
72
  text.value = (e as CustomEvent<{ value: string }>).detail.value;
87
73
  }
88
74
  </script>
89
75
 
90
76
  <template>
91
- <pinyin-ime-editor :value="text" @pinyin-ime-change="onPinyinChange" />
77
+ <pinyin-ime-editor :value="text" @change="onChange" />
92
78
  </template>
93
79
  ```
94
80
 
95
- ### 1.3 原生 Web Component
81
+ 完整示例见 **[`site/src/vue/VuePage.vue`](site/src/vue/VuePage.vue)**。
96
82
 
97
- 在支持 **ESM** 的页面或应用中:
83
+ ### 1.4 原生 Web Component
98
84
 
99
85
  ```html
100
86
  <script type="module">
101
- import "pinyin-ime/element";
87
+ import "pinyin-ime";
102
88
  import "pinyin-ime/pinyin-ime.css";
103
89
  </script>
104
90
  ```
105
91
 
106
- 注册完成后可用 HTML / DOM API 使用 **`<pinyin-ime-editor>`**:
107
-
108
92
  ```js
109
93
  const el = document.createElement("pinyin-ime-editor");
110
- el.addEventListener("pinyin-ime-change", (e) => {
94
+ el.addEventListener("change", (e) => {
111
95
  console.log(e.detail.value);
112
96
  });
113
97
  document.body.append(el);
114
98
  ```
115
99
 
116
- 独立页面演示见 **[`site/src/react/react-page.tsx`](site/src/react/react-page.tsx)**(React 内挂载自定义元素)与 **[`site/src/wc/wc-main.ts`](site/src/wc/wc-main.ts)**(纯 DOM)。
100
+ 示例见 **[`site/src/wc/wc-main.ts`](site/src/wc/wc-main.ts)**。
117
101
 
118
102
  ---
119
103
 
120
- ## 2. Props / 属性说明
104
+ ## 2. `<pinyin-ime-editor>` 属性与事件
105
+
106
+ ### 2.1 自有属性
121
107
 
122
- ### 2.1 React:`PinyinField`
108
+ | 属性(HTML) | 类型 | 默认值 | 说明 |
109
+ |--------------|------|--------|------|
110
+ | `value` | `string` | `""` | 受控文本(property) |
111
+ | `editor-type` | `"input" \| "textarea"` | `"input"` | 单行或多行宿主 |
112
+ | `page-size` | `number` | `5` | 每页候选数(1–9) |
113
+ | `enabled` | `boolean` | `true` | 是否启用 IME 逻辑 |
123
114
 
124
- `PinyinInput` / `PinyinTextarea` 的 IME 相关 props 与下表一致;差别在于:二者把 **原生 `input` / `textarea` 属性** 直接铺在根上(仍不含被 IME 占用的键),而 `PinyinField` 通过 **`inputProps` / `textareaProps`** 透传。
115
+ ### 2.2 getDictionary(仅 property)
125
116
 
126
- 以下 **不可** 出现在 `inputProps` / `textareaProps` 中:`value`、`onChange`、`onBeforeInput`、`onKeyDownCapture`、`ref`(由组件接管)。类型见 **`PinyinFieldNativeInputProps`** / **`PinyinFieldNativeTextareaProps`**。
117
+ 通过 JavaScript 设置 **`getDictionary`** 来自定义词典加载(无法通过 HTML 属性设置):
127
118
 
128
- | 属性 | 类型 | 默认值 | 说明 |
129
- |------|------|--------|------|
130
- | `value` | `string` | — | 受控文本 |
131
- | `onChange` | `(value: string) => void` | — | 文本变化 |
132
- | `onKeyDown` | `KeyboardEventHandler<HTMLInputElement \| HTMLTextAreaElement>` | — | 未被 IME 拦截时的键盘回调 |
133
- | `variant` | `"input" \| "textarea"` | `"input"` | 宿主类型(仅 `PinyinField`) |
134
- | `enabled` | `boolean` | `true` | `false` 时关闭 IME,行为等同普通受控输入 |
135
- | `pageSize` | `number` | `3` | 每页候选数,范围 1–9(对应数字键 1–n) |
136
- | `classNames` | `Partial<PinyinPopupClassNames>` | — | 候选弹窗各区域 `className` |
137
- | `popupPortalContainer` | `HTMLElement \| null` | `document.body` | 候选层 Portal 挂载节点 |
138
- | `className` | `string` | — | 外层包裹元素 `className` |
139
- | `inputProps` | `PinyinFieldNativeInputProps` | — | 仅 `variant="input"` 时合并到 `<input>` |
140
- | `textareaProps` | `PinyinFieldNativeTextareaProps` | — | 仅 `variant="textarea"` 时合并到 `<textarea>` |
141
- | `getEngine` | `() => PinyinEngine \| null` | — | **词典优先级最高**:自定义引擎实例 |
142
- | `dictionary` | `GooglePinyinDict` | — | 内存中的整本词典对象 |
143
- | `dictionaryUrl` | `string` | — | 远程词典 JSON 的 URL(需 CORS);加载完成前候选为空 |
144
- | `dictionaryFetchInit` | `RequestInit` | — | 传给 `fetch(dictionaryUrl, init)` |
145
- | `onDictionaryLoaded` | `() => void` | — | 远程词典加载成功并创建引擎后调用 |
146
- | `onDictionaryLoadError` | `(error: unknown) => void` | — | 远程加载或解析失败时调用 |
119
+ ```ts
120
+ type GetDictionaryFn = () => Promise<GooglePinyinDict> | GooglePinyinDict;
121
+ ```
147
122
 
148
- ### 2.2 `usePinyinIME` 的选项与返回值(进阶)
123
+ - 组件初始化(`connectedCallback`)时调用
124
+ - 返回词典对象或 Promise;resolve 前候选框显示「加载中…」
125
+ - 未设置时动态 import 包内词典(`pinyin-ime/dict`),按需加载
149
126
 
150
- 除组件外可直接使用 **`usePinyinIME(value, onChange, onKeyDown, options)`**。其中 **`options`** 的字段与上表中的 `enabled`、`pageSize`、`getEngine`、`dictionary`、`dictionaryUrl`、`dictionaryFetchInit`、`onDictionaryLoaded`、`onDictionaryLoadError` 相同。
127
+ ```js
128
+ const el = document.querySelector("pinyin-ime-editor");
129
+ el.getDictionary = () =>
130
+ fetch("https://example.com/dict.json").then((r) => r.json());
131
+ ```
151
132
 
152
- 返回值中常用字段:`elementRef`、`pinyinInput`、`candidates`、`displayCandidates`、`page`、`pageSize`、`position`、`showPopup`、`selectCandidate`、`setPage`、`handleKeyDown`、`handleBeforeInput`;若使用 `dictionaryUrl`,另有 **`dictionaryLoadState`**(`"idle" \| "loading" \| "ready" \| "error"`)、**`dictionaryError`**。
133
+ ### 2.3 属性透传
153
134
 
154
- ### 2.3 自定义元素:`<pinyin-ime-editor>`
135
+ `value`、`editor-type`、`page-size`、`enabled`、`class` 外,其它 attribute 会透传到内部的 `<input>` 或 `<textarea>`,便于进一步定制(如 `placeholder`、`disabled`、`rows` 等):
155
136
 
156
- 属性名为 **DOM 中的写法**(Lit 会将 camelCase 映射为 attribute)。
137
+ ```html
138
+ <pinyin-ime-editor placeholder="请输入" rows="6" editor-type="textarea" />
139
+ ```
157
140
 
158
- | 属性(HTML) | 类型 | 默认值 | 说明 |
159
- |--------------|------|--------|------|
160
- | `value` | `string` | `""` | 受控文本(property) |
161
- | `variant` | `"input" \| "textarea"` | `"input"` | 单行或多行宿主 |
162
- | `dictionary-url` | `string` | `""` | 非空时从该 URL 拉取词典 JSON |
163
- | `enabled` | `boolean` | `true` | 是否启用 IME 逻辑 |
164
- | `page-size` | `number` | `3` | 每页候选数(1–9) |
141
+ ### 2.4 事件
165
142
 
166
143
  | 事件 | `detail` | 说明 |
167
144
  |------|-----------|------|
168
- | `pinyin-ime-change` | `{ value: string }` | 文本变化(选词、上屏、普通输入等导致 `value` 更新时) |
145
+ | `change` | `{ value: string }` | 文本变化(选词、上屏、普通输入等导致 `value` 更新时) |
169
146
 
170
147
  ---
171
148
 
172
- ## 3. 样式
149
+ ## 3. 样式定制
173
150
 
174
- ### 3.1 默认样式怎么用
151
+ 组件使用 Shadow DOM,样式在内部。支持两种定制方式:
175
152
 
176
- 在应用入口(或懒加载 IME chunk 入口)增加:
153
+ ### 3.1 CSS 变量
177
154
 
178
- ```ts
179
- import "pinyin-ime/pinyin-ime.css";
155
+ 在宿主或父级设置变量覆盖默认值:
156
+
157
+ ```css
158
+ pinyin-ime-editor {
159
+ --pinyin-ime-border-color: #e5e7eb;
160
+ --pinyin-ime-focus-border: #6366f1;
161
+ --pinyin-ime-popup-bg: #fff;
162
+ --pinyin-ime-cursor-color: #4f46e5;
163
+ --pinyin-ime-hover-bg: #f3f4f6;
164
+ --pinyin-ime-text-color: #111827;
165
+ --pinyin-ime-muted-color: #6b7280;
166
+ --pinyin-ime-popup-border: #e5e7eb;
167
+ --pinyin-ime-focus-shadow: rgba(99, 102, 241, 0.25);
168
+ }
180
169
  ```
181
170
 
182
- 样式使用 **`pinyin-ime-*`** 类名(输入框、候选条、分页区等)。**不引入该文件** 时,组件仍可运行,但默认外观会缺失,需自行用下文方式补全。
171
+ ### 3.2 Part 选择器
183
172
 
184
- ### 3.2 怎么自定义
173
+ 内部元素暴露 `part`,可通过 `::part()` 选择器定制:
185
174
 
186
- 1. **React 宿主**:根级 **`className`**(或 `inputProps.className` / `textareaProps.className`)覆盖输入框;**`classNames`** 覆盖弹窗分区,键名见类型 **`PinyinPopupClassNames`**(`popup`、`pinyinBar`、`cursor`、`candidateRow` 等)。可与 **`defaultPinyinPopupClassNames`** 合并后再覆盖局部。
187
- 2. **自建弹窗**:使用 **`usePinyinIME`** + **`PinyinCandidatePopup`**(或完全自建 UI),只消费 hook 返回的状态与事件。
188
- 3. **Web Component**:样式在 **Shadow DOM** 内联,默认已包含与 `pinyin-ime.css` 等价的一套规则;宿主页面再引 `pinyin-ime.css` 主要影响 **document 内** 其它元素,一般仍需依赖内置样式或通过 **继承 / 未来主题 API** 扩展(当前版本以内联为主)。
175
+ ```css
176
+ pinyin-ime-editor::part(popup) {
177
+ border-radius: 8px;
178
+ }
179
+ pinyin-ime-editor::part(candidate-row):hover {
180
+ background: #eef2ff;
181
+ }
182
+ ```
189
183
 
190
- 工具函数 **`joinClassNames`** 可用于拼接 `className` 字符串(无 Tailwind 依赖)。
184
+ 可用 part:`popup`、`pinyin-bar`、`cursor`、`candidate-list`、`candidate-row`、`candidate-index`、`candidate-text`、`empty`、`loading`、`footer`。
191
185
 
192
186
  ---
193
187
 
194
- ## 4. 字典与懒加载
188
+ ## 4. 字典
195
189
 
196
- ### 4.1 默认行为
190
+ ### 4.1 两种加载方式
197
191
 
198
- 未配置 `getEngine` / `dictionary` / `dictionaryUrl` 时,使用包内 **同步内嵌** 的默认词典(体积较大,安装包可达数 MB 量级)。
192
+ | 方式 | 条件 | 行为 | 第三方构建 |
193
+ |------|------|------|------------|
194
+ | **本地加载** | `getDictionary` 未设置 | 动态 `import("pinyin-ime/dict")` 按需加载包内词典 | 会生成字典 chunk,仅在使用本地时加载 |
195
+ | **远程加载** | `getDictionary` 已设置 | 调用用户方法获取词典 | 不加载字典 chunk,运行时由 getDictionary 提供 |
199
196
 
200
- ### 4.2 懒加载(远程 URL)
197
+ 只需 `import "pinyin-ime"`,无需额外 import;本地/远程由是否设置 `getDictionary` 决定。
201
198
 
202
- 设置 **`dictionaryUrl`**(React 组件或 `usePinyinIME` / 自定义元素的 **`dictionary-url`**)后:
199
+ ### 4.2 远程加载示例
203
200
 
204
- - 会在客户端 **`fetch(url)`** 拉取 JSON; body 须为与 **`GooglePinyinDict`** 同形的对象:`Record<string, Array<{ w: string; f: number }>>`。
205
- - **加载完成前** 引擎为空,**候选列表为空**(不会回退到内嵌大词典,除非你自己在 `getEngine` 里组合逻辑)。
206
- - 服务端需配置 **CORS**,生产环境建议 **版本化 URL** 与合理 **`Cache-Control`**。
207
- - 可选 **`dictionaryFetchInit`** 传入 `fetch` 的第二参数;**`onDictionaryLoaded` / `onDictionaryLoadError`** 做提示或埋点。
208
- - React 下可通过 **`dictionaryLoadState`**、**`dictionaryError`** 展示加载态与错误。
201
+ ```js
202
+ el.getDictionary = () =>
203
+ fetch("/path/to/dict.json").then((r) => r.json());
204
+ ```
209
205
 
210
- ### 4.3 其它方式
206
+ 词典须为 `GooglePinyinDict` 格式:`Record<string, Array<{ w: string; f: number }>>`。服务端需配置 **CORS**。
211
207
 
212
- - **`dictionary`**:已解析的对象,适合小表或与打包器拆分的 JSON 模块。
213
- - **`getEngine()`**:返回 **`createPinyinEngine(dict)`** 的实例,优先级最高,可实现缓存、多源合并等。
208
+ ### 4.3 子路径与 API
214
209
 
215
- ### 4.4 构建体积:`index.js` / `element.js` 与词典
210
+ | 子路径 | 说明 |
211
+ |--------|------|
212
+ | `pinyin-ime` | 主入口,注册 `<pinyin-ime-editor>` 并导出 API |
213
+ | `pinyin-ime/dict` | 导出 `dict`,供 element 本地加载时 `import("pinyin-ime/dict")` |
214
+ | `pinyin-ime/pinyin-ime.css` | 默认样式(Shadow DOM 内联为主,按需引入) |
215
+ | `pinyin-ime/google-pinyin-dict.json` | 词典 JSON,可用于 CDN/静态托管 |
216
216
 
217
- - **为何曾经各约 5MB**:`src/google_pinyin_dict.ts` 内嵌整本词典;若用 **两次独立的 tsup 构建**(先 `index.ts`、再 `element.ts`),esbuild 无法在两次运行之间复用模块,**同一份词典会被完整打进两个入口**,体积几乎翻倍。
218
- - **当前仓库做法**:`tsup.config.ts` 使用 **单次多入口**(`index` + `element`)并开启 **`splitting: true`(仅 ESM)**,共享依赖(含词典)落到 **`dist/chunk-*.js`**,`index.js` / `element.js` 只保留入口胶水代码。部署 npm 包或静态资源时,请 **一并发布所有 `dist/*.js`**,否则相对路径的 chunk 会 404。
219
- - **单独词典文件**:`pnpm run build` 会在 `dist/google-pinyin-dict.json` 再写一份 JSON(与内嵌数据一致),并通过子路径 **`pinyin-ime/google-pinyin-dict.json`** 暴露。业务里可设 `dictionaryUrl`(或自定义 `fetch`)指向该文件,便于 CDN 缓存或与内嵌默认引擎并存。
220
- - **若希望应用首包不含内嵌词典**:需要避免从主入口引用会 **静态拉取 `defaultPinyinEngine` / `dict`** 的 API(例如 `getCandidates`、`computeMatchedLength` 等),并改用 **`createPinyinEngine` + `loadGooglePinyinDictFromUrl`** 等自行装配;这属于进阶用法,当前包仍以「开箱即用内嵌词典」为主。
217
+ 可导入 **`createPinyinEngine`**、**`loadGooglePinyinDictFromUrl`** API 自行构建引擎。`getCandidates`、`computeMatchedLength` 使用已注册的默认引擎(需至少有一个 `<pinyin-ime-editor>` 已加载词典后才会生效)。
221
218
 
222
219
  ---
223
220
 
224
- ## 快捷键
221
+ ## 5. 导出 API
222
+
223
+ 主入口 `import "pinyin-ime"` 或 `import { ... } from "pinyin-ime"` 提供:
224
+
225
+ - **组件**:`PinyinIMEEditor`(注册 `<pinyin-ime-editor>`)
226
+ - **引擎**:`createPinyinEngine`、`getCandidates`、`computeMatchedLength`
227
+ - **工具**:`loadGooglePinyinDictFromUrl`、`assertGooglePinyinDictShape`、`DictionaryLoadError`
228
+ - **控制器**:`PinyinIMEController`、`IME_PAGE_SIZE`、`clampIMPageSize`
229
+ - **类型**:`GooglePinyinDict`、`GetDictionaryFn`、`PinyinIMEChangeDetail` 等
230
+
231
+ ---
232
+
233
+ ## 6. 快捷键
225
234
 
226
235
  - **a–z**:写入拼音缓冲(`'` 音节分隔)
227
236
  - **空格**:选第一候选;无候选则上屏当前拼音串
@@ -232,26 +241,6 @@ import "pinyin-ime/pinyin-ime.css";
232
241
 
233
242
  ---
234
243
 
235
- ## 本地开发与演示站
236
-
237
- ```bash
238
- pnpm install
239
- pnpm run test
240
- pnpm run build # 生成根目录 dist/(npm 发布内容)
241
- pnpm run site:dev # 启动 site(依赖 registry 中的 pinyin-ime,见 site/package.json)
242
- pnpm run site:build # 构建 site/dist(同上)
243
- ```
244
-
245
- 发布前可使用 `pnpm pack` / `npm pack --dry-run` 检查打包包容。
246
-
247
- ---
248
-
249
- ## 第三方数据与合规
250
-
251
- 拼音词表衍生自 [web-pinyin-ime](https://github.com/dongyuwei/web-pinyin-ime) 等开源数据;使用与再分发前请自行评估许可与合规要求。
252
-
253
- ---
254
-
255
- ## SSR 与客户端
244
+ ## 7. 字典数据
256
245
 
257
- IME 使用 Portal、`window` 监听与选区 API,**仅适用于客户端**。在 Next.js 等环境中请对含 IME 的界面使用 **`dynamic(..., { ssr: false })`** 或等价方式。
246
+ 拼音词表衍生自 [web-pinyin-ime](https://github.com/dongyuwei/web-pinyin-ime)
@@ -0,0 +1,15 @@
1
+ /**
2
+ * One candidate word or phrase with an optional corpus frequency weight.
3
+ */
4
+ type DictEntry = {
5
+ w: string;
6
+ f: number;
7
+ };
8
+ /**
9
+ * Map from lowercase pinyin key to ranked candidates (larger corpora use long keys).
10
+ */
11
+ type GooglePinyinDict = Record<string, DictEntry[]>;
12
+ /** 内嵌 Google 拼音风格词典(体积大;按需改用 `dictionaryUrl` / `createPinyinEngine`) */
13
+ declare const dict: GooglePinyinDict;
14
+
15
+ export { type DictEntry as D, type GooglePinyinDict as G, dict as d };
package/dist/dict.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { d as dict } from './dict-B47RwQqm.js';