@pie-players/pie-tool-dictionary 0.3.67

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 ADDED
@@ -0,0 +1,102 @@
1
+ # @pie-players/pie-tool-dictionary
2
+
3
+ Dictionary panel for the PIE assessment player. Registers
4
+ `<pie-tool-dictionary>`.
5
+
6
+ ## Lookup is host-supplied
7
+
8
+ PIE ships no dictionary endpoint. The corpus behind a dictionary is licensed per
9
+ programme, so a default here would bake one deployment into the package.
10
+
11
+ Two ways to supply one, in precedence order:
12
+
13
+ ```html
14
+ <!-- Built-in POST shaping -->
15
+ <pie-tool-dictionary endpoint="/api/dictionary" language="en"></pie-tool-dictionary>
16
+ ```
17
+
18
+ ```js
19
+ // Your own client, preferred when you already have one
20
+ element.lookup = async ({ keyword, language, max }, signal) => ({
21
+ status: "ok",
22
+ items: [{ word: keyword, senses: [{ definition: "…" }] }],
23
+ });
24
+ ```
25
+
26
+ With neither, the panel says no service is configured rather than offering a field
27
+ that silently fails.
28
+
29
+ ### Request
30
+
31
+ `POST` with `{ keyword, language?, max? }`. `keyword` is normalised before it is
32
+ sent: whitespace collapsed, surrounding punctuation stripped, internal hyphens and
33
+ apostrophes kept. A selection longer than four words is refused without a request.
34
+
35
+ ### Response
36
+
37
+ ```json
38
+ {
39
+ "entries": [
40
+ {
41
+ "word": "reason",
42
+ "pronunciation": "ˈriːzən",
43
+ "senses": [
44
+ { "partOfSpeech": "noun", "definition": "A cause or explanation.", "example": "…" }
45
+ ]
46
+ }
47
+ ]
48
+ }
49
+ ```
50
+
51
+ Unknown extra fields are ignored, so the payload can be extended without a change
52
+ here. An entry carrying no usable definition is dropped: rendering a bare headword
53
+ tells a learner the word exists and nothing they asked for. Zero entries is
54
+ reported as "no entry", distinct from a service failure — a learner must not be
55
+ told their word is not real when the network is down.
56
+
57
+ The endpoint is called `same-origin`, so a route already behind the assessment's own
58
+ session answers with no further configuration — naming the endpoint is the whole
59
+ setup. A host authorising some other way passes a `headers` function, read per request
60
+ so a short-lived token is fetched fresh rather than captured at mount, and one that
61
+ wants no ambient credentials at all passes `credentials: "omit"`. Both are properties
62
+ rather than attributes, and both are optional.
63
+
64
+ ## Two entry points, deliberately
65
+
66
+ The `term` property is set by whatever selection affordance the host offers. Under
67
+ `<pie-assessment-toolkit>` that is the annotation strip: selecting a word offers a
68
+ lookup, and activating it opens this panel with the word already searched, through
69
+ the coordinator's `requestTool`. The
70
+ field is how a learner looks up a word without one, and it is the reason the tool
71
+ is keyboard accessible rather than a convenience: a sighted keyboard-only learner
72
+ cannot originate a text selection in non-editable content, because Chromium does
73
+ not extend one with Shift+Arrow there unless caret browsing is on — an OS-level
74
+ toggle absent on mobile. A selection-only dictionary is unreachable for them.
75
+
76
+ The two entry points have to coexist within one open panel, which is what
77
+ `termRequestId` is for. A requested term is reapplied on every sync, so the term alone
78
+ cannot distinguish a re-render from a fresh ask: without an id, reopening the panel
79
+ re-searches the term that opened it and discards whatever the learner typed since. A
80
+ host setting `term` directly can leave the id unset and gets term-identity behaviour,
81
+ which is enough to stop a re-render re-issuing.
82
+
83
+ ## Properties
84
+
85
+ | Name | Attribute | Type | Notes |
86
+ | ---------- | ---------- | ----------------- | -------------------------------------------- |
87
+ | `visible` | `visible` | boolean | Owned by the toolbar shell. |
88
+ | `toolId` | `tool-id` | string | Scoped tool instance id. |
89
+ | `term` | `term` | string | Pre-fills and searches when the panel is open. |
90
+ | `termRequestId` | — | string \| number | Identity of the current `term`; optional. |
91
+ | `endpoint` | `endpoint` | string | Enables the built-in POST lookup. |
92
+ | `language` | `language` | string | BCP-47 tag sent with the request. |
93
+ | `lookup` | — | function | Host resolver; takes precedence over `endpoint`. |
94
+ | `headers` | — | function | Extra request headers for `endpoint`, read per request. |
95
+ | `credentials` | — | string | Overrides the `same-origin` default for `endpoint`. |
96
+
97
+ A `lookup` resolves to `{ status: "ok", items }`, `{ status: "empty" }`, or
98
+ `{ status: "error", reason }` — the same three states the shared term-lookup contract
99
+ in `@pie-players/pie-players-shared/tools/term-lookup` defines for both dictionaries.
100
+
101
+ The panel renders its body only. Floating chrome — title bar, drag, resize, close —
102
+ belongs to the toolbar shell.
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,33 @@
1
+ import { TermLookup, TermLookupRequest, TermLookupResult } from '@pie-players/pie-players-shared/tools/term-lookup';
2
+ /** What a host's dictionary service is asked for. */
3
+ export type DictionaryLookupRequest = TermLookupRequest;
4
+ export interface DictionarySense {
5
+ partOfSpeech?: string;
6
+ definition: string;
7
+ example?: string;
8
+ }
9
+ export interface DictionaryEntry {
10
+ word: string;
11
+ /** Respelling or IPA, whichever the host's corpus carries. */
12
+ pronunciation?: string;
13
+ senses: DictionarySense[];
14
+ }
15
+ export type DictionaryLookupResult = TermLookupResult<DictionaryEntry>;
16
+ export type DictionaryLookup = TermLookup<DictionaryEntry>;
17
+ /** Entries a single lookup may render before the tool stops asking for more. */
18
+ export declare const DEFAULT_MAX_ENTRIES = 6;
19
+ /** Read a host response into a result, ignoring unknown extra fields. */
20
+ export declare function readLookupResponse(payload: unknown): DictionaryLookupResult;
21
+ /**
22
+ * A lookup that POSTs to a host endpoint.
23
+ *
24
+ * The session cookie rides along by default, because a host is expected to put its
25
+ * dictionary route behind the same session boundary as the assessment; `credentials`
26
+ * and `headers` are there for a host that authorises some other way.
27
+ */
28
+ export declare function createEndpointLookup(args: {
29
+ endpoint: string;
30
+ headers?: () => Promise<Record<string, string>> | Record<string, string>;
31
+ credentials?: RequestCredentials;
32
+ fetchImpl?: typeof fetch;
33
+ }): DictionaryLookup;