@pie-players/pie-assessment-toolkit 0.3.64 → 0.3.65
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 +45 -17
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +6 -6
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-cckwpz6c.js +51 -0
- package/dist/components/chunks/ItemToolBar-pryf0rtz.js +22 -0
- package/dist/index.d.ts +5 -6
- package/dist/index.js +9 -4
- package/dist/runtime/composition-emit-scheduler.d.ts +78 -0
- package/dist/runtime/composition-emit-scheduler.js +154 -0
- package/dist/runtime/core/engine-resolver.d.ts +1 -1
- package/dist/services/ToolRegistry.d.ts +218 -8
- package/dist/services/ToolRegistry.js +124 -8
- package/dist/services/ToolkitCoordinator.d.ts +2 -1
- package/dist/services/ToolkitCoordinator.js +23 -6
- package/dist/services/createDefaultToolRegistry.d.ts +25 -58
- package/dist/services/createDefaultToolRegistry.js +24 -104
- package/dist/services/defaultPersonalNeedsProfile.d.ts +16 -14
- package/dist/services/defaultPersonalNeedsProfile.js +17 -38
- package/dist/services/pnp-standard-features.d.ts +1 -1
- package/dist/services/tool-config-defaults.d.ts +7 -23
- package/dist/services/tool-config-defaults.js +7 -46
- package/dist/services/tool-config-validation.d.ts +1 -1
- package/dist/services/tool-config-validation.js +44 -4
- package/dist/services/tts/browser-provider.js +2 -1
- package/dist/services/tts-runtime-config.js +7 -2
- package/dist/tools/internal.d.ts +34 -0
- package/dist/tools/internal.js +33 -0
- package/dist/tools/tool-tag-map.d.ts +15 -3
- package/dist/tools/tool-tag-map.js +21 -18
- package/package.json +14 -10
- package/dist/components/chunks/ItemToolBar-3cppre9r.js +0 -51
- package/dist/components/chunks/ItemToolBar-7rq2gj8b.js +0 -22
- package/dist/services/sign-language-cards.d.ts +0 -82
- package/dist/services/sign-language-cards.js +0 -133
- package/dist/tools/registrations/accessibility-tools.d.ts +0 -34
- package/dist/tools/registrations/accessibility-tools.js +0 -217
- package/dist/tools/registrations/calculator.d.ts +0 -20
- package/dist/tools/registrations/calculator.js +0 -228
- package/dist/tools/registrations/interaction-tools.d.ts +0 -27
- package/dist/tools/registrations/interaction-tools.js +0 -143
- package/dist/tools/registrations/measurement-tools.d.ts +0 -24
- package/dist/tools/registrations/measurement-tools.js +0 -130
- package/dist/tools/registrations/subject-specific-tools.d.ts +0 -27
- package/dist/tools/registrations/subject-specific-tools.js +0 -158
- package/dist/tools/registrations/tts.d.ts +0 -21
- package/dist/tools/registrations/tts.js +0 -184
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import{B as bJ,C as H0,D as S0,E as pJ,F as L0,G as I0,H as _J,I as d,J as EJ,M as vJ,O as gJ,Q as $J,S as mj,T as hj,b as G0,c as SJ,d as IJ,e as N,f as a,g as w0,h as P0,i as CJ,j as $0,ja as mJ,k as K0,l as Gj,m as Y0,n as Q0,o as j,q as Pj,r as yJ,s as M0,t as U0,u as F,w as D0,x as Mj,y as e0,z as jj}from"./ItemToolBar-3cppre9r.js";function vj(v){return typeof v.href==="string"}function wJ(v){if(!v||typeof v!=="object"||Array.isArray(v))return!1;let q=v;if(typeof q.id!=="string"||q.id.trim().length===0)return!1;if(typeof q.label!=="string"||q.label.trim().length===0)return!1;if(q.ariaLabel!==void 0&&typeof q.ariaLabel!=="string")return!1;if(q.icon!==void 0&&typeof q.icon!=="string")return!1;if(q.tooltip!==void 0&&typeof q.tooltip!=="string")return!1;if(q.active!==void 0&&typeof q.active!=="boolean")return!1;if(q.disabled!==void 0&&typeof q.disabled!=="boolean")return!1;let s=typeof q.href==="string",m0=typeof q.onClick==="function";if(s===m0)return!1;if(s)return!0;return m0}function gj(v){return typeof v==="string"&&v.trimStart().startsWith("<svg")}function $j(v){return typeof v==="string"&&v.trimStart().startsWith("http")}import{sanitizeSvgIcon as Yj}from"@pie-players/pie-players-shared/security";import{approximateZoomFromWidths as qZ,computeZoomCompensation as FZ,ICON_BUTTON_ZOOM_OPTIONS as HJ}from"@pie-players/pie-players-shared/ui/zoom-compensation";import{createFocusTrap as kZ,FOCUSABLE_SELECTOR as xJ,isProgrammaticFocusTarget as BJ}from"@pie-players/pie-players-shared";import"@pie-players/pie-players-shared/nds-icon-button";var RZ=(v,q)=>{if(customElements.get(v))return;try{customElements.define(v,q)}catch(s){if(!(s instanceof DOMException&&s.name==="NotSupportedError"||s&&typeof s==="object"&&s.name==="NotSupportedError")||!customElements.get(v))throw s}},Oj=M0('<span class="item-toolbar__element-host svelte-rnx3ie"></span>'),WZ=M0('<span class="item-toolbar__nds-button-zoom svelte-rnx3ie"><nds-icon-button></nds-icon-button></span>',2),Nj=M0('<span aria-hidden="true"></span>'),AJ=M0('<img class="item-toolbar__icon-image svelte-rnx3ie" alt=""/>'),fJ=M0('<i aria-hidden="true"></i>'),zZ=M0("<a><!></a>"),wZ=M0('<button type="button"><!></button>'),TJ=M0('<span class="item-toolbar__controls-host svelte-rnx3ie"></span>'),HZ=M0("<div></div>"),xZ=M0('<div><div class="item-toolbar__tools-row svelte-rnx3ie"><!> <!> <!></div> <!></div>'),BZ={hash:"svelte-rnx3ie",code:`.item-toolbar.svelte-rnx3ie {display:flex;flex-direction:column;align-items:flex-end;gap:0;--pie-toolbar-tools-row-height: 2rem;--pie-tts-controls-row-height: 2.875rem;}.item-toolbar__tools-row.svelte-rnx3ie {display:flex;align-items:center;justify-content:flex-end;flex-wrap:nowrap;
|
|
2
|
-
/* Cap the gap between toolbar items (e.g. TTS play ↔ calculator) at its
|
|
3
|
-
200%-zoom size with the same factor the buttons use, so the spacing
|
|
4
|
-
doesn't keep growing past 200% while the buttons themselves freeze. */gap:calc(0.5rem * var(--pie-toolbar-zoom-comp, 1));min-height:var(--pie-toolbar-tools-row-height);}.item-toolbar__controls-row.svelte-rnx3ie {display:flex;align-items:center;justify-content:flex-end;width:100%;min-height:0;height:auto;}.item-toolbar__controls-row--reserve.svelte-rnx3ie {min-height:var(--pie-tts-controls-row-height);height:var(--pie-tts-controls-row-height);}.item-toolbar__controls-row--active.svelte-rnx3ie {min-height:var(--pie-tts-controls-row-height);height:var(--pie-tts-controls-row-height);}.item-toolbar__controls-row--align-start.svelte-rnx3ie {justify-content:flex-start;}.item-toolbar__controls-host.svelte-rnx3ie {display:inline-flex;align-items:center;justify-content:flex-end;width:100%;}.item-toolbar--top.svelte-rnx3ie,
|
|
5
|
-
.item-toolbar--bottom.svelte-rnx3ie {align-items:flex-end;}.item-toolbar--left.svelte-rnx3ie,
|
|
6
|
-
.item-toolbar--right.svelte-rnx3ie {align-items:stretch;}.item-toolbar--left.svelte-rnx3ie .item-toolbar__tools-row:where(.svelte-rnx3ie),
|
|
7
|
-
.item-toolbar--right.svelte-rnx3ie .item-toolbar__tools-row:where(.svelte-rnx3ie) {flex-direction:column;align-items:center;justify-content:flex-start;flex-wrap:nowrap;}.item-toolbar--left.svelte-rnx3ie .item-toolbar__controls-row:where(.svelte-rnx3ie),
|
|
8
|
-
.item-toolbar--right.svelte-rnx3ie .item-toolbar__controls-row:where(.svelte-rnx3ie) {justify-content:flex-start;width:auto;min-height:0;height:auto;}.item-toolbar__button.svelte-rnx3ie {display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0.25rem;border:1px solid var(--pie-button-border, var(--pie-border, #ccc));border-radius:0.25rem;background-color:var(--pie-button-bg, var(--pie-background, white));color:var(--pie-button-color, var(--pie-text, #333));cursor:pointer;transition:all 0.15s ease;text-decoration:none;}
|
|
9
|
-
|
|
10
|
-
/* Drive the vendored NDS icon button's outer size via its own \`--height-32\`
|
|
11
|
-
custom property so its light-DOM inner button matches the toolbar's
|
|
12
|
-
md/sm/lg dimensions (32 / 44 / 40 px) without a layout shift. The glyph
|
|
13
|
-
keeps the NDS-native icon size (we render size="small"), so it isn't
|
|
14
|
-
oversized. */
|
|
15
|
-
/* Freeze the calculator's header open/close button at its 200%-zoom size
|
|
16
|
-
(factor is 1 at zoom <= 200%). Zoom on this wrapper, not the host. */.item-toolbar__nds-button-zoom.svelte-rnx3ie {display:inline-flex;zoom:var(--pie-toolbar-zoom-comp, 1);}.item-toolbar.svelte-rnx3ie nds-icon-button:where(.svelte-rnx3ie) {
|
|
17
|
-
/* Host-settable button size per toolbar size (drives the NDS outer button
|
|
18
|
-
via its own --height-32). */--height-32: var(--pie-calculator-button-size, 2rem);
|
|
19
|
-
/* Host-settable accent for the calculator button: the NDS tertiary glyph
|
|
20
|
-
colour derives from --color-interactive-blue, remapped here to a
|
|
21
|
-
themeable variable. */--color-interactive-blue: var(--pie-calculator-button-color, #146eb3);}.item-toolbar--sm.svelte-rnx3ie nds-icon-button:where(.svelte-rnx3ie) {--height-32: var(--pie-calculator-button-size-sm, 2.75rem);}.item-toolbar--lg.svelte-rnx3ie nds-icon-button:where(.svelte-rnx3ie) {--height-32: var(--pie-calculator-button-size-lg, 2.5rem);}.item-toolbar__element-host.svelte-rnx3ie {display:contents;}.item-toolbar--sm.svelte-rnx3ie .item-toolbar__button:where(.svelte-rnx3ie) {width:2.75rem;height:2.75rem;}.item-toolbar--sm.svelte-rnx3ie {--pie-toolbar-tools-row-height: 2.75rem;--pie-tts-controls-row-height: 3.625rem;}.item-toolbar--lg.svelte-rnx3ie .item-toolbar__button:where(.svelte-rnx3ie) {width:2.5rem;height:2.5rem;}.item-toolbar--lg.svelte-rnx3ie {--pie-toolbar-tools-row-height: 2.5rem;--pie-tts-controls-row-height: 3.375rem;}.item-toolbar__button.svelte-rnx3ie:hover:not(:disabled) {background-color:var(--pie-button-hover-bg, var(--pie-secondary-background, #f5f5f5));border-color:var(--pie-button-hover-border, var(--pie-button-border, var(--pie-border, #ccc)));color:var(--pie-button-hover-color, var(--pie-button-color, var(--pie-text, #333)));transform:translateY(-1px);box-shadow:0 2px 4px color-mix(in srgb, var(--pie-black, #000) 10%, transparent);}.item-toolbar__button.svelte-rnx3ie:active:not(:disabled) {transform:translateY(0);box-shadow:none;}.item-toolbar__button--active.svelte-rnx3ie {background-color:var(--pie-primary, #1976d2);color:var(--pie-white, #fff);border-color:var(--pie-primary, #1976d2);}.item-toolbar__button--active.svelte-rnx3ie:hover:not(:disabled) {background-color:var(--pie-primary-dark, #1565c0);}.item-toolbar__button.svelte-rnx3ie:focus-visible {outline:2px solid var(--pie-button-focus-outline, var(--pie-primary, #1976d2));outline-offset:2px;}.item-toolbar__button.svelte-rnx3ie:disabled {opacity:0.5;cursor:not-allowed;}.item-toolbar__button.svelte-rnx3ie svg {width:100%;height:100%;}.item-toolbar__icon-image.svelte-rnx3ie {width:100%;height:100%;object-fit:contain;}`};function hJ(v,q){SJ(q,!0),bJ(v,BZ);let s=typeof window<"u",m0=["/_fa-pro/fontawesome.min.css","/_fa-pro/light.min.css"],uj="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css",uJ="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap",cj=/font.?awesome|fa-?pro/i,sj=!1,Rj=()=>{if(!s||sj)return;if(sj=!0,!document.querySelector('link[href*="Roboto"]')){let K=document.createElement("link");K.rel="stylesheet",K.href=uJ,document.head.appendChild(K)}if(Array.from(document.querySelectorAll('link[rel="stylesheet"][href]')).some((K)=>cj.test(K.href)))return;if(!document.querySelector(`link[href="${uj}"]`)){let K=document.createElement("link");K.rel="stylesheet",K.href=uj,document.head.appendChild(K)}for(let K of m0){if(document.querySelector(`link[href="${K}"]`))continue;let Z=document.createElement("link");Z.rel="stylesheet",Z.href=K,document.head.appendChild(Z)}},ij="__pieFaToolbarShadowInstalled",cJ=(J)=>{let K=J.getRootNode();if(!(K instanceof ShadowRoot))return;let Z=K;if(Z[ij])return;Z[ij]=!0;let Q=new Set,X=(w)=>{if(!w||Q.has(w))return;Q.add(w);let i=document.createElement("link");i.rel="stylesheet",i.href=w,K.appendChild(i)},Y=Array.from(document.querySelectorAll('link[rel="stylesheet"][href]')).filter((w)=>cj.test(w.href));for(let w of Y)X(w.href)},sJ=(J)=>{return Rj(),cJ(J),{}},iJ=(J,K)=>{let Z=K,Q=()=>{let Y=J.querySelector("button");if(Y)Y.setAttribute("aria-pressed",Z?"true":"false")};Q();let X=new MutationObserver(Q);return X.observe(J,{childList:!0,subtree:!0}),{update(Y){Z=Y,Q()},destroy(){X.disconnect()}}},aJ={calculator:"calculator"},dJ=(J)=>aJ[J.id]??null,rJ=mJ(),C0=w0(CJ({})),p0=d(q,"level",7,"item"),Jj=d(q,"scopeId",7,""),qj=d(q,"itemId",7,""),Fj=d(q,"sectionId",7,""),kj=d(q,"catalogId",7,""),Wj=d(q,"tools",7,"calculator,textToSpeech,answerEliminator"),zj=d(q,"contentKind",7,"assessment-item"),x0=d(q,"position",7,"bottom"),h0=d(q,"scopeElement",7,null),wj=d(q,"toolRegistry",7,null),Hj=d(q,"item",7,null),Zj=d(q,"hostButtons",23,()=>[]),xj=d(q,"class",7,""),u0=d(q,"size",7,"md"),Lj=d(q,"language",7,"en-US"),R0=w0(null);function aj(){if(typeof window>"u")return 1;return FZ(qZ(window.outerWidth,window.innerWidth),HJ.maxZoom,HJ.minCompensation)}let dj=w0(1);Y0(()=>{if(typeof window>"u")return;let J=()=>{P0(dj,aj(),!0)};return J(),window.addEventListener("resize",J),()=>window.removeEventListener("resize",J)});let g=w0(null),c0=N(()=>j(g)?.ndsIcons===!0),y0=w0(null),s0=w0(0),Kj=w0(0),Bj=w0(0);Y0(()=>{if(!j(R0))return;return vJ(j(R0),(J)=>{P0(g,J,!0)})}),Y0(()=>{if(!j(R0))return;return gJ(j(R0),(J)=>{P0(y0,J,!0)})}),Y0(()=>{let J=j(g)?.toolkitCoordinator;if(!J||typeof J.onPolicyChange!=="function")return;let K=J.onPolicyChange(()=>{P0(Kj,j(Kj)+1)});return()=>{try{K?.()}catch{}}}),Y0(()=>{let J=j(g)?.toolkitCoordinator;if(!J||typeof J.onToolContextResolverChange!=="function")return;let K=J.onToolContextResolverChange(()=>{P0(Bj,j(Bj)+1)});return()=>{try{K?.()}catch{}}});let I=N(()=>j(g)?.toolCoordinator),rj=N(()=>j(g)?.ttsService),_0=N(()=>j(g)?.elementToolStateStore),Qj=N(()=>j(g)?.assessmentId??""),i0=N(()=>qj()||j(y0)?.itemId||""),r=N(()=>j(y0)?.canonicalItemId||j(i0)),B0=N(()=>Fj()||j(g)?.sectionId||""),E0=N(()=>zj()||j(y0)?.contentKind||(p0()==="section"?"section":"assessment-item")),C=N(()=>{if(p0()&&p0()!=="item")return p0();if(j(E0)==="rubric-block-stimulus")return"passage";return"item"}),A0=N(()=>{if(Jj())return Jj();if(j(C)==="section")return j(B0)||j(g)?.sectionId||"default-section";if(j(C)==="assessment")return j(g)?.assessmentId||"default-assessment";return j(r)||j(i0)||"default-item"}),lj=N(()=>kj()||j(A0)),k0=N(()=>Hj()||j(y0)?.item||null),X0=N(()=>wj()||rJ),lJ=N(()=>$J(Wj())),oJ=N(()=>j(X0).normalizeToolIds(j(lJ)).filter(Boolean)),nJ=N(()=>{if(j(C)==="section")return"section";if(j(C)==="passage"||j(E0)==="rubric-block-stimulus")return"passage";return"item"}),oj=N(()=>{j(Kj);let J=j(g)?.toolkitCoordinator;if(!J||typeof J.decideToolPolicy!=="function")return null;return J.decideToolPolicy({level:j(nJ),scope:{level:j(C),scopeId:j(A0),assessmentId:j(g)?.assessmentId,sectionId:j(B0)||void 0,itemId:j(i0)||void 0,canonicalItemId:j(r)||void 0,contentKind:j(E0)}})}),nj=N(()=>{let J=(K)=>Array.from(new Set(K));if(j(oj))return J(j(X0).normalizeToolIds(j(oj).visibleTools.map((K)=>K.toolId)).filter(Boolean));return J(j(oJ))}),Aj=N(()=>{if(j(C)==="section"||j(C)==="assessment")return!0;let J=j(k0)?.config;return!!(j(k0)&&J&&typeof J==="object")}),tj=N(()=>{j(Kj);let J=j(g)?.toolkitCoordinator;if(!J||typeof J.getPolicyInputs!=="function")return null;return J.getPolicyInputs()}),v0=N(()=>j(tj)?.assessment??null),Uj=N(()=>j(tj)?.currentItemRef??null),a0=N(()=>{if(j(C)==="section")return{level:"section",assessment:j(v0)||{},section:{}};if(j(C)==="assessment")return{level:"assessment",assessment:j(v0)||{}};if(!j(Aj)||!j(k0))return null;if(j(C)==="passage")return{level:"passage",assessment:j(v0)||{},itemRef:j(Uj)||{id:j(r)},passage:j(k0)};return{level:"item",assessment:j(v0)||{},itemRef:j(Uj)||{id:j(r)},item:j(k0)}}),ej=N(()=>{if(j(a0))return j(a0);return{level:"item",assessment:j(v0)||{},itemRef:j(Uj)||{id:j(r)},item:j(k0)||{id:j(r),config:{}}}}),jJ=N(()=>{if(j(C)!=="item"&&j(C)!=="passage")return[];if(!j(Aj)||!j(k0))return[];let J=j(k0)?.config?.models;return(Array.isArray(J)?J:J&&typeof J==="object"?Object.values(J):[]).filter((Z)=>Z&&typeof Z==="object"&&typeof Z.id==="string").map((Z)=>({level:"element",assessment:j(v0)||{},itemRef:j(Uj)||{id:j(r)},item:j(k0),elementId:Z.id}))}),tJ=N(()=>{let J=j(g)?.toolkitCoordinator||null,K=(Z)=>hj(Z)?Z:mj(Z,j(C),j(A0));return{scope:{level:j(C),scopeId:j(A0),assessmentId:j(g)?.assessmentId,sectionId:j(B0),itemId:j(i0),canonicalItemId:j(r),contentKind:j(E0)},itemId:j(A0),catalogId:j(lj),language:Lj(),ui:{size:u0()},getScopeElement:()=>h0()||j(y0)?.scopeElement||null,getGlobalElementId:()=>{if(!j(_0)||!j(Qj)||!j(B0)||!j(r))return null;return j(_0).getGlobalElementId(j(Qj),j(B0),j(r),j(r))},toolCoordinator:j(I)||null,toolkitCoordinator:J,ttsService:j(rj)||null,elementToolStateStore:j(_0)||null,toggleTool:(Z)=>{if(!j(I))return;let Q=K(Z);if(!j(I).getToolState(Q))j(I).registerTool(Q,Z);j(I).toggleTool(Q)},isToolVisible:(Z)=>{if(!j(I))return!1;return j(I).isToolVisible(K(Z))},subscribeVisibility:j(I)?(Z)=>j(I).subscribe(Z):null}}),fj=N(()=>{j(Bj);let J=j(g)?.toolkitCoordinator;if(!J||typeof J.hasToolContextResolver!=="function"||typeof J.resolveToolContext!=="function")return{};let K={};for(let Z of j(nj)){if(!j(X0).get(Z)?.supportedLevels.includes(j(C)))continue;if(!J.hasToolContextResolver(Z))continue;let X=J.resolveToolContext({toolId:Z,context:j(ej),toolbarContext:j(tJ)});if(X)K[Z]=X}return K}),eJ=N(()=>{let J=j(nj).filter((Y)=>{let w=j(X0).get(Y);return w?w.supportedLevels.includes(j(C)):!1}),K=Object.values(j(fj)),Z=new Set(K.map((Y)=>Y.toolId)),Q=new Set(K.filter((Y)=>Y.visible).map((Y)=>Y.toolId)),X=J.filter((Y)=>!Z.has(Y));if(j(C)==="section")return X.forEach((Y)=>Q.add(Y)),Array.from(Q);if(!j(Aj))return X.forEach((Y)=>Q.add(Y)),Array.from(Q);if(!j(a0)&&j(jJ).length===0)return X.forEach((Y)=>Q.add(Y)),Array.from(Q);if(j(a0))j(X0).filterVisibleInContext(X,j(a0)).forEach((Y)=>Q.add(Y.toolId));for(let Y of j(jJ))j(X0).filterVisibleInContext(X,Y).forEach((w)=>Q.add(w.toolId));return Array.from(Q)}),Tj=N(()=>j(X0).filterToolIdsByActivation(j(eJ),"toolbar-toggle"));Y0(()=>{if(!s)return;let J=!1;return j(X0).ensureToolModulesLoaded(j(Tj)).then(()=>{if(!J)P0(s0,j(s0)+1)}).catch((K)=>{console.error("[ItemToolBar] Failed to load one or more tool modules:",K)}),()=>{J=!0}});function jZ(){if(h0())return h0();return j(y0)?.scopeElement||null}function JZ(){if(!j(_0)||!j(Qj)||!j(B0)||!j(r))return null;return j(_0).getGlobalElementId(j(Qj),j(B0),j(r),j(r))}let b0=N(()=>{let J=j(g)?.toolkitCoordinator||null,K=(Z)=>{return hj(Z)?Z:mj(Z,j(C),j(A0))};return{scope:{level:j(C),scopeId:j(A0),assessmentId:j(g)?.assessmentId,sectionId:j(B0),itemId:j(i0),canonicalItemId:j(r),contentKind:j(E0)},itemId:j(A0),catalogId:j(lj),language:Lj(),ui:{size:u0()},getScopeElement:jZ,getGlobalElementId:JZ,toolCoordinator:j(I)||null,toolkitCoordinator:J,ttsService:j(rj)||null,elementToolStateStore:j(_0)||null,toggleTool:(Z)=>{if(!j(I))return;let Q=K(Z);if(!j(I).getToolState(Q))j(I).registerTool(Q,Z);j(I).toggleTool(Q)},isToolVisible:(Z)=>{if(!j(I))return!1;return j(I).isToolVisible(K(Z))},subscribeVisibility:j(I)?(Z)=>j(I).subscribe(Z):null,getResolvedToolContext:(Z)=>j(fj)[Z]??null,getToolRenderParams:(Z)=>j(fj)[Z]?.params??null}}),W0=N(()=>{if(!s)return[];j(s0);let J=[];for(let K of j(Tj)){let Z=j(X0).renderForToolbar(K,j(ej),j(b0));if(Z)J.push(Z)}return J}),ZZ=N(()=>{if(!Array.isArray(Zj()))return[];let J=[];return Zj().forEach((K,Z)=>{if(wJ(K)){J.push(K);return}console.warn(`[ItemToolBar] Ignoring invalid host button at index ${Z}. Expected { id, label, href | onClick } with valid types.`)}),J}),LZ=N(()=>j(W0).filter((J)=>!!J.button).map((J)=>{let K=J.button;return{id:J.toolId,label:K.label,ariaLabel:K.ariaLabel||K.label,icon:K.icon,tooltip:K.tooltip||K.label,disabled:K.disabled,active:j(C0)[J.toolId]??K.active??!1,onClick:()=>{K.onClick(),r0()}}})),JJ=N(()=>[...j(LZ),...j(ZZ)]),d0=N(()=>{let J={};for(let K of j(W0))J[K.toolId]=j(C0)[K.toolId]??K.button?.active??!1;return J}),KZ=N(()=>j(W0).flatMap((J)=>(J.elements||[]).filter((K)=>K.mount==="before-buttons").filter((K)=>Boolean(K.element)).map((K,Z)=>({key:`before-${J.toolId}-${Z}`,toolId:J.toolId,entry:K})))),QZ=N(()=>j(W0).flatMap((J)=>(J.elements||[]).filter((K)=>K.mount==="after-buttons").filter((K)=>Boolean(K.element)).map((K,Z)=>({key:`after-${J.toolId}-${Z}`,toolId:J.toolId,entry:K})))),ZJ=N(()=>j(W0).flatMap((J)=>(J.elements||[]).filter((K)=>K.mount==="controls-row").filter((K)=>Boolean(K.element)).map((K,Z)=>({key:`controls-row-${J.toolId}-${Z}`,toolId:J.toolId,entry:K})))),LJ=N(()=>j(W0).flatMap((J)=>(J.elements||[]).map((K)=>({toolId:J.toolId,hint:K.layoutHints?.controlsRow})).filter((K)=>Boolean(K.hint)))),KJ=N(()=>j(W0).flatMap((J)=>(J.elements||[]).map((K)=>({toolId:J.toolId,hint:K.layoutHints?.headerOverlay})).filter((K)=>Boolean(K.hint)))),QJ=N(()=>j(LJ).some((J)=>J.hint?.reserveSpace===!0)),UJ=N(()=>j(LJ).some((J)=>J.hint?.showWhenToolActive===!0&&(j(d0)[J.toolId]??!1))),UZ=N(()=>x0()==="left"||x0()==="right"),DJ=N(()=>j(KJ).some((J)=>J.hint?.showWhenToolActive===!0&&(j(d0)[J.toolId]??!1))),DZ=N(()=>j(ZJ).length>0||j(QJ)||j(UJ));function XZ(){if(!j(R0))return null;let J=j(R0).getRootNode();if(J instanceof ShadowRoot)return J.host;return null}Y0(()=>{let J=XZ();if(!J)return;let K=j(KJ).length>0,Z=j(DJ);return J.setAttribute("data-pie-header-overlay",K?"true":"false"),J.setAttribute("data-pie-header-overlay-active",Z?"true":"false"),()=>{J.removeAttribute("data-pie-header-overlay"),J.removeAttribute("data-pie-header-overlay-active")}}),Y0(()=>{if(!s)return;if(j(JJ).some((J)=>J.icon==="calculator"))Rj()});function Dj(J){if(J.id in j(C0))return j(C0)[J.id]===!0;return J.active===!0}function XJ(J){return{calculator:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 2h10a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Zm0 2v4h10V4H7Zm0 6v2h2v-2H7Zm4 0v2h2v-2h-2Zm4 0v2h2v-2h-2Zm-8 4v2h2v-2H7Zm4 0v2h2v-2h-2Zm4 0v2h2v-2h-2Zm-8 4v2h2v-2H7Zm4 0v2h2v-2h-2Zm4 0v2h2v-2h-2Z" fill="currentColor"/></svg>',"volume-up":'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 3.23v2.06A7.002 7.002 0 0 1 19 12a7 7 0 0 1-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77Zm-2 17.75V3L7 8H3v8h4l5 5Zm4.5-9a4.5 4.5 0 0 0-2.5-4.03v8.05A4.5 4.5 0 0 0 16.5 12Z" fill="currentColor"/></svg>',swatch:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 3a9 9 0 1 0 9 9c0-.55-.45-1-1-1h-2.5a1.5 1.5 0 0 1 0-3H20a1 1 0 0 0 1-1 8.99 8.99 0 0 0-9-4Zm-5.5 9A1.5 1.5 0 1 1 8 13.5 1.5 1.5 0 0 1 6.5 12Zm3-4A1.5 1.5 0 1 1 11 9.5 1.5 1.5 0 0 1 9.5 8Zm5 0A1.5 1.5 0 1 1 16 9.5 1.5 1.5 0 0 1 14.5 8Z" fill="currentColor"/></svg>',"chart-bar":'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4.75 5a.76.76 0 0 1 .75.75v11c0 .438.313.75.75.75h13a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-13C5 19 4 18 4 16.75v-11A.74.74 0 0 1 4.75 5ZM8 8.25a.74.74 0 0 1 .75-.75h6.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-6.5A.722.722 0 0 1 8 8.25Zm.75 2.25h4.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-4.5a.723.723 0 0 1-.75-.75.74.74 0 0 1 .75-.75Zm0 3h8.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-8.5a.723.723 0 0 1-.75-.75.74.74 0 0 1 .75-.75Z" fill="currentColor"/></svg>',beaker:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 21c-.85 0-1.454-.38-1.813-1.137-.358-.759-.27-1.463.263-2.113L9 11V5H8a.968.968 0 0 1-.713-.287A.968.968 0 0 1 7 4c0-.283.096-.52.287-.712A.968.968 0 0 1 8 3h8c.283 0 .52.096.712.288.192.191.288.429.288.712s-.096.52-.288.713A.968.968 0 0 1 16 5h-1v6l5.55 6.75c.533.65.62 1.354.262 2.113C20.454 20.62 19.85 21 19 21H5Zm2-3h10l-3.4-4h-3.2L7 18Zm-2 1h14l-6-7.3V5h-2v6.7L5 19Z" fill="currentColor"/></svg>',protractor:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m6.75 21-.25-2.2 2.85-7.85a3.95 3.95 0 0 0 1.75.95l-2.75 7.55L6.75 21Zm10.5 0-1.6-1.55-2.75-7.55a3.948 3.948 0 0 0 1.75-.95l2.85 7.85-.25 2.2ZM12 11a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 9 8c0-.65.188-1.23.563-1.737A2.935 2.935 0 0 1 11 5.2V3h2v2.2c.583.2 1.063.554 1.438 1.063C14.812 6.77 15 7.35 15 8c0 .833-.292 1.542-.875 2.125A2.893 2.893 0 0 1 12 11Zm0-2c.283 0 .52-.096.713-.287A.967.967 0 0 0 13 8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8c0 .283.096.52.287.713.192.191.43.287.713.287Z" fill="currentColor"/></svg>',"bars-3":'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.85 15c.517 0 .98-.15 1.388-.45.408-.3.695-.692.862-1.175l.375-1.15c.267-.8.2-1.537-.2-2.213C8.875 9.337 8.3 9 7.55 9H4.025l.475 3.925c.083.583.346 1.075.787 1.475.442.4.963.6 1.563.6Zm10.3 0c.6 0 1.12-.2 1.563-.6.441-.4.704-.892.787-1.475L19.975 9h-3.5c-.75 0-1.325.342-1.725 1.025-.4.683-.467 1.425-.2 2.225l.35 1.125c.167.483.454.875.862 1.175.409.3.871.45 1.388.45Zm-10.3 2c-1.1 0-2.063-.363-2.887-1.088a4.198 4.198 0 0 1-1.438-2.737L2 9H1V7h6.55c.733 0 1.404.18 2.013.537A3.906 3.906 0 0 1 11 9h2.025c.35-.617.83-1.104 1.438-1.463A3.892 3.892 0 0 1 16.474 7H23v2h-1l-.525 4.175a4.198 4.198 0 0 1-1.438 2.737A4.238 4.238 0 0 1 17.15 17c-.95 0-1.804-.27-2.562-.813A4.234 4.234 0 0 1 13 14.026l-.375-1.125a21.35 21.35 0 0 1-.1-.363 4.926 4.926 0 0 1-.1-.537h-.85c-.033.2-.067.363-.1.488a21.35 21.35 0 0 1-.1.362L11 14a4.3 4.3 0 0 1-1.588 2.175A4.258 4.258 0 0 1 6.85 17Z" fill="currentColor"/></svg>',ruler:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m8.8 10.95 2.15-2.175-1.4-1.425-1.1 1.1-1.4-1.4 1.075-1.1L7 4.825 4.825 7 8.8 10.95Zm8.2 8.225L19.175 17l-1.125-1.125-1.1 1.075-1.4-1.4 1.075-1.1-1.425-1.4-2.15 2.15L17 19.175ZM7.25 21H3v-4.25l4.375-4.375L2 7l5-5 5.4 5.4 3.775-3.8c.2-.2.425-.35.675-.45a2.068 2.068 0 0 1 1.55 0c.25.1.475.25.675.45L20.4 4.95c.2.2.35.425.45.675.1.25.15.508.15.775a1.975 1.975 0 0 1-.6 1.425l-3.775 3.8L22 17l-5 5-5.375-5.375L7.25 21ZM5 19h1.4l9.8-9.775L14.775 7.8 5 17.6V19Z" fill="currentColor"/></svg>'}[J]||null}function r0(){let J={};for(let K of j(W0))if(K.sync?.(),K.button)J[K.toolId]=K.button.active??!1;P0(C0,J,!0)}Y0(()=>{let J=[];r0();for(let K of j(W0))if(K.subscribeActive){let Z=!1,Q=K.subscribeActive((X)=>{queueMicrotask(()=>{if(Z)return;P0(C0,{...j(C0),[K.toolId]:X},!0),K.sync?.()})});J.push(()=>{Z=!0,Q()})}return()=>{J.forEach((K)=>K())}}),Y0(()=>{if(!j(b0).subscribeVisibility)return;let J=!1,K=j(b0).subscribeVisibility(()=>{queueMicrotask(()=>{if(J)return;r0()})});return()=>{J=!0,K?.()}}),Y0(()=>{let J=j(b0).toolkitCoordinator;if(typeof J?.subscribeTelemetry!=="function")return;let K=!1,Z=J.subscribeTelemetry(({eventName:Q,payload:X})=>{if(Q!=="pie-toolkit-tool-config-updated")return;if(X?.toolId&&!j(Tj).includes(X.toolId))return;queueMicrotask(()=>{if(K)return;P0(s0,j(s0)+1),r0()})});return()=>{K=!0,Z?.()}});function Sj(J,K){let Z=null,Q=(Y)=>{if(!Y)return;let w=Y.__pieToolElementUnmount;if(typeof w==="function")w()},X=(Y)=>{if(Z===Y)return;if(Z){if(Q(Z),Z.parentNode===J)J.removeChild(Z)}if(Z=Y,Z){if(Z.parentNode&&Z.parentNode!==J)Z.parentNode.removeChild(Z);J.appendChild(Z)}};return X(K),{update(Y){X(Y)},destroy(){X(null)}}}function Ij(J,K){let Z=K,Q=null,X=null,Y=null,w=null,i=null,q0=null,u=null,O=null,l=null,o=!1,c=!1,k=null,A=null,y=null,j0=0,$=0,T=0,H=0,R=0,B=0,n=0,O0=0,S=null,N0=[],b=0,p=0,_=Z.mounted.entry.shell?.initialWidth??720,E=Z.mounted.entry.shell?.initialHeight??560,F0=null,J0=null,x=!1,f=(L)=>{if(!L)return;let D=L.__pieToolElementUnmount;if(typeof D==="function")D()},z0=()=>{let L=Z.mounted.entry.shell;if(!L)return null;return{toolId:Z.mounted.toolId,toolbarContext:j(b0),shellConfig:L}},l0=(L)=>{let D=j(X0).get(Z.mounted.toolId),P=z0();if(!D?.onHostedMount||!P)return;D.onHostedMount(L,P)},f0=()=>{let L=j(X0).get(Z.mounted.toolId),D=z0();if(!L?.onHostedResize||!D)return;L.onHostedResize({width:_,height:E},Z.mounted.entry.element,D)},o0=()=>{let L=j(X0).get(Z.mounted.toolId),D=z0();if(!L?.onHostedUnmount||!D)return;L.onHostedUnmount(Z.mounted.entry.element,D)},z=(L,D,P)=>Math.max(D,Math.min(L,P)),t=()=>{let L=Z.mounted.entry.shell,D=L?.minWidth??320,P=L?.minHeight??240,V=L?.maxWidth??window.innerWidth,G=L?.maxHeight??window.innerHeight;return{minWidth:D,minHeight:P,maxWidth:V,maxHeight:G}},Cj=()=>{let L=Z.mounted.entry.shell?.minWidth,D=typeof L==="number"&&L>0&&_<L,P=D?`${L}px`:"";if(k)k.style.minWidth=P;if(X)X.style.minWidth=P;if(Y)Y.style.minWidth=P;if(Q)Q.style.overflowX=D?"auto":"visible",Q.style.overflowY="visible"},YJ=()=>Z.mounted.entry.shell?.content?.overflowY==="auto"?"auto":"hidden",NZ=()=>{if(!X)return 0;let L=X.getBoundingClientRect().height;if(L>0)return L;return X.offsetHeight||0},yj=()=>{if(!Y)return;let L=Z.mounted.entry.shell;if(Y.style.overflowX="hidden",Y.style.overflowY=YJ(),!k)return;if(L?.content?.preserveMinHeight===!0){let D=NZ(),P=L.minHeight??240,V=Math.max(0,P-D),G=Math.max(0,E-D),U=Math.max(G,V);k.style.height=`${U}px`,k.style.minHeight="0",k.style.flex=`0 0 ${U}px`;return}k.style.height="100%",k.style.minHeight="0",k.style.flex="1 1 auto"},Xj=()=>{let{minWidth:L,minHeight:D,maxWidth:P,maxHeight:V}=t(),G=Math.min(L,window.innerWidth),U=Math.min(D,window.innerHeight);_=z(_,G,Math.max(G,Math.min(P,window.innerWidth))),E=z(E,U,Math.max(U,Math.min(V,window.innerHeight))),b=z(b,0,Math.max(0,window.innerWidth-_)),p=z(p,0,Math.max(0,window.innerHeight-E)),n0(),Cj(),yj(),f0()},T0=(L,D)=>{b+=L,p+=D,Xj()},Vj=(L,D)=>{_+=L,E+=D,Xj()},OJ=(L,D,P,V="fa-regular")=>{let G=document.createElement("nds-icon-button");if(G.setAttribute("variant","tertiary"),G.setAttribute("size","small"),G.setAttribute("type","circle"),G.setAttribute("icon-name",D),G.setAttribute("button-aria-label",L),G.title=L,G.addEventListener("click",(U)=>{U.stopPropagation(),P(),g0()}),V!=="fa-light"){let U=(M)=>{M.classList.remove("fa-light"),M.classList.add(V)},W=G.querySelector("i.fa-light");if(W)U(W);else{let M=new MutationObserver(()=>{let m=G.querySelector("i.fa-light");if(m)U(m),M.disconnect()});M.observe(G,{childList:!0,subtree:!0})}}return G},NJ=(L,D,P)=>{let V=document.createElement("button");return V.type="button",V.className="pie-tool-shell__control",V.setAttribute("aria-label",L),V.title=L,V.textContent=D,V.style.border="1px solid transparent",V.style.background="color-mix(in srgb, var(--pie-white, #fff) 10%, transparent)",V.style.color="inherit",V.style.cursor="pointer",V.style.display="inline-flex",V.style.alignItems="center",V.style.justifyContent="center",V.style.width="28px",V.style.height="28px",V.style.padding="0",V.style.fontSize="14px",V.style.fontWeight="700",V.style.borderRadius="8px",V.style.lineHeight="1",V.onclick=(G)=>{G.stopPropagation(),P(),g0()},V.onfocus=()=>{V.style.outline="2px solid var(--pie-button-focus-outline, var(--pie-primary, #4A90E2))",V.style.outlineOffset="2px"},V.onblur=()=>{V.style.outline="none",V.style.outlineOffset="0"},V},n0=()=>{if(!Q)return;Q.style.left=`${b}px`,Q.style.top=`${p}px`,Q.style.width=`${_}px`,Q.style.height=`${E}px`,Q.style.display=Z.active?"flex":"none",Q.style.setProperty("--pie-tool-shell-zoom-comp",String(aj()))},GJ=()=>{if(!Y)return;let L=Z.mounted.entry.element;if(L.style.display="block",L.style.width="100%",L.style.height="100%",L.style.flex="1 1 auto",L.style.minHeight="0",k&&k!==L){if(k.parentNode===Y)f(k),Y.removeChild(k);k=null}if(L.parentNode&&L.parentNode!==Y)L.parentNode.removeChild(L);if(L.parentNode!==Y)Y.appendChild(L);k=L,Cj(),yj(),l0(L)},g0=()=>{if(j(I)&&Q)j(I).bringToFront(Q)},bj=()=>{let{innerWidth:L,innerHeight:D}=window,P=Z.mounted.entry.shell,V=P?.initialAlign??"center",G=P?.initialMargin??16,U=G+60;switch(V){case"top-left":b=G,p=U;break;case"top-right":b=Math.max(0,L-_-G),p=U;break;case"bottom-left":b=G,p=Math.max(0,D-E-U);break;case"bottom-right":b=Math.max(0,L-_-G),p=Math.max(0,D-E-U);break;default:b=Math.max(0,Math.round((L-_)/2)),p=Math.max(0,Math.round((D-E)/2))}Xj()},GZ=()=>{let L=J0;if(!L)return;queueMicrotask(()=>{if(!L.isConnected)return;try{L.focus()}catch{}})},PJ=()=>{if(typeof document>"u")return null;let L=document.activeElement;while(L){let D=L.shadowRoot;if(D&&D.activeElement&&D.activeElement!==L)L=D.activeElement;else break}return L??null},MJ=()=>{if(!Q||F0)return;let L=PJ();if(!J0&&L&&!Q.contains(L))J0=L;let D=Z.mounted.toolId==="calculator";if(D&&!c)document.addEventListener("keydown",_j,!0),c=!0;F0=kZ(Q,{initialFocus:q0,onEscape:()=>{Ej()},wrap:!D,onTabExit:D?(P,V)=>{if(P==="backward"){if(J0?.isConnected){V.preventDefault();try{J0.focus()}catch{}}return}let G=pj();if(G){V.preventDefault();try{G.focus()}catch{}}}:void 0})},pj=()=>{let L=j(b0).getScopeElement?.()??null;if(!L)return null;let D=(V)=>{if(j(R0)&&j(R0).contains(V))return!0;if(Q&&Q.contains(V))return!0;return!1},P=(V)=>{if(V instanceof HTMLElement){if(D(V))return null;if(V.matches?.(xJ)&&BJ(V))return V}let G=V.shadowRoot;if(G)for(let U=0;U<G.children.length;U++){let W=P(G.children[U]);if(W)return W}for(let U=0;U<V.children.length;U++){let W=P(V.children[U]);if(W)return W}return null};return P(L)},PZ=()=>{if(!Q)return[];return Array.from(Q.querySelectorAll(xJ)).filter((L)=>L!==O&&L!==l).filter(BJ)},_j=(L)=>{if(L.key!=="Tab")return;if(!Q||!Z.active)return;let D=PJ();if(!D)return;if(Q.contains(D))return;let P=PZ();if(P.length===0)return;if(L.shiftKey){let V=pj();if(D!==V)return;L.preventDefault();try{P[P.length-1].focus()}catch{}return}if(D!==J0)return;L.preventDefault();try{P[0].focus()}catch{}},RJ=()=>{if(c)document.removeEventListener("keydown",_j,!0),c=!1;if(!F0)return;let L=F0;F0=null;try{L()}catch{}GZ()},Ej=()=>{j(b0).toggleTool(Z.mounted.toolId),r0()},qJ=(L)=>{if(!Z.mounted.entry.shell?.draggable)return;if(L.target.closest("button")||!Q)return;L.preventDefault(),A=L.pointerId,j0=L.clientX-b,$=L.clientY-p,Q.setPointerCapture(L.pointerId),g0()},MZ=(L)=>(D)=>{if(!Q||!Z.mounted.entry.shell?.resizable)return;D.preventDefault(),D.stopPropagation(),y=D.pointerId,S=L,T=_,H=E,R=D.clientX,B=D.clientY,n=b,O0=p,Q.setPointerCapture(D.pointerId),g0()},FJ=(L)=>{if(!Q)return;if(A===L.pointerId){L.preventDefault();let D=Math.max(0,window.innerWidth-_),P=Math.max(0,window.innerHeight-E);b=z(L.clientX-j0,0,D),p=z(L.clientY-$,0,P),n0();return}if(y===L.pointerId){L.preventDefault();let D=Z.mounted.entry.shell,P=D?.minWidth??320,V=D?.minHeight??240,G=Math.min(P,window.innerWidth),U=Math.min(V,window.innerHeight),W=D?.maxWidth??window.innerWidth,M=D?.maxHeight??window.innerHeight,m=L.clientX-R,e=L.clientY-B;if(S==="se")_=z(T+m,G,Math.max(G,Math.min(W,window.innerWidth-b))),E=z(H+e,U,Math.max(U,Math.min(M,window.innerHeight-p)));else if(S==="sw"){let Z0=n+T,V0=z(T-m,G,Math.min(W,Z0));b=Z0-V0,_=V0,E=z(H+e,U,Math.max(U,Math.min(M,window.innerHeight-p)))}else if(S==="ne"){let Z0=O0+H;_=z(T+m,G,Math.max(G,Math.min(W,window.innerWidth-b)));let V0=z(H-e,U,Math.min(M,Z0));p=Z0-V0,E=V0}else if(S==="nw"){let Z0=n+T,V0=O0+H,t0=z(T-m,G,Math.min(W,Z0));b=Z0-t0,_=t0;let h=z(H-e,U,Math.min(M,V0));p=V0-h,E=h}n0(),Cj(),yj(),f0()}},kJ=(L)=>{if(!Q)return;if(A===L.pointerId)A=null,Q.releasePointerCapture(L.pointerId);if(y===L.pointerId)y=null,Q.releasePointerCapture(L.pointerId)},WJ=()=>{Xj()};if(s&&Z.mounted.entry.shell){let L=Z.mounted.toolId==="calculator",D=L&&j(c0);if(D)Rj();if(Q=document.createElement("div"),Q.className="pie-tool-shell",Q.setAttribute("data-pie-tool-shell",Z.mounted.toolId),Q.style.position="fixed",Q.style.zIndex="2000",Q.style.background="var(--pie-background, #fff)",Q.style.border="1px solid var(--pie-border-light, #d1d5db)",Q.style.borderRadius="12px",Q.style.boxShadow="0 10px 40px color-mix(in srgb, var(--pie-black, #000) 25%, transparent)",Q.style.overflow="visible",Q.style.display=Z.active?"flex":"none",Q.style.flexDirection="column",Q.style.userSelect="none",Q.style.webkitUserSelect="none",Q.style.touchAction="none",Q.setAttribute("draggable","false"),Q.addEventListener("dragstart",(U)=>U.preventDefault()),X=document.createElement("div"),X.className="pie-tool-shell__header",X.style.display="flex",X.style.alignItems="center",X.style.justifyContent="space-between",X.style.gap="6px",X.style.padding=L?"12px 12px 12px 28px":"10px 12px",L)X.style.minHeight="48px";if(L)X.style.background="var(--pie-section-player-card-header-background, #f3f4f6)",X.style.color="var(--pie-text, #111827)",X.style.borderBottom="1px solid var(--pie-border-light, #e5e7eb)";else X.style.background="var(--pie-primary-dark, #2c3e50)",X.style.color="var(--pie-white, #fff)";X.style.cursor=Z.mounted.entry.shell.draggable===!1?"default":"move",X.style.flex="0 0 auto",X.style.borderRadius="12px 12px 0 0",X.style.overflow="hidden",X.style.userSelect="none",X.style.webkitUserSelect="none",X.style.touchAction="none",X.setAttribute("draggable","false"),X.addEventListener("dragstart",(U)=>U.preventDefault()),w=document.createElement("span"),w.className="pie-tool-shell__title",w.textContent=Z.mounted.entry.shell.title||Z.mounted.toolId,X.appendChild(w),i=document.createElement("div"),i.className="pie-tool-shell__controls",i.style.display="inline-flex",i.style.alignItems="center",i.style.gap=L?"6px":"4px";let P=Z.mounted.entry.shell,V=(U,W,M,m,e="fa-regular")=>{if(!i)return;i.appendChild(D?OJ(U,M,m,e):NJ(U,W,m))};if(P?.draggable!==!1)V("Move tool left","←","chevron-left",()=>T0(-24,0)),V("Move tool right","→","chevron-right",()=>T0(24,0)),V("Move tool up","↑","chevron-up",()=>T0(0,-24)),V("Move tool down","↓","chevron-down",()=>T0(0,24));if(P?.resizable!==!1)V("Shrink tool window","−","magnifying-glass-minus",()=>Vj(-40,-40)),V("Grow tool window","+","magnifying-glass-plus",()=>Vj(40,40));if(!L)i.appendChild(NJ("Center tool window","◎",bj));let G=null;if(L)G=document.createElement("div"),G.className="pie-tool-shell__header-right",G.style.display="inline-flex",G.style.alignItems="center",G.style.gap="6px",G.style.setProperty("zoom","var(--pie-tool-shell-zoom-comp, 1)"),G.appendChild(i),X.appendChild(G);else X.appendChild(i);if(D)q0=OJ("Close tool","xmark",Ej,"fa-regular"),q0.style.display=Z.mounted.entry.shell.closeable===!1?"none":"inline-block";else{let U=document.createElement("button");U.type="button",U.className="pie-tool-shell__close",U.setAttribute("aria-label","Close tool");let W="http://www.w3.org/2000/svg",M=document.createElementNS(W,"svg");M.setAttribute("xmlns",W),M.setAttribute("viewBox","0 0 16 16"),M.setAttribute("aria-hidden","true");let m=document.createElementNS(W,"path");m.setAttribute("d","M3.5 3.5L12.5 12.5M12.5 3.5L3.5 12.5"),m.setAttribute("stroke","currentColor"),m.setAttribute("stroke-width","1.8"),m.setAttribute("stroke-linecap","round"),M.appendChild(m),U.appendChild(M);let e=M.style;e.width="16px",e.height="16px",e.display="block",e.flexShrink="0",e.pointerEvents="none";let Z0="color-mix(in srgb, var(--pie-white, #fff) 8%, transparent)",V0="color-mix(in srgb, var(--pie-white, #fff) 18%, transparent)";U.style.border="1px solid transparent",U.style.background=Z0,U.style.color="inherit",U.style.cursor="pointer",U.style.display="inline-flex",U.style.alignItems="center",U.style.justifyItems="center",U.style.width="28px",U.style.height="28px",U.style.padding="0",U.style.borderRadius="8px",U.style.lineHeight="0",U.style.transition="background-color 0.15s ease, border-color 0.15s ease",U.style.display=Z.mounted.entry.shell.closeable===!1?"none":"inline-flex",U.onmouseenter=()=>{U.style.background=V0},U.onmouseleave=()=>{U.style.background=Z0},U.onfocus=()=>{U.style.outline="2px solid var(--pie-button-focus-outline, var(--pie-primary, #4A90E2))",U.style.outlineOffset="2px"},U.onblur=()=>{U.style.outline="none",U.style.outlineOffset="0"},U.onclick=Ej,q0=U}if(G)G.appendChild(q0);else X.appendChild(q0);if(X.tabIndex=0,X.onkeydown=(U)=>{if(U.key==="Home"){U.preventDefault(),bj();return}let W=Z.mounted.entry.shell;if(U.shiftKey&&W?.resizable!==!1){if(U.key==="ArrowRight"||U.key==="ArrowDown"){U.preventDefault(),Vj(40,40);return}if(U.key==="ArrowLeft"||U.key==="ArrowUp"){U.preventDefault(),Vj(-40,-40);return}}if(W?.draggable!==!1){if(U.key==="ArrowLeft")U.preventDefault(),T0(-24,0);else if(U.key==="ArrowRight")U.preventDefault(),T0(24,0);else if(U.key==="ArrowUp")U.preventDefault(),T0(0,-24);else if(U.key==="ArrowDown")U.preventDefault(),T0(0,24)}},Y=document.createElement("div"),Y.className="pie-tool-shell__content",Y.style.position="relative",Y.style.width="100%",Y.style.flex="1 1 auto",Y.style.minHeight="0",Y.style.overflowX="hidden",Y.style.overflowY=YJ(),Y.style.borderRadius="0 0 12px 12px",L){let U=(W)=>{let M=document.createElement("div");return M.tabIndex=0,M.setAttribute("aria-hidden","true"),M.setAttribute("data-pie-tool-shell-focus-guard",W),M.style.position="absolute",M.style.width="1px",M.style.height="1px",M.style.padding="0",M.style.margin="-1px",M.style.overflow="hidden",M.style.clipPath="inset(50%)",M.style.whiteSpace="nowrap",M.style.border="0",M};O=U("start"),l=U("end"),O.addEventListener("focus",(W)=>{if(o)return;o=!0;try{if(W.stopPropagation(),J0?.isConnected)try{J0.focus()}catch{}}finally{queueMicrotask(()=>{o=!1})}}),l.addEventListener("focus",(W)=>{if(o)return;o=!0;try{W.stopPropagation();let M=pj();if(M)try{M.focus()}catch{}}finally{queueMicrotask(()=>{o=!1})}}),Q.appendChild(O)}if(Q.appendChild(X),Q.appendChild(Y),L&&l)Q.appendChild(l);if(Z.mounted.entry.shell.resizable!==!1){let U=(W,M,m,e,Z0,V0,t0)=>{let h=document.createElement("div");if(h.className="pie-tool-shell__resize",h.style.position="absolute",h.style.width="24px",h.style.height="24px",h.style.cursor=V0,h.style.zIndex="10",h.style.touchAction="none",h.setAttribute("draggable","false"),M!==null)h.style.top=M;if(m!==null)h.style.right=m;if(e!==null)h.style.bottom=e;if(Z0!==null)h.style.left=Z0;if(t0!==null)h.style.background=`linear-gradient(${t0}, transparent 0%, transparent 40%, rgba(0,0,0,0.35) 40%, rgba(0,0,0,0.35) 60%, transparent 60%, transparent 100%)`;let zJ=MZ(W);h.addEventListener("pointerdown",zJ),Q.appendChild(h),N0.push({el:h,handler:zJ})};U("se",null,"0","0",null,"nwse-resize",null),U("nw","0",null,null,"0","nwse-resize","135deg"),U("ne","0","0",null,null,"nesw-resize",null),U("sw",null,null,"0","0","nesw-resize",null)}if(X.addEventListener("pointerdown",qJ),Q.addEventListener("pointermove",FJ),Q.addEventListener("pointerup",kJ),Q.addEventListener("pointerdown",g0),window.addEventListener("resize",WJ),document.body.appendChild(Q),bj(),n0(),GJ(),f0(),Z.active)MJ();x=Z.active}return{update(L){if(Z=L,!Q||!Y||!w||!q0)return;w.textContent=Z.mounted.entry.shell?.title||Z.mounted.toolId;let D=Z.mounted.toolId==="calculator"?"inline-block":"inline-flex";if(q0.style.display=Z.mounted.entry.shell?.closeable===!1?"none":D,n0(),GJ(),f0(),!x&&Z.active)MJ();else if(x&&!Z.active)RJ(),J0=null;x=Z.active},destroy(){if(o0(),F0)RJ();if(c)document.removeEventListener("keydown",_j,!0),c=!1;for(let{el:L,handler:D}of N0)L.removeEventListener("pointerdown",D);if(J0=null,N0.length=0,X)X.removeEventListener("pointerdown",qJ),X.onkeydown=null;if(Q)Q.removeEventListener("pointermove",FJ),Q.removeEventListener("pointerup",kJ),Q.removeEventListener("pointerdown",g0);if(window.removeEventListener("resize",WJ),k&&Y&&k.parentNode===Y)f(k),Y.removeChild(k);if(k=null,Q&&Q.parentElement)Q.remove()}}}var VZ={get level(){return p0()},set level(J){p0(J),a()},get scopeId(){return Jj()},set scopeId(J){Jj(J),a()},get itemId(){return qj()},set itemId(J){qj(J),a()},get sectionId(){return Fj()},set sectionId(J){Fj(J),a()},get catalogId(){return kj()},set catalogId(J){kj(J),a()},get tools(){return Wj()},set tools(J){Wj(J),a()},get contentKind(){return zj()},set contentKind(J){zj(J),a()},get position(){return x0()},set position(J){x0(J),a()},get scopeElement(){return h0()},set scopeElement(J){h0(J),a()},get toolRegistry(){return wj()},set toolRegistry(J){wj(J),a()},get item(){return Hj()},set item(J){Hj(J),a()},get hostButtons(){return Zj()},set hostButtons(J){Zj(J),a()},get class(){return xj()},set class(J){xj(J),a()},get size(){return u0()},set size(J){u0(J),a()},get language(){return Lj()},set language(J){Lj(J),a()}},VJ=U0(),YZ=K0(VJ);{var OZ=(J)=>{var K=xZ();let Z;var Q=$0(K),X=$0(Q);e0(X,17,()=>j(KZ),(u)=>u.key,(u,O)=>{var l=U0(),o=K0(l);{var c=(A)=>{var y=U0(),j0=K0(y);Mj(j0,()=>j(c0),($)=>{var T=Oj();H0(T,(H,R)=>Ij?.(H,R),()=>({mounted:j(O),active:j(d0)[j(O).toolId]??!1})),F($,T)}),F(A,y)},k=(A)=>{var y=Oj();H0(y,(j0,$)=>Sj?.(j0,$),()=>j(O).entry.element),F(A,y)};D0(o,(A)=>{if(j(O).entry.shell)A(c);else A(k,-1)})}F(u,l)});var Y=Gj(X,2);e0(Y,17,()=>j(JJ),(u)=>u.id,(u,O,l,o)=>{let c=N(()=>j(c0)&&!vj(j(O))?dJ(j(O)):null);var k=U0(),A=K0(k);{var y=(H)=>{var R=WZ(),B=$0(R);S0(B,1,"item-toolbar__nds-button svelte-rnx3ie"),I0(B,"type","circle"),I0(B,"size","small"),I0(B,"variant","tertiary"),Q0(()=>I0(B,"icon-name",j(c))),Q0(()=>I0(B,"button-aria-label",j(O).ariaLabel||j(O).label)),Q0(()=>I0(B,"title",j(O).tooltip||j(O).label)),Q0(()=>I0(B,"disabled",j(O).disabled)),H0(B,(n)=>sJ?.(n)),H0(B,(n,O0)=>iJ?.(n,O0),()=>Dj(j(O))),G0(R),Pj("click",B,function(...n){j(O).onClick?.apply(this,n)}),F(H,R)},j0=(H)=>{var R=zZ();let B;var n=$0(R);{var O0=(S)=>{var N0=U0(),b=K0(N0);{var p=(x)=>{var f=Nj();jj(f,()=>Yj(j(O).icon),!0),G0(f),F(x,f)},_=N(()=>gj(j(O).icon)),E=(x)=>{var f=AJ();Q0(()=>L0(f,"src",j(O).icon)),F(x,f)},F0=N(()=>$j(j(O).icon)),J0=(x)=>{let f=N(()=>XJ(j(O).icon));var z0=U0(),l0=K0(z0);{var f0=(z)=>{var t=Nj();jj(t,()=>Yj(j(f)),!0),G0(t),F(z,t)},o0=(z)=>{var t=fJ();Q0(()=>S0(t,1,`icon icon-${j(O).icon}`,"svelte-rnx3ie")),F(z,t)};D0(l0,(z)=>{if(j(f))z(f0);else z(o0,-1)})}F(x,z0)};D0(b,(x)=>{if(j(_))x(p);else if(j(F0))x(E,1);else x(J0,-1)})}F(S,N0)};D0(n,(S)=>{if(j(O).icon)S(O0)})}G0(R),Q0((S)=>{B=S0(R,1,"item-toolbar__button svelte-rnx3ie",null,B,S),L0(R,"href",j(O).disabled?void 0:j(O).href),L0(R,"target",j(O).target),L0(R,"rel",j(O).rel),L0(R,"aria-label",j(O).ariaLabel||j(O).label),L0(R,"title",j(O).tooltip||j(O).label),L0(R,"aria-disabled",j(O).disabled?"true":void 0)},[()=>({"item-toolbar__button--active":Dj(j(O))})]),Pj("click",R,(S)=>{if(j(O).disabled)S.preventDefault()}),F(H,R)},$=N(()=>vj(j(O))),T=(H)=>{var R=wZ();let B;var n=$0(R);{var O0=(S)=>{var N0=U0(),b=K0(N0);{var p=(x)=>{var f=Nj();jj(f,()=>Yj(j(O).icon),!0),G0(f),F(x,f)},_=N(()=>gj(j(O).icon)),E=(x)=>{var f=AJ();Q0(()=>L0(f,"src",j(O).icon)),F(x,f)},F0=N(()=>$j(j(O).icon)),J0=(x)=>{let f=N(()=>XJ(j(O).icon));var z0=U0(),l0=K0(z0);{var f0=(z)=>{var t=Nj();jj(t,()=>Yj(j(f)),!0),G0(t),F(z,t)},o0=(z)=>{var t=fJ();Q0(()=>S0(t,1,`icon icon-${j(O).icon}`,"svelte-rnx3ie")),F(z,t)};D0(l0,(z)=>{if(j(f))z(f0);else z(o0,-1)})}F(x,z0)};D0(b,(x)=>{if(j(_))x(p);else if(j(F0))x(E,1);else x(J0,-1)})}F(S,N0)};D0(n,(S)=>{if(j(O).icon)S(O0)})}G0(R),Q0((S,N0)=>{B=S0(R,1,"item-toolbar__button svelte-rnx3ie",null,B,S),L0(R,"aria-label",j(O).ariaLabel||j(O).label),L0(R,"aria-pressed",N0),L0(R,"title",j(O).tooltip||j(O).label),R.disabled=j(O).disabled},[()=>({"item-toolbar__button--active":Dj(j(O))}),()=>Dj(j(O))]),Pj("click",R,function(...S){j(O).onClick?.apply(this,S)}),F(H,R)};D0(A,(H)=>{if(j(c))H(y);else if(j($))H(j0,1);else H(T,-1)})}F(u,k)});var w=Gj(Y,2);e0(w,17,()=>j(QZ),(u)=>u.key,(u,O)=>{var l=U0(),o=K0(l);{var c=(A)=>{var y=U0(),j0=K0(y);Mj(j0,()=>j(c0),($)=>{var T=Oj();H0(T,(H,R)=>Ij?.(H,R),()=>({mounted:j(O),active:j(d0)[j(O).toolId]??!1})),F($,T)}),F(A,y)},k=(A)=>{var y=Oj();H0(y,(j0,$)=>Sj?.(j0,$),()=>j(O).entry.element),F(A,y)};D0(o,(A)=>{if(j(O).entry.shell)A(c);else A(k,-1)})}F(u,l)}),G0(Q);var i=Gj(Q,2);{var q0=(u)=>{var O=HZ();let l;e0(O,21,()=>j(ZJ),(o)=>o.key,(o,c)=>{var k=U0(),A=K0(k);{var y=($)=>{var T=U0(),H=K0(T);Mj(H,()=>j(c0),(R)=>{var B=TJ();H0(B,(n,O0)=>Ij?.(n,O0),()=>({mounted:j(c),active:j(d0)[j(c).toolId]??!1})),F(R,B)}),F($,T)},j0=($)=>{var T=TJ();H0(T,(H,R)=>Sj?.(H,R),()=>j(c).entry.element),F($,T)};D0(A,($)=>{if(j(c).entry.shell)$(y);else $(j0,-1)})}F(o,k)}),G0(O),Q0(()=>l=S0(O,1,"item-toolbar__controls-row svelte-rnx3ie",null,l,{"item-toolbar__controls-row--reserve":j(QJ),"item-toolbar__controls-row--active":j(UJ),"item-toolbar__controls-row--align-start":j(UZ)})),F(u,O)};D0(i,(u)=>{if(j(DZ))u(q0)})}G0(K),_J(K,(u)=>P0(R0,u),()=>j(R0)),Q0(()=>{Z=S0(K,1,`item-toolbar ${xj()??""} item-toolbar--${u0()??""}`,"svelte-rnx3ie",Z,{"item-toolbar--top":x0()==="top","item-toolbar--right":x0()==="right","item-toolbar--bottom":x0()==="bottom","item-toolbar--left":x0()==="left","item-toolbar--header-overlay-active":j(DJ)}),L0(K,"data-content-kind",j(E0)),L0(K,"data-level",j(C)),pJ(K,`--pie-toolbar-zoom-comp: ${j(dj)};`)}),F(J,K)};D0(YZ,(J)=>{if(s)J(OZ)})}return F(v,VJ),IJ(VZ)}yJ(["click"]);RZ("pie-item-toolbar",EJ(hJ,{level:{attribute:"level",type:"String"},scopeId:{attribute:"scope-id",type:"String"},itemId:{attribute:"item-id",type:"String"},sectionId:{attribute:"section-id",type:"String"},catalogId:{attribute:"catalog-id",type:"String"},tools:{attribute:"tools",type:"String"},contentKind:{attribute:"content-kind",type:"String"},position:{attribute:"position",type:"String"},size:{attribute:"size",type:"String"},language:{attribute:"language",type:"String"},scopeElement:{type:"Object"},toolRegistry:{type:"Object"},item:{type:"Object"},hostButtons:{type:"Object"},class:{}},[],[],{mode:"open"}));
|
|
22
|
-
export{hJ as a};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sign-language catalog card payloads.
|
|
3
|
-
*
|
|
4
|
-
* A `sign-language` catalog card carries a signing video rather than text, so
|
|
5
|
-
* `CatalogCard.content` (a flat string) cannot describe it: no second source,
|
|
6
|
-
* no MIME type, no poster, no time range. `CatalogCard.payload` carries those,
|
|
7
|
-
* and this module is the single place that decides whether a card describes a
|
|
8
|
-
* playable signed alternate.
|
|
9
|
-
*
|
|
10
|
-
* The payload is the *only* accepted form. A bare URL in `content` is not a
|
|
11
|
-
* signing card: nothing writes that shape, so accepting it would buy a second
|
|
12
|
-
* code path and a second source of truth for no existing content. Such a card
|
|
13
|
-
* is reported and treated as absent rather than silently rendering.
|
|
14
|
-
*
|
|
15
|
-
* Validation is "treat as absent, never as text": a malformed payload must not
|
|
16
|
-
* degrade to an empty video or render a URL as visible content.
|
|
17
|
-
*
|
|
18
|
-
* There is deliberately no signing equivalent of `data-tts-suppress`. Whether a
|
|
19
|
-
* clip gives a decoding item away depends on fingerspelling versus lexical
|
|
20
|
-
* signing — a fact about the recording, known to the signer and not to whoever
|
|
21
|
-
* authors an attribute. And suppression is per node while a signed alternate is
|
|
22
|
-
* one video per item, so the only available rule would withhold a deaf
|
|
23
|
-
* candidate's whole translation over one word. Read-aloud needs a machine-readable
|
|
24
|
-
* guard because a synthesizer speaks whatever text is present; signed content does
|
|
25
|
-
* not exist until a signer films it. Revisit only if per-node signing docking
|
|
26
|
-
* lands and a program authors signing for decoding-construct items.
|
|
27
|
-
*
|
|
28
|
-
* Part of PIE Assessment Toolkit.
|
|
29
|
-
*/
|
|
30
|
-
import type { CatalogCard, CatalogCardPayload, MediaFragmentRange, MediaSource } from "@pie-players/pie-players-shared/types";
|
|
31
|
-
import { applyMediaFragment } from "./catalog-media.js";
|
|
32
|
-
export { applyMediaFragment };
|
|
33
|
-
/** Catalog type token for signed alternates. Matches QTI 3's `support` value. */
|
|
34
|
-
export declare const SIGN_LANGUAGE_CATALOG_TYPE = "sign-language";
|
|
35
|
-
/** ISO 639-3 code for American Sign Language, and QTI 3's `xml:lang` value. */
|
|
36
|
-
export declare const AMERICAN_SIGN_LANGUAGE = "ase";
|
|
37
|
-
export declare function describeSignLanguage(signLang?: string): string;
|
|
38
|
-
/**
|
|
39
|
-
* A validated signed alternate, flattened for rendering.
|
|
40
|
-
*
|
|
41
|
-
* `signLang` is optional because a card need not assert a language. Callers
|
|
42
|
-
* decide what to do with an unknown one; see `matchesRequestedSignLanguage`.
|
|
43
|
-
*/
|
|
44
|
-
export interface SignLanguageMedia {
|
|
45
|
-
signLang?: string;
|
|
46
|
-
sources: MediaSource[];
|
|
47
|
-
poster?: string;
|
|
48
|
-
label?: string;
|
|
49
|
-
fragment?: MediaFragmentRange;
|
|
50
|
-
}
|
|
51
|
-
type SignLanguageCardLike = {
|
|
52
|
-
language?: string;
|
|
53
|
-
content?: string;
|
|
54
|
-
payload?: CatalogCardPayload;
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* Validate a `sign-language` card into something renderable, or `null`.
|
|
58
|
-
*
|
|
59
|
-
* Returns `null` — meaning "this card is absent" — when the payload yields no
|
|
60
|
-
* usable source. Never returns a partially-valid result that would render an
|
|
61
|
-
* empty player.
|
|
62
|
-
*
|
|
63
|
-
* A payload that carries sources but no `signLang` falls back to the card's
|
|
64
|
-
* `language`, and then to unlabelled. Language *matching* is a separate
|
|
65
|
-
* decision (see `matchesRequestedSignLanguage`) so the strict
|
|
66
|
-
* no-cross-sign-language rule lives in exactly one place.
|
|
67
|
-
*/
|
|
68
|
-
export declare function resolveSignLanguageMedia(card: SignLanguageCardLike | null | undefined): SignLanguageMedia | null;
|
|
69
|
-
/**
|
|
70
|
-
* Whether a resolved signed alternate may be shown for a requested sign
|
|
71
|
-
* language.
|
|
72
|
-
*
|
|
73
|
-
* Deliberately strict: there is no cross-sign-language fallback. ASL, BSL and
|
|
74
|
-
* LSF are not interchangeable, so showing a different sign language than the
|
|
75
|
-
* one requested would hand a learner a language they may not follow — worse
|
|
76
|
-
* than showing nothing. A card that asserts *no* language is accepted, because it
|
|
77
|
-
* cannot be shown to be a mismatch — only a positive claim of another language
|
|
78
|
-
* is refused.
|
|
79
|
-
*/
|
|
80
|
-
export declare function matchesRequestedSignLanguage(media: SignLanguageMedia, requestedSignLang: string): boolean;
|
|
81
|
-
/** Whether a catalog card is a sign-language card at all. */
|
|
82
|
-
export declare function isSignLanguageCard(card: CatalogCard): boolean;
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sign-language catalog card payloads.
|
|
3
|
-
*
|
|
4
|
-
* A `sign-language` catalog card carries a signing video rather than text, so
|
|
5
|
-
* `CatalogCard.content` (a flat string) cannot describe it: no second source,
|
|
6
|
-
* no MIME type, no poster, no time range. `CatalogCard.payload` carries those,
|
|
7
|
-
* and this module is the single place that decides whether a card describes a
|
|
8
|
-
* playable signed alternate.
|
|
9
|
-
*
|
|
10
|
-
* The payload is the *only* accepted form. A bare URL in `content` is not a
|
|
11
|
-
* signing card: nothing writes that shape, so accepting it would buy a second
|
|
12
|
-
* code path and a second source of truth for no existing content. Such a card
|
|
13
|
-
* is reported and treated as absent rather than silently rendering.
|
|
14
|
-
*
|
|
15
|
-
* Validation is "treat as absent, never as text": a malformed payload must not
|
|
16
|
-
* degrade to an empty video or render a URL as visible content.
|
|
17
|
-
*
|
|
18
|
-
* There is deliberately no signing equivalent of `data-tts-suppress`. Whether a
|
|
19
|
-
* clip gives a decoding item away depends on fingerspelling versus lexical
|
|
20
|
-
* signing — a fact about the recording, known to the signer and not to whoever
|
|
21
|
-
* authors an attribute. And suppression is per node while a signed alternate is
|
|
22
|
-
* one video per item, so the only available rule would withhold a deaf
|
|
23
|
-
* candidate's whole translation over one word. Read-aloud needs a machine-readable
|
|
24
|
-
* guard because a synthesizer speaks whatever text is present; signed content does
|
|
25
|
-
* not exist until a signer films it. Revisit only if per-node signing docking
|
|
26
|
-
* lands and a program authors signing for decoding-construct items.
|
|
27
|
-
*
|
|
28
|
-
* Part of PIE Assessment Toolkit.
|
|
29
|
-
*/
|
|
30
|
-
import { applyMediaFragment, isSafeMediaSrc, normalizeMediaFragment, normalizeMediaSources, trimmedOrUndefined, } from "./catalog-media.js";
|
|
31
|
-
// Re-exported because `applyMediaFragment` is part of the toolkit's public
|
|
32
|
-
// surface under this module's name; the implementation is shared with spoken
|
|
33
|
-
// audio cards now that both forms reference media.
|
|
34
|
-
export { applyMediaFragment };
|
|
35
|
-
/** Catalog type token for signed alternates. Matches QTI 3's `support` value. */
|
|
36
|
-
export const SIGN_LANGUAGE_CATALOG_TYPE = "sign-language";
|
|
37
|
-
/** ISO 639-3 code for American Sign Language, and QTI 3's `xml:lang` value. */
|
|
38
|
-
export const AMERICAN_SIGN_LANGUAGE = "ase";
|
|
39
|
-
/**
|
|
40
|
-
* Human-readable names for the sign languages PIE has a reason to name today.
|
|
41
|
-
*
|
|
42
|
-
* Used for the region's accessible label, which must name the language ("American
|
|
43
|
-
* Sign Language") rather than say "video". Unknown codes fall back to a labelled
|
|
44
|
-
* code rather than a lie.
|
|
45
|
-
*/
|
|
46
|
-
const SIGN_LANGUAGE_NAMES = {
|
|
47
|
-
ase: "American Sign Language",
|
|
48
|
-
bfi: "British Sign Language",
|
|
49
|
-
fsl: "French Sign Language",
|
|
50
|
-
gss: "Greek Sign Language",
|
|
51
|
-
mfs: "Mexican Sign Language",
|
|
52
|
-
// Signed English is not a distinct sign language; it rides the same card
|
|
53
|
-
// type tagged with a spoken-language code, so name it where it appears.
|
|
54
|
-
"eng-US": "Signed English",
|
|
55
|
-
"en-US": "Signed English",
|
|
56
|
-
};
|
|
57
|
-
export function describeSignLanguage(signLang) {
|
|
58
|
-
const code = (signLang || "").trim();
|
|
59
|
-
if (!code)
|
|
60
|
-
return "Sign language";
|
|
61
|
-
return SIGN_LANGUAGE_NAMES[code] ?? `Sign language (${code})`;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Validate a `sign-language` card into something renderable, or `null`.
|
|
65
|
-
*
|
|
66
|
-
* Returns `null` — meaning "this card is absent" — when the payload yields no
|
|
67
|
-
* usable source. Never returns a partially-valid result that would render an
|
|
68
|
-
* empty player.
|
|
69
|
-
*
|
|
70
|
-
* A payload that carries sources but no `signLang` falls back to the card's
|
|
71
|
-
* `language`, and then to unlabelled. Language *matching* is a separate
|
|
72
|
-
* decision (see `matchesRequestedSignLanguage`) so the strict
|
|
73
|
-
* no-cross-sign-language rule lives in exactly one place.
|
|
74
|
-
*/
|
|
75
|
-
export function resolveSignLanguageMedia(card) {
|
|
76
|
-
if (!card)
|
|
77
|
-
return null;
|
|
78
|
-
const cardLanguage = trimmedOrUndefined(card.language);
|
|
79
|
-
const payload = card.payload;
|
|
80
|
-
if (!payload || typeof payload !== "object") {
|
|
81
|
-
// Always say something. A signing card that yields nothing is invisible to
|
|
82
|
-
// everyone except the learner who needed the accommodation, so the only
|
|
83
|
-
// place it can surface is here.
|
|
84
|
-
//
|
|
85
|
-
// `payload` was briefly also spelled `signLanguage` by two producers, and
|
|
86
|
-
// this function accepted both. It no longer does — one fact under two names
|
|
87
|
-
// is what let a card render on one code path and read as absent on another —
|
|
88
|
-
// so a card left over from that spelling arrives here with no payload at
|
|
89
|
-
// all, which is what the second message is for.
|
|
90
|
-
if (trimmedOrUndefined(card.content)) {
|
|
91
|
-
console.warn("[sign-language] card carries `content` but no `payload`; signing media must be a structured payload, so this card is ignored");
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
console.warn("[sign-language] card carries no `payload`; signing media lives in `payload` (a card written against the older `signLanguage` key needs re-importing), so this card is ignored");
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
const media = payload.media;
|
|
99
|
-
const sources = normalizeMediaSources(media?.sources);
|
|
100
|
-
if (sources.length === 0)
|
|
101
|
-
return null;
|
|
102
|
-
const poster = trimmedOrUndefined(media?.poster);
|
|
103
|
-
return {
|
|
104
|
-
signLang: trimmedOrUndefined(payload.signLang) ?? cardLanguage,
|
|
105
|
-
sources,
|
|
106
|
-
poster: poster && isSafeMediaSrc(poster) ? poster : undefined,
|
|
107
|
-
label: trimmedOrUndefined(media?.label),
|
|
108
|
-
fragment: normalizeMediaFragment(payload.fragment),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Whether a resolved signed alternate may be shown for a requested sign
|
|
113
|
-
* language.
|
|
114
|
-
*
|
|
115
|
-
* Deliberately strict: there is no cross-sign-language fallback. ASL, BSL and
|
|
116
|
-
* LSF are not interchangeable, so showing a different sign language than the
|
|
117
|
-
* one requested would hand a learner a language they may not follow — worse
|
|
118
|
-
* than showing nothing. A card that asserts *no* language is accepted, because it
|
|
119
|
-
* cannot be shown to be a mismatch — only a positive claim of another language
|
|
120
|
-
* is refused.
|
|
121
|
-
*/
|
|
122
|
-
export function matchesRequestedSignLanguage(media, requestedSignLang) {
|
|
123
|
-
if (!media.signLang)
|
|
124
|
-
return true;
|
|
125
|
-
const requested = (requestedSignLang || "").trim();
|
|
126
|
-
if (!requested)
|
|
127
|
-
return true;
|
|
128
|
-
return media.signLang.toLowerCase() === requested.toLowerCase();
|
|
129
|
-
}
|
|
130
|
-
/** Whether a catalog card is a sign-language card at all. */
|
|
131
|
-
export function isSignLanguageCard(card) {
|
|
132
|
-
return card?.catalog === SIGN_LANGUAGE_CATALOG_TYPE;
|
|
133
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Accessibility Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers tools for visual accessibility and reading support:
|
|
5
|
-
* - Line Reader (reading guide)
|
|
6
|
-
* - Color Scheme (theme/contrast)
|
|
7
|
-
* - Annotation Toolbar (text highlighting)
|
|
8
|
-
*
|
|
9
|
-
* Maps to QTI 3.0 standard access features from:
|
|
10
|
-
* - visual category: highContrastDisplay, colorContrast
|
|
11
|
-
* - reading category: readingMask, readingGuide, highlighting
|
|
12
|
-
*/
|
|
13
|
-
import type { ToolRegistration } from "../../services/ToolRegistry.js";
|
|
14
|
-
/**
|
|
15
|
-
* Line Reader tool registration
|
|
16
|
-
*
|
|
17
|
-
* Provides a reading guide overlay to help track reading position.
|
|
18
|
-
* Useful for text-heavy passages and questions.
|
|
19
|
-
*/
|
|
20
|
-
export declare const lineReaderToolRegistration: ToolRegistration;
|
|
21
|
-
/**
|
|
22
|
-
* Theme tool registration
|
|
23
|
-
*
|
|
24
|
-
* Provides accessible theme and contrast controls.
|
|
25
|
-
* Global tool that affects entire assessment.
|
|
26
|
-
*/
|
|
27
|
-
export declare const themeToolRegistration: ToolRegistration;
|
|
28
|
-
/**
|
|
29
|
-
* Annotation Toolbar registration
|
|
30
|
-
*
|
|
31
|
-
* Text highlighting with CSS Custom Highlight API.
|
|
32
|
-
* Zero DOM mutation, optimal performance.
|
|
33
|
-
*/
|
|
34
|
-
export declare const annotationToolbarRegistration: ToolRegistration;
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Accessibility Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers tools for visual accessibility and reading support:
|
|
5
|
-
* - Line Reader (reading guide)
|
|
6
|
-
* - Color Scheme (theme/contrast)
|
|
7
|
-
* - Annotation Toolbar (text highlighting)
|
|
8
|
-
*
|
|
9
|
-
* Maps to QTI 3.0 standard access features from:
|
|
10
|
-
* - visual category: highContrastDisplay, colorContrast
|
|
11
|
-
* - reading category: readingMask, readingGuide, highlighting
|
|
12
|
-
*/
|
|
13
|
-
import { hasReadableText } from "../../services/tool-context.js";
|
|
14
|
-
import { createToolElement, } from "../tool-tag-map.js";
|
|
15
|
-
import { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "./toolbar-registration-helpers.js";
|
|
16
|
-
/**
|
|
17
|
-
* Line Reader tool registration
|
|
18
|
-
*
|
|
19
|
-
* Provides a reading guide overlay to help track reading position.
|
|
20
|
-
* Useful for text-heavy passages and questions.
|
|
21
|
-
*/
|
|
22
|
-
export const lineReaderToolRegistration = {
|
|
23
|
-
toolId: "lineReader",
|
|
24
|
-
name: "Line Reader",
|
|
25
|
-
description: "Reading guide overlay",
|
|
26
|
-
icon: "bars-3",
|
|
27
|
-
// Line reader appears where there's text to read
|
|
28
|
-
supportedLevels: ["section", "passage", "rubric", "item"],
|
|
29
|
-
// PNP support IDs
|
|
30
|
-
// Maps to QTI 3.0 standard features: readingMask, readingGuide, readingRuler
|
|
31
|
-
pnpSupportIds: [
|
|
32
|
-
"readingMask", // QTI 3.0 standard (reading.readingMask)
|
|
33
|
-
"readingGuide", // QTI 3.0 standard (reading.readingGuide)
|
|
34
|
-
"readingRuler", // QTI 3.0 standard (reading.readingRuler)
|
|
35
|
-
"lineReader", // Common variant
|
|
36
|
-
"trackingGuide", // Common variant
|
|
37
|
-
],
|
|
38
|
-
/**
|
|
39
|
-
* Pass 2: Line reader is relevant when readable text is present
|
|
40
|
-
*/
|
|
41
|
-
isVisibleInContext(context) {
|
|
42
|
-
return hasReadableText(context);
|
|
43
|
-
},
|
|
44
|
-
renderToolbar(context, toolbarContext) {
|
|
45
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
46
|
-
const button = {
|
|
47
|
-
toolId: this.toolId,
|
|
48
|
-
label: this.name,
|
|
49
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
50
|
-
disabled: false,
|
|
51
|
-
ariaLabel: "Line reader - Reading guide",
|
|
52
|
-
tooltip: "Line Reader",
|
|
53
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
54
|
-
active: visibility.isActive(),
|
|
55
|
-
};
|
|
56
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
57
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
58
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
59
|
-
applyOverlaySurface(overlay, "frameless");
|
|
60
|
-
return {
|
|
61
|
-
toolId: this.toolId,
|
|
62
|
-
button,
|
|
63
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
64
|
-
sync: () => {
|
|
65
|
-
syncButtonAndOverlayVisibility({
|
|
66
|
-
button,
|
|
67
|
-
overlay,
|
|
68
|
-
isActive: visibility.isActive,
|
|
69
|
-
});
|
|
70
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
71
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
subscribeActive: visibility.subscribeActive,
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Theme tool registration
|
|
80
|
-
*
|
|
81
|
-
* Provides accessible theme and contrast controls.
|
|
82
|
-
* Global tool that affects entire assessment.
|
|
83
|
-
*/
|
|
84
|
-
export const themeToolRegistration = {
|
|
85
|
-
toolId: "theme",
|
|
86
|
-
name: "Theme",
|
|
87
|
-
description: "Accessible themes and contrast",
|
|
88
|
-
icon: "swatch",
|
|
89
|
-
// Color scheme is assessment-wide
|
|
90
|
-
supportedLevels: ["assessment", "section"],
|
|
91
|
-
// PNP support IDs
|
|
92
|
-
// Maps to QTI 3.0 standard features: highContrastDisplay, colorContrast, invertColors
|
|
93
|
-
pnpSupportIds: [
|
|
94
|
-
"highContrastDisplay", // QTI 3.0 standard (visual.highContrastDisplay)
|
|
95
|
-
"colorContrast", // QTI 3.0 standard (visual.colorContrast)
|
|
96
|
-
"invertColors", // QTI 3.0 standard (visual.invertColors)
|
|
97
|
-
"theme", // Canonical id
|
|
98
|
-
"highContrast", // Common variant
|
|
99
|
-
"customColors", // Common variant
|
|
100
|
-
],
|
|
101
|
-
/**
|
|
102
|
-
* Pass 2: Color scheme is always relevant when allowed
|
|
103
|
-
*/
|
|
104
|
-
isVisibleInContext(context) {
|
|
105
|
-
return true; // Always show if allowed by orchestrator
|
|
106
|
-
},
|
|
107
|
-
renderToolbar(context, toolbarContext) {
|
|
108
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
109
|
-
const button = {
|
|
110
|
-
toolId: this.toolId,
|
|
111
|
-
label: this.name,
|
|
112
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
113
|
-
disabled: false,
|
|
114
|
-
ariaLabel: "Theme - Change colors and contrast",
|
|
115
|
-
tooltip: "Theme",
|
|
116
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
117
|
-
active: visibility.isActive(),
|
|
118
|
-
};
|
|
119
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
120
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
121
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
122
|
-
return {
|
|
123
|
-
toolId: this.toolId,
|
|
124
|
-
button,
|
|
125
|
-
elements: [
|
|
126
|
-
{
|
|
127
|
-
element: overlay,
|
|
128
|
-
mount: "after-buttons",
|
|
129
|
-
shell: {
|
|
130
|
-
title: this.name,
|
|
131
|
-
draggable: true,
|
|
132
|
-
resizable: false,
|
|
133
|
-
closeable: true,
|
|
134
|
-
initialWidth: 520,
|
|
135
|
-
initialHeight: 380,
|
|
136
|
-
minWidth: 420,
|
|
137
|
-
minHeight: 300,
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
sync: () => {
|
|
142
|
-
syncButtonAndOverlayVisibility({
|
|
143
|
-
button,
|
|
144
|
-
overlay,
|
|
145
|
-
isActive: visibility.isActive,
|
|
146
|
-
});
|
|
147
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
148
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
subscribeActive: visibility.subscribeActive,
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
/**
|
|
156
|
-
* Annotation Toolbar registration
|
|
157
|
-
*
|
|
158
|
-
* Text highlighting with CSS Custom Highlight API.
|
|
159
|
-
* Zero DOM mutation, optimal performance.
|
|
160
|
-
*/
|
|
161
|
-
export const annotationToolbarRegistration = {
|
|
162
|
-
toolId: "annotationToolbar",
|
|
163
|
-
name: "Highlighter",
|
|
164
|
-
description: "Highlight and annotate text",
|
|
165
|
-
icon: "highlighter",
|
|
166
|
-
activation: "selection-gateway",
|
|
167
|
-
singletonScope: "section",
|
|
168
|
-
// Annotation appears where there's text content
|
|
169
|
-
supportedLevels: ["passage", "rubric", "item", "element"],
|
|
170
|
-
// PNP support IDs
|
|
171
|
-
// Maps to QTI 3.0 standard features: highlighting, annotations
|
|
172
|
-
pnpSupportIds: [
|
|
173
|
-
"highlighting", // QTI 3.0 standard (cognitive.highlighting / reading.wordHighlighting)
|
|
174
|
-
"annotations", // QTI 3.0 standard (cognitive.annotations)
|
|
175
|
-
"highlighter", // Common variant
|
|
176
|
-
"textHighlight", // Common variant
|
|
177
|
-
"annotation", // Common variant
|
|
178
|
-
],
|
|
179
|
-
/**
|
|
180
|
-
* Pass 2: Annotation is relevant when readable text is present
|
|
181
|
-
*/
|
|
182
|
-
isVisibleInContext(context) {
|
|
183
|
-
return hasReadableText(context);
|
|
184
|
-
},
|
|
185
|
-
renderToolbar(context, toolbarContext) {
|
|
186
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
187
|
-
const button = {
|
|
188
|
-
toolId: this.toolId,
|
|
189
|
-
label: this.name,
|
|
190
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
191
|
-
disabled: false,
|
|
192
|
-
ariaLabel: "Annotation toolbar - Highlight text",
|
|
193
|
-
tooltip: "Highlight",
|
|
194
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
195
|
-
active: visibility.isActive(),
|
|
196
|
-
};
|
|
197
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
198
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
199
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
200
|
-
return {
|
|
201
|
-
toolId: this.toolId,
|
|
202
|
-
button,
|
|
203
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
204
|
-
sync: () => {
|
|
205
|
-
syncButtonAndOverlayVisibility({
|
|
206
|
-
button,
|
|
207
|
-
overlay,
|
|
208
|
-
isActive: visibility.isActive,
|
|
209
|
-
});
|
|
210
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
211
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
subscribeActive: visibility.subscribeActive,
|
|
215
|
-
};
|
|
216
|
-
},
|
|
217
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Calculator Tool Registration
|
|
3
|
-
*
|
|
4
|
-
* Registers the calculator tool with support for multiple calculator types
|
|
5
|
-
* (basic, scientific, graphing) via Desmos provider.
|
|
6
|
-
*
|
|
7
|
-
* Maps to QTI 3.0 standard access features:
|
|
8
|
-
* - calculator (cognitive support)
|
|
9
|
-
* - graphingCalculator (assessment tool)
|
|
10
|
-
*/
|
|
11
|
-
import type { ToolRegistration } from "../../services/ToolRegistry.js";
|
|
12
|
-
/**
|
|
13
|
-
* Calculator tool registration
|
|
14
|
-
*
|
|
15
|
-
* Supports:
|
|
16
|
-
* - Basic, scientific, and graphing calculators via Desmos
|
|
17
|
-
* - Context-aware visibility (shows only when math content is detected)
|
|
18
|
-
* - Item level only
|
|
19
|
-
*/
|
|
20
|
-
export declare const calculatorToolRegistration: ToolRegistration;
|