@pie-players/pie-tool-sign-language 0.3.50
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,83 @@
|
|
|
1
|
+
# @pie-players/pie-tool-sign-language
|
|
2
|
+
|
|
3
|
+
The sign-language accommodation for PIE assessment players: a signed translation
|
|
4
|
+
of an item, docked beside its content.
|
|
5
|
+
|
|
6
|
+
This package is also the worked example of a capability contributed entirely from
|
|
7
|
+
outside the player. It is authored against
|
|
8
|
+
`@pie-players/pie-assessment-toolkit/tools/internal` — the same entry point the
|
|
9
|
+
packaged registrations use — and `@pie-players/pie-section-player` reaches it only
|
|
10
|
+
through `ToolRegistry.getToolsBySurface("content-media")`. No package in the player
|
|
11
|
+
names signing, the `signLanguage` support id, the `sign-language` catalog type or
|
|
12
|
+
this package.
|
|
13
|
+
|
|
14
|
+
## Opting in
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { signLanguageRegistration } from "@pie-players/pie-tool-sign-language";
|
|
18
|
+
|
|
19
|
+
registry.register(signLanguageRegistration);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Importing the package registers the `pie-tool-sign-language` element, so there is
|
|
23
|
+
nothing else to wire and no module-loader entry to add.
|
|
24
|
+
|
|
25
|
+
Signing is deliberately absent from `createPackagedToolRegistry` and
|
|
26
|
+
`DEFAULT_TOOL_MODULE_LOADERS`. It is an accommodation with an authored-content
|
|
27
|
+
dependency: a default that granted it would hand the accommodation to every
|
|
28
|
+
learner whose item happened to carry a card.
|
|
29
|
+
|
|
30
|
+
## Availability
|
|
31
|
+
|
|
32
|
+
Two independent halves, both required, neither implying the other.
|
|
33
|
+
|
|
34
|
+
**Eligibility** — policy granted `signLanguage`. Signing is an accommodation, so
|
|
35
|
+
silence means no. The host asks `decideFeaturePolicy` and never consults tool
|
|
36
|
+
placement: `activation: "region"` means there is no button to press, so a
|
|
37
|
+
`tools.placement` entry naming this capability is reported as unplaceable rather
|
|
38
|
+
than silently doing nothing.
|
|
39
|
+
|
|
40
|
+
**Content** — the item carries a matching `sign-language` catalog card. QTI
|
|
41
|
+
approximates AfA's DRD in-band: the presence of the card *is* the resource
|
|
42
|
+
declaration. This half is `requiresAuthoredContent.resolve`, and it is why a
|
|
43
|
+
learner with the accommodation still sees nothing on the vast majority of items.
|
|
44
|
+
|
|
45
|
+
A signed alternate reaches an item one way only: as a catalog card, authored or
|
|
46
|
+
written by an importer. There is no path that lifts a signing video out of item
|
|
47
|
+
markup at render time — one was implemented and removed, because it had no
|
|
48
|
+
producer and failed in the wrong direction, leaving the video in visible content
|
|
49
|
+
for every learner when the markup could not be parsed.
|
|
50
|
+
|
|
51
|
+
## No cross-sign-language substitution
|
|
52
|
+
|
|
53
|
+
ASL, BSL and LSF are not interchangeable. The catalog resolver's last fallback
|
|
54
|
+
rung matches any card of the requested type regardless of language, which helps
|
|
55
|
+
for spoken audio and harms here: handing an ASL learner a BSL recording is worse
|
|
56
|
+
than handing them nothing. `resolveSignLanguageAlternate` therefore accepts a
|
|
57
|
+
card reached by that rung only when its language matches, or when the card
|
|
58
|
+
asserts no language at all.
|
|
59
|
+
|
|
60
|
+
## The element
|
|
61
|
+
|
|
62
|
+
`<pie-tool-sign-language>` — open shadow root, mounted by the registration's
|
|
63
|
+
`renderSurface`, never authored directly. Props are `media` (a resolved
|
|
64
|
+
alternate) and `ttsService`; signing playback and read-aloud pause each other, and
|
|
65
|
+
the action the learner just took wins.
|
|
66
|
+
|
|
67
|
+
Sizing is driven by the recording's own frame shape, because signing needs height
|
|
68
|
+
for hands and face. Host overrides:
|
|
69
|
+
|
|
70
|
+
| Custom property | Default |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `--pie-section-player-item-media-aspect-ratio` | `3 / 4` |
|
|
73
|
+
| `--pie-section-player-item-media-min-height` | `220px` |
|
|
74
|
+
| `--pie-section-player-item-media-max-height` | `60vh` |
|
|
75
|
+
|
|
76
|
+
The region's share of the card width, the drag-to-resize handle and the stacking
|
|
77
|
+
breakpoint belong to the host: that is the card's layout, not the capability's.
|
|
78
|
+
|
|
79
|
+
## Related
|
|
80
|
+
|
|
81
|
+
- [`docs/prds/sign-language-asl-support.md`](../../docs/prds/sign-language-asl-support.md)
|
|
82
|
+
- [`docs/TOOL_REGISTRY.md`](../assessment-toolkit/docs/TOOL_REGISTRY.md) — host
|
|
83
|
+
surfaces and content dependencies
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { CONTENT_MEDIA_SURFACE, SIGN_LANGUAGE_ELEMENT_TAG, signLanguageRegistration, } from './src/sign-language-registration.js';
|
|
2
|
+
export type { SignLanguageMedia } from './src/sign-language-cards.js';
|
|
3
|
+
export { AMERICAN_SIGN_LANGUAGE, describeSignLanguage, isSignLanguageCard, matchesRequestedSignLanguage, resolveSignLanguageMedia, SIGN_LANGUAGE_CATALOG_TYPE, } from './src/sign-language-cards.js';
|
|
4
|
+
export type { ResolvedSignLanguageAlternate, SignLanguageCatalogRef, SignLanguageLookupArgs, } from './src/sign-language-content.js';
|
|
5
|
+
export { collectSignLanguageCatalogRefs, resolveRequestedSignLanguage, resolveSignLanguageAlternate, resolveSignLanguageContent, SIGN_LANGUAGE_FEATURE_ID, } from './src/sign-language-content.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CatalogCard, CatalogCardPayload, MediaFragmentRange, MediaSource } from '@pie-players/pie-players-shared/types';
|
|
2
|
+
/** Catalog type token for signed alternates. Matches QTI 3's `support` value. */
|
|
3
|
+
export declare const SIGN_LANGUAGE_CATALOG_TYPE = "sign-language";
|
|
4
|
+
/** ISO 639-3 code for American Sign Language, and QTI 3's `xml:lang` value. */
|
|
5
|
+
export declare const AMERICAN_SIGN_LANGUAGE = "ase";
|
|
6
|
+
export declare function describeSignLanguage(signLang?: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* A validated signed alternate, flattened for rendering.
|
|
9
|
+
*
|
|
10
|
+
* `signLang` is optional because a card need not assert a language. Callers
|
|
11
|
+
* decide what to do with an unknown one; see `matchesRequestedSignLanguage`.
|
|
12
|
+
*/
|
|
13
|
+
export interface SignLanguageMedia {
|
|
14
|
+
signLang?: string;
|
|
15
|
+
sources: MediaSource[];
|
|
16
|
+
poster?: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
fragment?: MediaFragmentRange;
|
|
19
|
+
}
|
|
20
|
+
type SignLanguageCardLike = {
|
|
21
|
+
language?: string;
|
|
22
|
+
content?: string;
|
|
23
|
+
payload?: CatalogCardPayload;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Validate a `sign-language` card into something renderable, or `null`.
|
|
27
|
+
*
|
|
28
|
+
* Returns `null` — meaning "this card is absent" — when the payload yields no
|
|
29
|
+
* usable source. Never returns a partially-valid result that would render an
|
|
30
|
+
* empty player.
|
|
31
|
+
*
|
|
32
|
+
* A payload that carries sources but no `signLang` falls back to the card's
|
|
33
|
+
* `language`, and then to unlabelled. Language *matching* is a separate
|
|
34
|
+
* decision (see `matchesRequestedSignLanguage`) so the strict
|
|
35
|
+
* no-cross-sign-language rule lives in exactly one place.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveSignLanguageMedia(card: SignLanguageCardLike | null | undefined): SignLanguageMedia | null;
|
|
38
|
+
/**
|
|
39
|
+
* Whether a resolved signed alternate may be shown for a requested sign
|
|
40
|
+
* language.
|
|
41
|
+
*
|
|
42
|
+
* Deliberately strict: there is no cross-sign-language fallback. ASL, BSL and
|
|
43
|
+
* LSF are not interchangeable, so showing a different sign language than the
|
|
44
|
+
* one requested would hand a learner a language they may not follow — worse
|
|
45
|
+
* than showing nothing. A card that asserts *no* language is accepted, because it
|
|
46
|
+
* cannot be shown to be a mismatch — only a positive claim of another language
|
|
47
|
+
* is refused.
|
|
48
|
+
*/
|
|
49
|
+
export declare function matchesRequestedSignLanguage(media: SignLanguageMedia, requestedSignLang: string): boolean;
|
|
50
|
+
/** Whether a catalog card is a sign-language card at all. */
|
|
51
|
+
export declare function isSignLanguageCard(card: CatalogCard): boolean;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { CatalogOwnerContext, AccessibilityCatalogResolverApi, ToolContentDependencyContext } from '@pie-players/pie-assessment-toolkit';
|
|
2
|
+
import { ItemEntity } from '@pie-players/pie-players-shared/types';
|
|
3
|
+
import { SignLanguageMedia } from './sign-language-cards.js';
|
|
4
|
+
/** QTI 3.0 / AfA support id gating signed alternates. */
|
|
5
|
+
export declare const SIGN_LANGUAGE_FEATURE_ID = "signLanguage";
|
|
6
|
+
/** A catalog on this item that carries at least one sign-language card. */
|
|
7
|
+
export interface SignLanguageCatalogRef {
|
|
8
|
+
catalogId: string;
|
|
9
|
+
/** Set when the catalog is owned by one model rather than the item root. */
|
|
10
|
+
modelId?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ResolvedSignLanguageAlternate extends SignLanguageMedia {
|
|
13
|
+
catalogId: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Collect the catalog identifiers on an item that carry signing cards.
|
|
17
|
+
*
|
|
18
|
+
* The region resolves through the catalog resolver, but the resolver is keyed by
|
|
19
|
+
* identifier within an owner scope — something has to say *which* identifiers
|
|
20
|
+
* this item put in play, and whether each belongs to the item or to one model.
|
|
21
|
+
* That is the same walk the runtime does when it registers an item's catalogs,
|
|
22
|
+
* so it is borrowed rather than repeated: a ref can only name a scope
|
|
23
|
+
* registration actually files under. Only the "does this catalog carry signing"
|
|
24
|
+
* filter is ours.
|
|
25
|
+
*
|
|
26
|
+
* The owner identity here is a placeholder: the assessment and section ids are
|
|
27
|
+
* not known at extraction time and are supplied by the caller at lookup time
|
|
28
|
+
* (see `resolveSignLanguageAlternate`). Nothing but `modelId` is read from the
|
|
29
|
+
* walk's contexts.
|
|
30
|
+
*/
|
|
31
|
+
export declare function collectSignLanguageCatalogRefs(item: ItemEntity | null | undefined): SignLanguageCatalogRef[];
|
|
32
|
+
export interface SignLanguageLookupArgs {
|
|
33
|
+
resolver: AccessibilityCatalogResolverApi;
|
|
34
|
+
refs: SignLanguageCatalogRef[];
|
|
35
|
+
/** Owner context for the item, without `modelId` — added per ref. */
|
|
36
|
+
ownerContext: CatalogOwnerContext;
|
|
37
|
+
/** Sign language the learner is entitled to, ISO 639-3. */
|
|
38
|
+
requestedSignLang?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the signed alternate to show for an item, or `null`.
|
|
42
|
+
*
|
|
43
|
+
* Priority, language fallback and owner scoping are the resolver's job and are
|
|
44
|
+
* not re-implemented here. What *is* enforced here is the one deliberate
|
|
45
|
+
* departure from the resolver's default behaviour: **no cross-sign-language
|
|
46
|
+
* substitution.** The resolver's last fallback rung matches any card of the
|
|
47
|
+
* requested type regardless of language, which for spoken content is helpful
|
|
48
|
+
* and for signing is not — handing an ASL learner a BSL recording is worse than
|
|
49
|
+
* handing them nothing. So a card the resolver returns by that rung is accepted
|
|
50
|
+
* only if its language actually matches, or if the card asserts no language at
|
|
51
|
+
* all.
|
|
52
|
+
*
|
|
53
|
+
* MVP takes the first resolvable card: sample content is one recording per item.
|
|
54
|
+
* The refs stay per-node capable for when choice-level docking lands.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveSignLanguageAlternate(args: SignLanguageLookupArgs): ResolvedSignLanguageAlternate | null;
|
|
57
|
+
/**
|
|
58
|
+
* Which sign language the learner is entitled to.
|
|
59
|
+
*
|
|
60
|
+
* Read from the feature's policy parameters (`toolParameters` / `toolConfigs`),
|
|
61
|
+
* never inferred from the item's content language — a Spanish item's signed
|
|
62
|
+
* alternate is LSM, not ASL.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveRequestedSignLanguage(parameters: unknown): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* The registration's `requiresAuthoredContent` implementation: the whole
|
|
67
|
+
* content half behind the one call the host makes.
|
|
68
|
+
*
|
|
69
|
+
* The host supplies the item, the resolver and the owner scope, and learns only
|
|
70
|
+
* whether there is something to render. It never sees a catalog type, a card
|
|
71
|
+
* shape or a sign-language code.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveSignLanguageContent(context: ToolContentDependencyContext): ResolvedSignLanguageAlternate | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ToolRegistration } from '@pie-players/pie-assessment-toolkit/tools/internal';
|
|
2
|
+
/**
|
|
3
|
+
* Host surface this capability docks into: media beside a card's content.
|
|
4
|
+
*
|
|
5
|
+
* Item cards and passage cards open the same surface, so declaring it once
|
|
6
|
+
* reaches both. A signed alternate is authored against a content node, and a
|
|
7
|
+
* passage owns content nodes as an item does.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CONTENT_MEDIA_SURFACE = "content-media";
|
|
10
|
+
/** Element tag this package registers. A host may substitute its own. */
|
|
11
|
+
export declare const SIGN_LANGUAGE_ELEMENT_TAG = "pie-tool-sign-language";
|
|
12
|
+
export declare const signLanguageRegistration: ToolRegistration;
|