@pie-players/pie-players-shared 0.3.74 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +88 -75
  2. package/dist/components/vendor/nds/README.md +4 -5
  3. package/dist/config/profile.d.ts +1 -1
  4. package/dist/config/profile.js +1 -1
  5. package/dist/i18n/index.d.ts +1 -1
  6. package/dist/i18n/index.js +1 -1
  7. package/dist/i18n/language-tags.d.ts +9 -1
  8. package/dist/i18n/language-tags.js +11 -1
  9. package/dist/i18n/messages/en-US.d.ts +33 -28
  10. package/dist/i18n/messages/en-US.js +34 -29
  11. package/dist/i18n/messages/nl-NL.d.ts +33 -28
  12. package/dist/i18n/messages/nl-NL.js +34 -29
  13. package/dist/i18n/provider.d.ts +14 -7
  14. package/dist/i18n/provider.js +26 -29
  15. package/dist/i18n/types.d.ts +4 -5
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +0 -1
  18. package/dist/instrumentation/providers/BaseInstrumentationProvider.js +0 -14
  19. package/dist/loader-config.d.ts +0 -2
  20. package/dist/loader-config.js +0 -2
  21. package/dist/loaders/element-loader.js +13 -6
  22. package/dist/loaders/esm-adapter.d.ts +11 -0
  23. package/dist/loaders/esm-adapter.js +74 -45
  24. package/dist/loaders/iife-adapter.d.ts +3 -3
  25. package/dist/loaders/iife-adapter.js +36 -35
  26. package/dist/loaders/index.d.ts +4 -2
  27. package/dist/loaders/index.js +2 -1
  28. package/dist/loaders/mathjax-events.d.ts +22 -0
  29. package/dist/loaders/mathjax-events.js +65 -0
  30. package/dist/loaders/preloaded-registration.d.ts +18 -2
  31. package/dist/loaders/preloaded-registration.js +14 -2
  32. package/dist/media/index.d.ts +4 -6
  33. package/dist/media/index.js +6 -8
  34. package/dist/object/index.d.ts +8 -3
  35. package/dist/object/index.js +8 -6
  36. package/dist/pie/asset-handler.d.ts +0 -17
  37. package/dist/pie/asset-handler.js +1 -1
  38. package/dist/pie/authoring.js +5 -7
  39. package/dist/pie/elements-rendered.d.ts +23 -0
  40. package/dist/pie/elements-rendered.js +96 -0
  41. package/dist/pie/index.d.ts +4 -6
  42. package/dist/pie/index.js +4 -7
  43. package/dist/pie/initialization.d.ts +13 -14
  44. package/dist/pie/initialization.js +61 -75
  45. package/dist/pie/instrumentation-event-bridge.js +23 -1
  46. package/dist/pie/instrumentation-event-map.js +11 -18
  47. package/dist/pie/item-controller.js +4 -0
  48. package/dist/pie/item-session-contract.js +7 -9
  49. package/dist/pie/logger.d.ts +6 -0
  50. package/dist/pie/logger.js +10 -0
  51. package/dist/pie/math-assets.d.ts +48 -0
  52. package/dist/pie/math-assets.js +81 -0
  53. package/dist/pie/resource-monitor.d.ts +34 -32
  54. package/dist/pie/resource-monitor.js +152 -231
  55. package/dist/pie/scoring.d.ts +1 -6
  56. package/dist/pie/scoring.js +3 -8
  57. package/dist/pie/session-commit.js +1 -1
  58. package/dist/pie/stages.d.ts +11 -47
  59. package/dist/pie/stages.js +11 -47
  60. package/dist/pie/updates.js +5 -4
  61. package/dist/pie/utils.d.ts +0 -2
  62. package/dist/pie/utils.js +0 -2
  63. package/dist/security/sanitize-item-markup.d.ts +8 -4
  64. package/dist/security/sanitize-item-markup.js +52 -6
  65. package/dist/security/sanitize-svg-icon.js +2 -2
  66. package/dist/security/wrap-overwide-images.d.ts +1 -1
  67. package/dist/security/wrap-overwide-images.js +20 -1
  68. package/dist/security/wrap-overwide.d.ts +8 -0
  69. package/dist/security/wrap-overwide.js +47 -3
  70. package/dist/timed-media/media-element-source.js +1 -2
  71. package/dist/types/index.d.ts +88 -153
  72. package/dist/types/index.js +2 -2
  73. package/dist/ui/attribute-coercion.d.ts +5 -0
  74. package/dist/ui/attribute-coercion.js +6 -4
  75. package/dist/ui/content-styles.d.ts +6 -10
  76. package/dist/ui/content-styles.js +8 -13
  77. package/dist/ui/first-focusable.d.ts +0 -1
  78. package/dist/ui/first-focusable.js +0 -1
  79. package/dist/ui/focus-trap.js +2 -3
  80. package/dist/ui/scope-css.d.ts +23 -26
  81. package/dist/ui/scope-css.js +23 -26
  82. package/package.json +6 -4
  83. package/dist/loaders/mathjax-version-conflict.d.ts +0 -17
  84. package/dist/loaders/mathjax-version-conflict.js +0 -51
  85. package/dist/pie/stage-tracker.d.ts +0 -50
  86. package/dist/pie/stage-tracker.js +0 -105
