@pie-element/ebsr 14.0.1 → 14.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [14.1.0](https://github.com/pie-framework/pie-elements/compare/@pie-element/ebsr@14.0.1...@pie-element/ebsr@14.1.0) (2026-05-04)
7
+
8
+ ### Features
9
+
10
+ - **multiple-choice / ebsr:** handle logic for player heading attributes PIE-153 PIE-154 ([3530ce6](https://github.com/pie-framework/pie-elements/commit/3530ce6e6bad9f032ceb7c774cfdc66a43c1f252))
11
+
6
12
  ## [14.0.1](https://github.com/pie-framework/pie-elements/compare/@pie-element/ebsr@14.0.0...@pie-element/ebsr@14.0.1) (2026-04-28)
7
13
 
8
14
  **Note:** Version bump only for package @pie-element/ebsr
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [13.0.2](https://github.com/pie-framework/pie-elements/compare/@pie-element/ebsr-configure@13.0.1...@pie-element/ebsr-configure@13.0.2) (2026-05-04)
7
+
8
+ **Note:** Version bump only for package @pie-element/ebsr-configure
9
+
6
10
  ## [13.0.1](https://github.com/pie-framework/pie-elements/compare/@pie-element/ebsr-configure@13.0.0...@pie-element/ebsr-configure@13.0.1) (2026-04-28)
7
11
 
8
12
  **Note:** Version bump only for package @pie-element/ebsr-configure
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pie-element/ebsr-configure",
3
3
  "private": true,
4
- "version": "13.0.1",
4
+ "version": "13.0.2",
5
5
  "description": "",
6
6
  "main": "lib/index.js",
7
7
  "module": "src/index.js",
@@ -11,7 +11,7 @@
11
11
  "@emotion/style": "^0.8.0",
12
12
  "@mui/icons-material": "^7.3.4",
13
13
  "@mui/material": "^7.3.4",
14
- "@pie-element/multiple-choice": "^13.0.1",
14
+ "@pie-element/multiple-choice": "^13.1.0",
15
15
  "@pie-framework/pie-configure-events": "^1.2.0",
16
16
  "@pie-lib/config-ui": "13.0.0",
17
17
  "lodash-es": "^4.17.23",
package/lib/index.js CHANGED
@@ -27,6 +27,33 @@ const isSessionComplete = session => {
27
27
  return isNonEmptyArray(a) && isNonEmptyArray(b);
28
28
  };
29
29
  exports.isSessionComplete = isSessionComplete;
30
+ function getPlayerAttributes(element) {
31
+ const player = element.closest('pie-player') || element.closest('pie-item-player');
32
+ if (!player) {
33
+ return {
34
+ baseHeadingLevel: undefined,
35
+ includeSrHeading: true
36
+ };
37
+ }
38
+ const getRaw = (camelCaseName, hyphenatedName, allLowerName) => {
39
+ let raw = player[camelCaseName];
40
+
41
+ // fallback in case someone sets via HTML attribute manually
42
+ if (raw == null) {
43
+ raw = player.getAttribute(hyphenatedName) ?? player.getAttribute(allLowerName);
44
+ }
45
+ return raw;
46
+ };
47
+ const levelRaw = getRaw('baseHeadingLevel', 'base-heading-level', 'baseheadinglevel');
48
+ const level = parseInt(levelRaw, 10);
49
+ const baseHeadingLevel = Number.isFinite(level) && level >= 1 && level <= 6 ? level : undefined;
50
+ const srRaw = getRaw('includeSrHeading', 'include-sr-heading', 'includesrheading');
51
+ const includeSrHeading = srRaw == null ? true : srRaw !== false && srRaw !== 'false';
52
+ return {
53
+ baseHeadingLevel,
54
+ includeSrHeading
55
+ };
56
+ }
30
57
  class Ebsr extends HTMLElement {
31
58
  constructor() {
32
59
  super();
@@ -76,6 +103,15 @@ class Ebsr extends HTMLElement {
76
103
  mode,
77
104
  keyMode: this._model[key].choicePrefix
78
105
  };
106
+
107
+ // Parts of an EBSR item should not render their own SR headings —
108
+ // the EBSR element itself provides the item-level heading.
109
+ const {
110
+ includeSrHeading,
111
+ baseHeadingLevel
112
+ } = getPlayerAttributes(this);
113
+ part.includeSrHeading = includeSrHeading;
114
+ part.baseHeadingLevel = baseHeadingLevel !== undefined ? Math.min(6, baseHeadingLevel + (includeSrHeading ? 1 : 0)) : undefined;
79
115
  }
80
116
  }
81
117
  setPartSession(part, key) {
@@ -105,14 +141,39 @@ class Ebsr extends HTMLElement {
105
141
  }
106
142
  connectedCallback() {
107
143
  this._render();
144
+ this._initPlayerObserver();
108
145
  this.addEventListener(SESSION_CHANGED, this.onSessionUpdated);
109
146
  }
110
147
  disconnectedCallback() {
148
+ this._disconnectPlayerObserver();
111
149
  this.removeEventListener(SESSION_CHANGED, this.onSessionUpdated);
112
150
  }
151
+ _initPlayerObserver() {
152
+ const player = this.closest('pie-player') || this.closest('pie-item-player');
153
+ if (!player) return;
154
+ this._playerObserver = new MutationObserver(() => {
155
+ this._render();
156
+ });
157
+ this._playerObserver.observe(player, {
158
+ attributes: true,
159
+ attributeFilter: ['base-heading-level', 'baseheadinglevel', 'include-sr-heading', 'includesrheading']
160
+ });
161
+ }
162
+ _disconnectPlayerObserver() {
163
+ if (this._playerObserver) {
164
+ this._playerObserver.disconnect();
165
+ this._playerObserver = null;
166
+ }
167
+ }
113
168
  _render() {
114
169
  this.ariaLabel = 'Two-Part Question';
115
170
  this.role = 'region';
171
+ const {
172
+ baseHeadingLevel: ebsrLevel,
173
+ includeSrHeading
174
+ } = getPlayerAttributes(this);
175
+ const headingTag = ebsrLevel ? `h${Math.min(6, ebsrLevel)}` : 'h2';
176
+ const srHeading = includeSrHeading ? `<${headingTag} class="srOnly">Two-Part Question</${headingTag}>` : '';
116
177
  this.innerHTML = `
117
178
  <style>
118
179
  .srOnly {
@@ -127,7 +188,7 @@ class Ebsr extends HTMLElement {
127
188
  }
128
189
  ${this._model?.extraCSSRules?.rules}
129
190
  </style>
130
- <h2 class="srOnly">Two-Part Question</h2>
191
+ ${srHeading}
131
192
  <${MC_TAG_NAME} id="a"></${MC_TAG_NAME}>
132
193
  <${MC_TAG_NAME} id="b"></${MC_TAG_NAME}>
133
194
  `;
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_piePlayerEvents","require","_multipleChoice","_interopRequireDefault","_lodashEs","_debug","SESSION_CHANGED","SessionChangedEvent","TYPE","MC_TAG_NAME","log","debug","EbsrMC","MultipleChoice","defineMultipleChoice","customElements","get","define","isNonEmptyArray","a","Array","isArray","length","isSessionComplete","session","b","exports","Ebsr","HTMLElement","constructor","_defineProperty2","default","e","target","preventDefault","stopImmediatePropagation","id","getAttribute","key","toUpperCase","update","_model","dispatchSessionChanged","srcElement","_session","model","m","whenDefined","then","setPartModel","partA","partB","s","setPartSession","part","mode","keyMode","choicePrefix","value","partSession","complete","dispatchEvent","tagName","toLowerCase","querySelector","connectedCallback","_render","addEventListener","onSessionUpdated","disconnectedCallback","removeEventListener","ariaLabel","role","innerHTML","extraCSSRules","rules"],"sources":["../src/index.js"],"sourcesContent":["import { SessionChangedEvent } from '@pie-framework/pie-player-events';\nimport MultipleChoice from '@pie-element/multiple-choice';\nimport { get } from 'lodash-es';\nimport debug from 'debug';\n\nconst SESSION_CHANGED = SessionChangedEvent.TYPE;\nconst MC_TAG_NAME = 'ebsr-multiple-choice';\nconst log = debug('pie-elements:ebsr');\n\nclass EbsrMC extends MultipleChoice {}\n\nconst defineMultipleChoice = () => {\n if (!customElements.get(MC_TAG_NAME)) {\n customElements.define(MC_TAG_NAME, EbsrMC);\n }\n};\n\ndefineMultipleChoice();\n\nconst isNonEmptyArray = (a) => Array.isArray(a) && a.length > 0;\n\nexport const isSessionComplete = (session) => {\n const a = get(session, 'value.partA.value');\n const b = get(session, 'value.partB.value');\n\n return isNonEmptyArray(a) && isNonEmptyArray(b);\n};\n\nexport default class Ebsr extends HTMLElement {\n constructor() {\n super();\n this._model = {};\n this._session = {};\n }\n\n onSessionUpdated = (e) => {\n if (e.target === this) {\n return;\n }\n\n e.preventDefault();\n e.stopImmediatePropagation();\n\n const id = e.target.getAttribute('id');\n\n if (id) {\n const key = `part${id.toUpperCase()}`;\n\n if (e.update) {\n this._model[key] = e.update;\n }\n //TODO: accessing a private property here. The session event should contain the update in future to prevent this.\n this.dispatchSessionChanged(e.srcElement._session, key);\n }\n };\n\n set model(m) {\n this._model = m;\n\n customElements.whenDefined(MC_TAG_NAME).then(() => {\n this.setPartModel(this.partA, 'partA');\n this.setPartModel(this.partB, 'partB');\n });\n }\n\n set session(s) {\n this._session = s;\n\n customElements.whenDefined(MC_TAG_NAME).then(() => {\n this.setPartSession(this.partA, 'partA');\n this.setPartSession(this.partB, 'partB');\n });\n }\n\n get session() {\n return this._session;\n }\n\n setPartModel(part, key) {\n if (this._model && this._model[key] && part) {\n const { mode } = this._model;\n\n part.model = {\n ...this._model[key],\n mode,\n keyMode: this._model[key].choicePrefix,\n };\n }\n }\n\n setPartSession(part, key) {\n if (this._session && this._model && part) {\n const { value } = this._session;\n part.session = value && value[key] ? value[key] : { id: key };\n }\n }\n\n dispatchSessionChanged(partSession, key) {\n this._session.value = {\n ...this._session.value,\n [key]: partSession,\n };\n\n log('[onSessionChanged] session: ', this._session);\n const complete = isSessionComplete(this._session);\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), complete));\n }\n\n get partA() {\n return this.querySelector(`${MC_TAG_NAME}#a`);\n }\n\n get partB() {\n return this.querySelector(`${MC_TAG_NAME}#b`);\n }\n\n connectedCallback() {\n this._render();\n this.addEventListener(SESSION_CHANGED, this.onSessionUpdated);\n }\n\n disconnectedCallback() {\n this.removeEventListener(SESSION_CHANGED, this.onSessionUpdated);\n }\n\n _render() {\n this.ariaLabel = 'Two-Part Question';\n this.role = 'region';\n this.innerHTML = `\n <style>\n .srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n left: -10000px;\n top: auto;\n }\n ${this._model?.extraCSSRules?.rules}\n </style>\n <h2 class=\"srOnly\">Two-Part Question</h2>\n <${MC_TAG_NAME} id=\"a\"></${MC_TAG_NAME}>\n <${MC_TAG_NAME} id=\"b\"></${MC_TAG_NAME}>\n `;\n\n // when item is re-rendered (due to connectedCallback), if the custom element is already defined,\n // we need to set the model and session, otherwise the setters are not reached again\n if (customElements.get(MC_TAG_NAME)) {\n this.setPartModel(this.partA, 'partA');\n this.setPartModel(this.partB, 'partB');\n this.setPartSession(this.partA, 'partA');\n this.setPartSession(this.partB, 'partB');\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_piePlayerEvents","require","_multipleChoice","_interopRequireDefault","_lodashEs","_debug","SESSION_CHANGED","SessionChangedEvent","TYPE","MC_TAG_NAME","log","debug","EbsrMC","MultipleChoice","defineMultipleChoice","customElements","get","define","isNonEmptyArray","a","Array","isArray","length","isSessionComplete","session","b","exports","getPlayerAttributes","element","player","closest","baseHeadingLevel","undefined","includeSrHeading","getRaw","camelCaseName","hyphenatedName","allLowerName","raw","getAttribute","levelRaw","level","parseInt","Number","isFinite","srRaw","Ebsr","HTMLElement","constructor","_defineProperty2","default","e","target","preventDefault","stopImmediatePropagation","id","key","toUpperCase","update","_model","dispatchSessionChanged","srcElement","_session","model","m","whenDefined","then","setPartModel","partA","partB","s","setPartSession","part","mode","keyMode","choicePrefix","Math","min","value","partSession","complete","dispatchEvent","tagName","toLowerCase","querySelector","connectedCallback","_render","_initPlayerObserver","addEventListener","onSessionUpdated","disconnectedCallback","_disconnectPlayerObserver","removeEventListener","_playerObserver","MutationObserver","observe","attributes","attributeFilter","disconnect","ariaLabel","role","ebsrLevel","headingTag","srHeading","innerHTML","extraCSSRules","rules"],"sources":["../src/index.js"],"sourcesContent":["import { SessionChangedEvent } from '@pie-framework/pie-player-events';\nimport MultipleChoice from '@pie-element/multiple-choice';\nimport { get } from 'lodash-es';\nimport debug from 'debug';\n\nconst SESSION_CHANGED = SessionChangedEvent.TYPE;\nconst MC_TAG_NAME = 'ebsr-multiple-choice';\nconst log = debug('pie-elements:ebsr');\n\nclass EbsrMC extends MultipleChoice {}\n\nconst defineMultipleChoice = () => {\n if (!customElements.get(MC_TAG_NAME)) {\n customElements.define(MC_TAG_NAME, EbsrMC);\n }\n};\n\ndefineMultipleChoice();\n\nconst isNonEmptyArray = (a) => Array.isArray(a) && a.length > 0;\n\nexport const isSessionComplete = (session) => {\n const a = get(session, 'value.partA.value');\n const b = get(session, 'value.partB.value');\n\n return isNonEmptyArray(a) && isNonEmptyArray(b);\n};\n\nfunction getPlayerAttributes(element) {\n const player =\n element.closest('pie-player') ||\n element.closest('pie-item-player');\n\n if (!player) {\n return { baseHeadingLevel: undefined, includeSrHeading: true };\n }\n\n const getRaw = (camelCaseName, hyphenatedName, allLowerName) => {\n let raw = player[camelCaseName];\n\n // fallback in case someone sets via HTML attribute manually\n if (raw == null) {\n raw =\n player.getAttribute(hyphenatedName) ??\n player.getAttribute(allLowerName);\n }\n\n return raw;\n };\n\n const levelRaw = getRaw('baseHeadingLevel', 'base-heading-level', 'baseheadinglevel');\n const level = parseInt(levelRaw, 10);\n const baseHeadingLevel = Number.isFinite(level) && level >= 1 && level <= 6 ? level : undefined;\n\n const srRaw = getRaw('includeSrHeading', 'include-sr-heading', 'includesrheading');\n const includeSrHeading = srRaw == null ? true : srRaw !== false && srRaw !== 'false';\n\n return { baseHeadingLevel, includeSrHeading };\n}\n\nexport default class Ebsr extends HTMLElement {\n constructor() {\n super();\n this._model = {};\n this._session = {};\n }\n\n onSessionUpdated = (e) => {\n if (e.target === this) {\n return;\n }\n\n e.preventDefault();\n e.stopImmediatePropagation();\n\n const id = e.target.getAttribute('id');\n\n if (id) {\n const key = `part${id.toUpperCase()}`;\n\n if (e.update) {\n this._model[key] = e.update;\n }\n //TODO: accessing a private property here. The session event should contain the update in future to prevent this.\n this.dispatchSessionChanged(e.srcElement._session, key);\n }\n };\n\n set model(m) {\n this._model = m;\n\n customElements.whenDefined(MC_TAG_NAME).then(() => {\n this.setPartModel(this.partA, 'partA');\n this.setPartModel(this.partB, 'partB');\n });\n }\n\n set session(s) {\n this._session = s;\n\n customElements.whenDefined(MC_TAG_NAME).then(() => {\n this.setPartSession(this.partA, 'partA');\n this.setPartSession(this.partB, 'partB');\n });\n }\n\n get session() {\n return this._session;\n }\n\n setPartModel(part, key) {\n if (this._model && this._model[key] && part) {\n const { mode } = this._model;\n\n part.model = {\n ...this._model[key],\n mode,\n keyMode: this._model[key].choicePrefix,\n };\n\n // Parts of an EBSR item should not render their own SR headings —\n // the EBSR element itself provides the item-level heading.\n const { includeSrHeading, baseHeadingLevel } = getPlayerAttributes(this);\n part.includeSrHeading = includeSrHeading;\n part.baseHeadingLevel = baseHeadingLevel !== undefined ? Math.min(6, baseHeadingLevel + (includeSrHeading ? 1 : 0)) : undefined;\n }\n }\n\n setPartSession(part, key) {\n if (this._session && this._model && part) {\n const { value } = this._session;\n part.session = value && value[key] ? value[key] : { id: key };\n }\n }\n\n dispatchSessionChanged(partSession, key) {\n this._session.value = {\n ...this._session.value,\n [key]: partSession,\n };\n\n log('[onSessionChanged] session: ', this._session);\n const complete = isSessionComplete(this._session);\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), complete));\n }\n\n get partA() {\n return this.querySelector(`${MC_TAG_NAME}#a`);\n }\n\n get partB() {\n return this.querySelector(`${MC_TAG_NAME}#b`);\n }\n\n connectedCallback() {\n this._render();\n this._initPlayerObserver();\n this.addEventListener(SESSION_CHANGED, this.onSessionUpdated);\n }\n\n disconnectedCallback() {\n this._disconnectPlayerObserver();\n this.removeEventListener(SESSION_CHANGED, this.onSessionUpdated);\n }\n\n _initPlayerObserver() {\n const player = this.closest('pie-player') || this.closest('pie-item-player');\n if (!player) return;\n\n this._playerObserver = new MutationObserver(() => {\n this._render();\n });\n this._playerObserver.observe(player, {\n attributes: true,\n attributeFilter: ['base-heading-level', 'baseheadinglevel', 'include-sr-heading', 'includesrheading'],\n });\n }\n\n _disconnectPlayerObserver() {\n if (this._playerObserver) {\n this._playerObserver.disconnect();\n this._playerObserver = null;\n }\n }\n\n _render() {\n this.ariaLabel = 'Two-Part Question';\n this.role = 'region';\n\n const { baseHeadingLevel: ebsrLevel, includeSrHeading } = getPlayerAttributes(this);\n const headingTag = ebsrLevel ? `h${Math.min(6, ebsrLevel)}` : 'h2';\n const srHeading = includeSrHeading ? `<${headingTag} class=\"srOnly\">Two-Part Question</${headingTag}>` : '';\n\n this.innerHTML = `\n <style>\n .srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n left: -10000px;\n top: auto;\n }\n ${this._model?.extraCSSRules?.rules}\n </style>\n ${srHeading}\n <${MC_TAG_NAME} id=\"a\"></${MC_TAG_NAME}>\n <${MC_TAG_NAME} id=\"b\"></${MC_TAG_NAME}>\n `;\n\n // when item is re-rendered (due to connectedCallback), if the custom element is already defined,\n // we need to set the model and session, otherwise the setters are not reached again\n if (customElements.get(MC_TAG_NAME)) {\n this.setPartModel(this.partA, 'partA');\n this.setPartModel(this.partB, 'partB');\n this.setPartSession(this.partA, 'partA');\n this.setPartSession(this.partB, 'partB');\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}