@@ -321,44 +321,20 @@ const nlNL = {
321
321
  textToSpeech: {
322
322
  name: "Voorlezen",
323
323
  description: "Inhoud laten voorlezen",
324
- toolA11y: "Voorleeshulp",
325
- title: "Voorlezen",
326
- initializing: "Wordt gestart…",
327
- initFailed: "Voorlezen kon niet worden gestart.",
328
- selectText: "Selecteer tekst op de pagina om die te laten voorlezen.",
329
- speed: "Snelheid:",
330
- play: "Voorlezen",
331
- pause: "Pauzeren",
332
- resume: "Hervatten",
333
- stop: "Stoppen",
334
- speaking: "Aan het voorlezen…",
335
- paused: "Gepauzeerd",
336
- charactersSelected: {
337
- one: "{count} teken geselecteerd",
338
- other: "{count} tekens geselecteerd",
339
- },
340
- rate: {
341
- slow: "Langzaam",
342
- slower: "Langzamer",
343
- normal: "Normaal",
344
- faster: "Sneller",
345
- fast: "Snel",
346
- veryFast: "Zeer snel",
347
- },
324
+ initFailed: "Voorlezen kon niet worden gestart. Probeer het opnieuw.",
348
325
  inline: {
349
326
  controlsA11y: "Voorleesknoppen",
350
327
  playbackSpeedA11y: "Voorleessnelheid",
351
328
  rewindA11y: "Terugspoelen",
352
329
  fastForwardA11y: "Vooruitspoelen",
353
330
  stopA11y: "Voorlezen stoppen",
354
- initializing: "Voorlezen wordt gestart",
355
- initFailed: "Voorlezen kon niet worden gestart. Probeer het opnieuw.",
356
331
  starting: "Voorlezen wordt gestart",
357
332
  started: "Voorlezen gestart",
358
333
  resumed: "Voorlezen hervat",
359
334
  pausedAnnouncement: "Voorlezen gepauzeerd",
360
335
  stopped: "Voorlezen gestopt",
361
336
  switchedSection: "Het voorlezen is naar een ander onderdeel gegaan",
337
+ nothingToRead: "Hier is niets om voor te lezen",
362
338
  startFailed: "Voorlezen kon niet worden gestart",
363
339
  skippedForward: "Vooruitgespoeld",
364
340
  skipForwardFailed: "Vooruitspoelen is niet gelukt",
@@ -438,6 +414,7 @@ const nlNL = {
438
414
  pnp: {
439
415
  title: "PNP-profiel",
440
416
  noAssessmentBound: "Geen toets gekoppeld",
417
+ noAssessmentBoundBody: "Profiel-, district- en afnamebeleid hebben niets om te lezen, dus alleen de requiredTools van een item kunnen een voorziening toekennen. Geef de toets door aan de assessment-eigenschap van de toolkit, of roep updateAssessment(...) aan op de toolkit-coordinator.",
441
418
  determinationReadOnly: "Vaststelling (alleen lezen)",
442
419
  toolsEditor: "Hulpmiddelen bewerken",
443
420
  enforcement: "PNP-handhaving",
@@ -450,6 +427,7 @@ const nlNL = {
450
427
  resolvedTools: "Toegekende hulpmiddelen (toolkit)",
451
428
  provenanceSummary: "Overzicht van herkomst van het hulpmiddelenbeleid",
452
429
  perToolDecisions: "Beslissingen per hulpmiddel",
430
+ policyDiagnostics: "Diagnose van het hulpmiddelenbeleid",
453
431
  profileReadOnly: "PNP-profiel (alleen lezen)",
454
432
  },
455
433
  tts: {
@@ -512,12 +490,39 @@ const nlNL = {
512
490
  previewEnterText: "Voer eerst voorbeeldtekst in.",
513
491
  previewUnavailable: "Een voorbeeld is niet mogelijk zolang deze dienst niet beschikbaar is.",
514
492
  browserSynthesisUnavailable: "Spraaksynthese van de browser is niet beschikbaar.",
515
- browserSynthesisEndedEarly: "De spraaksynthese van de browser stopte voordat de audio begon. Start de browser opnieuw en probeer het nog eens.",
516
- browserSynthesisQueueFailed: "De spraaksynthese van de browser kon het voorbeeldfragment niet in de wachtrij zetten.",
517
- browserPreviewFailed: "Het voorbeeld van de browserstem kon niet worden afgespeeld.",
518
493
  ssmlWordTrackingDisabled: "Bij een Google SSML-voorbeeld blijft de SSML uit de bron intact, waardoor woordmarkering is uitgeschakeld.",
519
494
  applyUnavailable: "Instellingen toepassen is niet mogelijk zolang deze dienst niet beschikbaar is.",
520
495
  coordinatorUnavailable: "De toolkitcoördinator is niet beschikbaar voor voorleesinstellingen.",
496
+ customProviderNotRegistered: "Aangepaste provider '{id}' is niet geregistreerd.",
497
+ customProviderNoConfig: "Aangepaste provider '{id}' gaf geen configuratie om toe te passen.",
498
+ httpError: "HTTP {status}: {message}",
499
+ unknownError: "Onbekende fout",
500
+ previewRequestFailed: "Het voorbeeldverzoek is mislukt ({status}).",
501
+ notAvailable: "n.v.t.",
502
+ voiceLocal: "lokaal",
503
+ voiceRemote: "extern",
504
+ voiceBrowserDefault: "browserstandaard",
505
+ browserAvailable: {
506
+ one: "Browserspraak beschikbaar ({count} stem gevonden).",
507
+ other: "Browserspraak beschikbaar ({count} stemmen gevonden).",
508
+ },
509
+ pollyAvailable: {
510
+ one: "AWS Polly beschikbaar ({count} passende stem, engine {engine}).",
511
+ other: "AWS Polly beschikbaar ({count} passende stemmen, engine {engine}).",
512
+ },
513
+ googleAvailable: {
514
+ one: "Google Cloud TTS beschikbaar ({count} passende stem).",
515
+ other: "Google Cloud TTS beschikbaar ({count} passende stemmen).",
516
+ },
517
+ headerRowReservation: "Rij in de itemkop gereserveerd: {state}",
518
+ speedOptionsHelp: "Vermenigvuldigers, gescheiden door komma's of puntkomma's. Neem 1 op voor Normaal; laat leeg om de snelheidsknoppen te verbergen.",
519
+ usingSelectedVoice: "Gekozen stem: {voice}",
520
+ autoVoice: "Beste beschikbare stem (automatisch): {voice}",
521
+ autoVoiceWaiting: "Beste beschikbare stem (automatisch): wachten op de stemmen van de browser.",
522
+ previewHintBrowserSsml: "SSML wordt niet ondersteund in het browservoorbeeld.",
523
+ previewHintGoogleSsml: "SSML blijft intact. Markering uitgeschakeld.",
524
+ previewHintCustom: "Markering actief wanneer de provider spraakmarkeringen teruggeeft.",
525
+ previewHintTracking: "Markering actief tijdens het afspelen van het voorbeeld.",
521
526
  },
522
527
  },
523
528
  };
@@ -43,12 +43,10 @@ export declare function detectBrowserLocale(): string;
43
43
  /**
44
44
  * The bundled provider.
45
45
  *
46
- * Retains the `SimpleI18n` name and the `I18nServiceApi` surface it published
47
- * before adoption. What changed is behaviour that had no caller: catalogs are
48
- * BCP-47 keyed and resolved through RFC 4647 lookup rather than string equality,
49
- * `dir`/`lang` are no longer written to `document.documentElement` (an embedded
50
- * player has no business writing the host page's root), and plural categories
51
- * come from `Intl.PluralRules` alone.
46
+ * Catalogs are BCP-47 keyed and resolved through RFC 4647 lookup, and plural
47
+ * categories come from `Intl.PluralRules`. It never writes `dir` or `lang` to
48
+ * `document.documentElement`: an embedded player does not own the host page's
49
+ * root.
52
50
  */
53
51
  export declare class SimpleI18n implements I18nServiceApi {
54
52
  /** Shared across instances and views: `Intl.PluralRules` is not cheap. */
@@ -138,11 +136,20 @@ export declare class SimpleI18n implements I18nServiceApi {
138
136
  private selectPluralCategory;
139
137
  private notify;
140
138
  }
139
+ /**
140
+ * The graceful default: an English-only provider, shared process-wide.
141
+ *
142
+ * `composition-context.md` requires a resolver to work with no publisher
143
+ * present, and this is that state. A tool mounted bare — in `print-player` or
144
+ * an authoring harness — resolves this and renders English rather than
145
+ * leaking raw message keys onto the screen. It carries no locale loader, so it
146
+ * pulls no catalog beyond the 5 KB English one already in the bundle.
147
+ */
141
148
  export declare function getDefaultI18n(): I18nServiceApi;
142
149
  /**
143
150
  * Resolve a component's interface-locale provider from a published context.
144
151
  *
145
- * Returns a **fresh** object on every call, and that is the whole point. A
152
+ * Returns a **fresh** object on every call. A
146
153
  * provider is mutable: `setLocale` swaps its catalog in place, so its identity is
147
154
  * unchanged before and after a locale load. A reactive `$derived` reading the
148
155
  * provider directly therefore never invalidates, and a label rendered while the
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @module @pie-players/pie-players-shared/i18n/provider
11
11
  */
12
- import { findBestLanguageMatch, normalizeLanguageTag, } from "./language-tags.js";
12
+ import { findBestLanguageMatch, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
13
13
  import enUS from "./messages/en-US.js";
14
14
  /** The locale every fallback chain terminates at. */
15
15
  export const DEFAULT_LOCALE = "en-US";
@@ -31,7 +31,6 @@ export function dynamicMessageKey(key) {
31
31
  * Consulted only where `Intl.Locale.prototype.textInfo` is unavailable — it is
32
32
  * the authoritative CLDR answer but shipped late in Safari, and an assessment
33
33
  * laid out left-to-right for an Arabic reader is not a graceful degradation.
34
- * Replaces a four-entry list that omitted every subtag below.
35
34
  */
36
35
  const RTL_LANGUAGES = new Set([
37
36
  "ar", // Arabic
@@ -101,12 +100,10 @@ export function detectBrowserLocale() {
101
100
  /**
102
101
  * The bundled provider.
103
102
  *
104
- * Retains the `SimpleI18n` name and the `I18nServiceApi` surface it published
105
- * before adoption. What changed is behaviour that had no caller: catalogs are
106
- * BCP-47 keyed and resolved through RFC 4647 lookup rather than string equality,
107
- * `dir`/`lang` are no longer written to `document.documentElement` (an embedded
108
- * player has no business writing the host page's root), and plural categories
109
- * come from `Intl.PluralRules` alone.
103
+ * Catalogs are BCP-47 keyed and resolved through RFC 4647 lookup, and plural
104
+ * categories come from `Intl.PluralRules`. It never writes `dir` or `lang` to
105
+ * `document.documentElement`: an embedded player does not own the host page's
106
+ * root.
110
107
  */
111
108
  export class SimpleI18n {
112
109
  /** Shared across instances and views: `Intl.PluralRules` is not cheap. */
@@ -121,7 +118,7 @@ export class SimpleI18n {
121
118
  config;
122
119
  constructor(config = {}) {
123
120
  this.config = { ...config };
124
- this.fallbackLocale = normalizeTag(config.fallbackLocale) || DEFAULT_LOCALE;
121
+ this.fallbackLocale = toLanguageTag(config.fallbackLocale) || DEFAULT_LOCALE;
125
122
  this.catalogs = new Map([[DEFAULT_LOCALE, enUS]]);
126
123
  this.customMessages = { ...(config.customMessages ?? {}) };
127
124
  this.loading = new Map();
@@ -160,11 +157,15 @@ export class SimpleI18n {
160
157
  // A locale we ship no catalog for is legitimate: the host may have
161
158
  // supplied its own messages for it. Honour the tag and let the
162
159
  // fallback chain cover whatever those messages omit.
163
- this.locale = normalizeTag(locale) || DEFAULT_LOCALE;
160
+ this.locale = toLanguageTag(locale) || DEFAULT_LOCALE;
164
161
  this.notify();
165
162
  return;
166
163
  }
167
- if (!this.catalogs.has(resolved)) {
164
+ // The loader is asked only for tags it declares. A tag that resolved through
165
+ // host messages alone has nothing to load, and is honoured like the
166
+ // unresolved case above.
167
+ if (!this.catalogs.has(resolved) &&
168
+ this.config.availableLocales?.includes(resolved)) {
168
169
  const inFlight = this.loading.get(resolved);
169
170
  if (inFlight) {
170
171
  await inFlight;
@@ -243,7 +244,7 @@ export class SimpleI18n {
243
244
  * a catalog.
244
245
  */
245
246
  addCustomMessages(locale, messages) {
246
- const tag = normalizeTag(locale);
247
+ const tag = toLanguageTag(locale);
247
248
  this.customMessages[tag] = deepMerge(this.customMessages[tag] ?? {}, messages);
248
249
  this.notify();
249
250
  }
@@ -256,7 +257,7 @@ export class SimpleI18n {
256
257
  * locales: the locale is per-view, the catalogs are per-provider.
257
258
  */
258
259
  withLocale(locale) {
259
- const resolved = this.resolveLocaleTag(locale) ?? normalizeTag(locale);
260
+ const resolved = this.resolveLocaleTag(locale) ?? toLanguageTag(locale);
260
261
  if (resolved === this.locale)
261
262
  return this;
262
263
  const view = new SimpleI18n({ ...this.config, locale: resolved });
@@ -320,9 +321,9 @@ export class SimpleI18n {
320
321
  this.catalogs.set(locale, await load(locale));
321
322
  }
322
323
  catch (error) {
323
- // A failed load is not fatal: the fallback chain still resolves every
324
- // key to English. Rethrowing here would take down a player over a
325
- // missing chunk.
324
+ // Rethrown with the locale named: `setLocale` rejects before switching
325
+ // (it assigns `this.locale` only after the load), so the previous locale
326
+ // stays active.
326
327
  throw new Error(`Failed to load i18n catalog for locale: ${locale}`, {
327
328
  cause: error,
328
329
  });
@@ -350,9 +351,9 @@ export class SimpleI18n {
350
351
  const node = this.lookupNode(key);
351
352
  if (typeof node === "string")
352
353
  return node;
353
- // A key landing on a namespace (`t("common")`) or on a plural group is a
354
- // miss, not a hit: returning the object would put one where the caller
355
- // expects a string, and interpolating it throws.
354
+ // A plural group resolves to its `other` form. A namespace (`t("common")`)
355
+ // is a miss: returning the object would put one where the caller expects
356
+ // a string, and interpolating it throws.
356
357
  if (node !== undefined && isPluralGroup(node))
357
358
  return node.other;
358
359
  return undefined;
@@ -375,9 +376,6 @@ export class SimpleI18n {
375
376
  listener();
376
377
  }
377
378
  }
378
- function normalizeTag(locale) {
379
- return locale ? locale.trim().replace(/_/g, "-") : "";
380
- }
381
379
  function readPath(source, key) {
382
380
  if (!source)
383
381
  return undefined;
@@ -415,17 +413,16 @@ function deepMerge(target, source) {
415
413
  }
416
414
  return result;
417
415
  }
416
+ let defaultProvider;
418
417
  /**
419
418
  * The graceful default: an English-only provider, shared process-wide.
420
419
  *
421
420
  * `composition-context.md` requires a resolver to work with no publisher
422
- * present, and this is that state. A tool mounted bare — in `print-player`, in
423
- * Studio preview, in an authoring harness — resolves this and renders English
424
- * rather than leaking raw message keys onto the screen. It carries no locale
425
- * loader, so it pulls no catalog beyond the 5 KB English one already in the
426
- * bundle.
421
+ * present, and this is that state. A tool mounted bare — in `print-player` or
422
+ * an authoring harness — resolves this and renders English rather than
423
+ * leaking raw message keys onto the screen. It carries no locale loader, so it
424
+ * pulls no catalog beyond the 5 KB English one already in the bundle.
427
425
  */
428
- let defaultProvider;
429
426
  export function getDefaultI18n() {
430
427
  if (!defaultProvider)
431
428
  defaultProvider = new SimpleI18n();
@@ -434,7 +431,7 @@ export function getDefaultI18n() {
434
431
  /**
435
432
  * Resolve a component's interface-locale provider from a published context.
436
433
  *
437
- * Returns a **fresh** object on every call, and that is the whole point. A
434
+ * Returns a **fresh** object on every call. A
438
435
  * provider is mutable: `setLocale` swaps its catalog in place, so its identity is
439
436
  * unchanged before and after a locale load. A reactive `$derived` reading the
440
437
  * provider directly therefore never invalidates, and a label rendered while the
@@ -52,11 +52,10 @@ type PluralCategoryKey = keyof PluralTranslation;
52
52
  * Dot-notation keys of a catalog shape.
53
53
  *
54
54
  * A plural group terminates the path at the group itself: `plural()` is called
55
- * with `tools.textToSpeech.charactersSelected`, never with
56
- * `…charactersSelected.other`. A group is recognized by every one of its keys
57
- * being a CLDR plural category — the containment has to run this way round,
58
- * because a group carrying only `one`/`other` does not contain the whole
59
- * category union.
55
+ * with `player.formative.triesLeft`, never with `…triesLeft.other`. A group is
56
+ * recognized by every one of its keys being a CLDR plural category — the
57
+ * containment has to run this way round, because a group carrying only
58
+ * `one`/`other` does not contain the whole category union.
60
59
  */
61
60
  type NestedKeys<T> = {
62
61
  [K in keyof T & string]: T[K] extends string ? K : keyof T[K] extends PluralCategoryKey ? K : T[K] extends object ? K | `${K}.${NestedKeys<T[K]>}` : K;
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export * from "./security/index.js";
6
6
  export * from "./loaders/index.js";
7
7
  export * from "./object/index.js";
8
8
  export * from "./pie/index.js";
9
- export type { AssessmentEntity, AssessmentItemRef, AssessmentSection, AdvancedItemConfig, ConfigEntity, ConfigResource, Env, FormativeDeliveryPolicy, FormativeItemPolicy, TimedMediaSectionData, ItemConfig, ItemEntity, ItemSession, OutcomeResponse, PassageEntity, PieController, PieContent, PieDefaultModel, PieItemElement, PieModel, PieUpdateSession, RubricBlock, TestPart, } from "./types/index.js";
9
+ export type { AssessmentEntity, AssessmentItemRef, AssessmentSection, AdvancedItemConfig, ConfigEntity, ConfigResource, Env, FormativeDeliveryPolicy, FormativeItemPolicy, TimedMediaSectionData, ItemConfig, ItemEntity, ItemSession, OutcomeResponse, PassageEntity, PieController, PieContent, PieDefaultModel, PieItemElement, PieModel, PieUpdateSession, ReferencedItemEntity, ReferencedPassageEntity, RubricBlock, TestPart, } from "./types/index.js";
10
10
  export { editorPostFix } from "./types/index.js";
11
11
  export * from "./ui/attribute-coercion.js";
12
12
  export * from "./ui/content-styles.js";
package/dist/index.js CHANGED
@@ -5,7 +5,6 @@ export * from "./player-strategy.js";
5
5
  export * from "./security/index.js";
6
6
  export * from "./loaders/index.js";
7
7
  export * from "./object/index.js";
8
- // Barrel export for PIE runtime utilities
9
8
  export * from "./pie/index.js";
10
9
  export { editorPostFix } from "./types/index.js";
11
10
  export * from "./ui/attribute-coercion.js";
@@ -37,17 +37,13 @@ export class BaseInstrumentationProvider {
37
37
  * @param attributes Contextual attributes
38
38
  */
39
39
  trackError(error, attributes) {
40
- // Guard: check if provider is ready
41
40
  if (!this.guardedOperation("trackError", error, attributes)) {
42
41
  return;
43
42
  }
44
- // Apply error filter
45
43
  if (!this.applyErrorFilter(error, attributes)) {
46
44
  return;
47
45
  }
48
- // Transform attributes
49
46
  const finalAttributes = this.transformAttributes(attributes);
50
- // Delegate to concrete provider
51
47
  try {
52
48
  this.doTrackError(error, finalAttributes);
53
49
  if (this.config?.debug) {
@@ -73,28 +69,22 @@ export class BaseInstrumentationProvider {
73
69
  * @param attributes Event attributes
74
70
  */
75
71
  trackEvent(eventName, attributes) {
76
- // Guard: check if provider is ready
77
72
  if (!this.guardedOperation("trackEvent", eventName, attributes)) {
78
73
  return;
79
74
  }
80
- // Apply event filter
81
75
  if (!this.applyEventFilter(eventName, attributes)) {
82
76
  return;
83
77
  }
84
- // Apply sampling
85
78
  if (!this.applySampling(eventName)) {
86
79
  return;
87
80
  }
88
- // Transform attributes
89
81
  let finalAttributes = this.transformAttributes(attributes);
90
- // Add timestamp if not present
91
82
  if (!finalAttributes.timestamp) {
92
83
  finalAttributes = {
93
84
  ...finalAttributes,
94
85
  timestamp: new Date().toISOString(),
95
86
  };
96
87
  }
97
- // Delegate to concrete provider
98
88
  try {
99
89
  this.doTrackEvent(eventName, finalAttributes);
100
90
  if (this.config?.debug) {
@@ -134,11 +124,9 @@ export class BaseInstrumentationProvider {
134
124
  * @param attributes Optional user attributes
135
125
  */
136
126
  setUserContext(userId, attributes) {
137
- // Guard: check if provider is ready
138
127
  if (!this.guardedOperation("setUserContext", userId, attributes)) {
139
128
  return;
140
129
  }
141
- // Delegate to concrete provider
142
130
  try {
143
131
  this.doSetUserContext(userId, attributes);
144
132
  if (this.config?.debug) {
@@ -158,11 +146,9 @@ export class BaseInstrumentationProvider {
158
146
  * @param attributes Attributes to set globally
159
147
  */
160
148
  setGlobalAttributes(attributes) {
161
- // Guard: check if provider is ready
162
149
  if (!this.guardedOperation("setGlobalAttributes", attributes)) {
163
150
  return;
164
151
  }
165
- // Delegate to concrete provider
166
152
  try {
167
153
  this.doSetGlobalAttributes(attributes);
168
154
  if (this.config?.debug) {
@@ -1,7 +1,5 @@
1
1
  /**
2
2
  * Shared loader configuration for PIE custom elements.
3
- *
4
- * Mirrors the `LoaderConfig` used by PIEOneer's custom element tags.
5
3
  */
6
4
  import type { InstrumentationProvider } from "./instrumentation/types.js";
7
5
  export type IifeBundleRetryConfig = {
@@ -1,7 +1,5 @@
1
1
  /**
2
2
  * Shared loader configuration for PIE custom elements.
3
- *
4
- * Mirrors the `LoaderConfig` used by PIEOneer's custom element tags.
5
3
  */
6
4
  export const DEFAULT_IIFE_BUNDLE_RETRY_CONFIG = {
7
5
  retryDelayMs: 3000,
@@ -128,6 +128,9 @@ const DEFAULT_LOAD_TIMEOUT_MS = DEFAULT_IIFE_BUNDLE_RETRY_CONFIG.timeoutMs;
128
128
  // Module-scoped in-flight cache. Key: backend signature + sorted elements.
129
129
  // Keeps concurrent identical requests collapsed to one backend call.
130
130
  const inFlightRequests = new Map();
131
+ // An ESM backend keeps page state that later loads build on (the import maps it
132
+ // injected, the shared dependency versions they fixed), so every load with the
133
+ // same config reuses one backend. IIFE backends are created per call.
131
134
  const resolvedEsmBackends = new Map();
132
135
  const resolvedBackendOverrides = new Map();
133
136
  /**
@@ -350,22 +353,26 @@ function backendKeyOf(backend) {
350
353
  }
351
354
  return "unknown";
352
355
  }
356
+ /**
357
+ * Plain data compares by value, functions and other objects by identity, so
358
+ * two configs get one key only when they behave the same.
359
+ */
353
360
  function fingerprintValue(value) {
354
361
  return JSON.stringify(normalizeForFingerprint(value, new Map()));
355
362
  }
356
363
  function normalizeForFingerprint(value, seen) {
357
364
  if (value === null || value === undefined)
358
365
  return value;
359
- const primitiveType = typeof value;
360
- if (primitiveType === "string" ||
361
- primitiveType === "number" ||
362
- primitiveType === "boolean") {
366
+ const valueType = typeof value;
367
+ if (valueType === "string" ||
368
+ valueType === "number" ||
369
+ valueType === "boolean") {
363
370
  return value;
364
371
  }
365
- if (primitiveType === "function") {
372
+ if (valueType === "function") {
366
373
  return { __functionRef: getFunctionRefId(value) };
367
374
  }
368
- if (primitiveType !== "object") {
375
+ if (valueType !== "object") {
369
376
  return String(value);
370
377
  }
371
378
  const objectValue = value;
@@ -73,4 +73,15 @@ export declare function resolveEsmRuntimeSupportUrl(packageVersion: string, opti
73
73
  cdnBaseUrl: string;
74
74
  cdnProvider?: EsmCdnProviderOption;
75
75
  }): string | undefined;
76
+ /**
77
+ * The npm root the ESM CDN the players load elements from serves raw package
78
+ * files under, `<root>/<package>@<version>/<path>`: the base URL for jsDelivr,
79
+ * raw.esm.sh for esm.sh, and for a custom provider whatever its
80
+ * `packageJsonUrl` puts before the package. `undefined` when that URL names
81
+ * no such root.
82
+ */
83
+ export declare function resolveEsmAssetRoot(options: {
84
+ cdnBaseUrl: string;
85
+ cdnProvider?: EsmCdnProviderOption;
86
+ }): string | undefined;
76
87
  export declare function pickElementClass(module: any, view: string): unknown;