Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/common-cougars-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@pie-element/multiple-choice": patch
---

test multiple-choice release flow
84 changes: 84 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"mode": "pre",
"tag": "next",
"initialVersions": {
"@pie-element/element-demo": "0.1.1",
"esm-player-test": "1.0.0",
"@pie-element/core": "0.1.0",
"@pie-element/element-player": "0.1.1",
"@pie-element/element-theme": "0.1.0",
"@pie-element/element-theme-daisyui": "0.1.0",
"@pie-element/categorize": "13.0.1",
"@pie-element/charting": "12.0.1",
"@pie-element/complex-rubric": "7.0.1",
"@pie-element/drag-in-the-blank": "10.0.1",
"@pie-element/drawing-response": "12.0.1",
"@pie-element/ebsr": "14.1.0",
"@pie-element/explicit-constructed-response": "11.0.1",
"@pie-element/extended-text-entry": "15.0.1",
"@pie-element/fraction-model": "6.0.1",
"@pie-element/graphing": "10.0.1",
"@pie-element/graphing-solution-set": "6.0.1",
"@pie-element/hotspot": "11.0.1",
"@pie-element/image-cloze-association": "10.0.1",
"@pie-element/inline-dropdown": "10.0.1",
"@pie-element/likert": "4.0.1",
"@pie-element/match": "12.0.1",
"@pie-element/match-list": "7.0.1",
"@pie-element/math-inline": "0.1.0",
"@pie-element/math-templated": "0.1.0",
"@pie-element/matrix": "4.0.1",
"@pie-element/multi-trait-rubric": "8.0.1",
"@pie-element/multiple-choice": "13.1.0",
"@pie-element/number-line": "13.0.1",
"@pie-element/passage": "7.0.1",
"@pie-element/placement-ordering": "14.0.1",
"@pie-element/rubric": "8.0.1",
"@pie-element/select-text": "13.0.1",
"@pie-element/mc-populated-blank": "0.2.10",
"@pie-element/simple-cloze": "0.1.3",
"@pie-element/venn-classification": "0.1.0",
"@pie-lib/categorize": "2.0.1",
"@pie-lib/charting": "7.0.1",
"@pie-lib/config-ui": "13.0.1",
"@pie-lib/controller-utils": "2.0.1",
"@pie-lib/correct-answer-toggle": "4.0.1",
"@pie-lib/drag": "4.0.1",
"@pie-lib/editable-html-tip-tap": "2.0.1",
"@pie-lib/graphing": "4.0.2",
"@pie-lib/graphing-solution-set": "4.0.1",
"@pie-lib/graphing-utils": "3.0.1",
"@pie-lib/icons": "4.0.1",
"@pie-lib/mask-markup": "3.0.1",
"@pie-lib/math-input": "0.1.0",
"@pie-lib/math-rendering": "0.1.0",
"@pie-lib/math-toolbar": "3.0.1",
"@pie-lib/plot": "4.0.1",
"@pie-lib/render-ui": "6.0.1",
"@pie-lib/rubric": "2.0.1",
"@pie-lib/style-utils": "2.0.1",
"@pie-lib/test-utils": "2.0.1",
"@pie-lib/text-select": "3.0.1",
"@pie-lib/tools": "2.0.1",
"@pie-lib/translator": "4.0.1",
"@pie-lib/delivery-events-svelte": "0.1.0",
"@pie-lib/editable-html-tiptap-svelte": "0.1.2",
"@pie-lib/math-input-svelte": "0.1.0",
"@pie-lib/styling-svelte": "0.1.2",
"@pie-element/print-player": "1.0.1",
"@pie-element/element-bundler": "0.1.1",
"@pie-element/bundler-shared": "0.1.1",
"@pie-element/shared-configure-events": "0.1.0",
"@pie-element/shared-controller-utils": "0.1.0",
"@pie-element/shared-feedback": "0.1.0",
"@pie-element/shared-math-rendering-mathjax": "0.1.0",
"@pie-element/shared-player-events": "0.1.0",
"@pie-element/shared-test-utils": "0.1.0",
"@pie-element/shared-theming": "0.1.0",
"@pie-element/shared-theming-mui": "0.1.0",
"@pie-element/shared-types": "0.1.0",
"@pie-element/shared-utils": "0.1.0",
"@pie-element/cli": "0.1.1"
},
"changesets": []
}
6 changes: 3 additions & 3 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/elements-react/ebsr/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pie-element/ebsr",
"version": "14.0.1",
"version": "14.1.0",
"description": "",
"dependencies": {
"@pie-element/multiple-choice": "workspace:*",
Expand Down
67 changes: 66 additions & 1 deletion packages/elements-react/ebsr/src/delivery/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,38 @@ export const isSessionComplete = (session) => {
return isNonEmptyArray(a) && isNonEmptyArray(b);
};

function getPlayerAttributes(element) {
const player =
element.closest('pie-player') ||
element.closest('pie-item-player');

if (!player) {
return { baseHeadingLevel: undefined, includeSrHeading: true };
}

const getRaw = (camelCaseName, hyphenatedName, allLowerName) => {
let raw = player[camelCaseName];

// fallback in case someone sets via HTML attribute manually
if (raw == null) {
raw =
player.getAttribute(hyphenatedName) ??
player.getAttribute(allLowerName);
}

return raw;
};

const levelRaw = getRaw('baseHeadingLevel', 'base-heading-level', 'baseheadinglevel');
const level = parseInt(levelRaw, 10);
const baseHeadingLevel = Number.isFinite(level) && level >= 1 && level <= 6 ? level : undefined;

const srRaw = getRaw('includeSrHeading', 'include-sr-heading', 'includesrheading');
const includeSrHeading = srRaw == null ? true : srRaw !== false && srRaw !== 'false';

return { baseHeadingLevel, includeSrHeading };
}

export default class Ebsr extends HTMLElement {
constructor() {
super();
Expand Down Expand Up @@ -95,6 +127,12 @@ export default class Ebsr extends HTMLElement {
mode,
keyMode: this._model[key].choicePrefix,
};

// Parts of an EBSR item should not render their own SR headings —
// the EBSR element itself provides the item-level heading.
const { includeSrHeading, baseHeadingLevel } = getPlayerAttributes(this);
part.includeSrHeading = includeSrHeading;
part.baseHeadingLevel = baseHeadingLevel !== undefined ? Math.min(6, baseHeadingLevel + (includeSrHeading ? 1 : 0)) : undefined;
}
}

Expand Down Expand Up @@ -126,16 +164,43 @@ export default class Ebsr extends HTMLElement {

connectedCallback() {
this._render();
this._initPlayerObserver();
this.addEventListener(SESSION_CHANGED, this.onSessionUpdated);
}

disconnectedCallback() {
this._disconnectPlayerObserver();
this.removeEventListener(SESSION_CHANGED, this.onSessionUpdated);
}

_initPlayerObserver() {
const player = this.closest('pie-player') || this.closest('pie-item-player');
if (!player) return;

this._playerObserver = new MutationObserver(() => {
this._render();
});
this._playerObserver.observe(player, {
attributes: true,
attributeFilter: ['base-heading-level', 'baseheadinglevel', 'include-sr-heading', 'includesrheading'],
});
}

_disconnectPlayerObserver() {
if (this._playerObserver) {
this._playerObserver.disconnect();
this._playerObserver = null;
}
}

_render() {
this.ariaLabel = 'Two-Part Question';
this.role = 'region';

const { baseHeadingLevel: ebsrLevel, includeSrHeading } = getPlayerAttributes(this);
const headingTag = ebsrLevel ? `h${Math.min(6, ebsrLevel)}` : 'h2';
const srHeading = includeSrHeading ? `<${headingTag} class="srOnly">Two-Part Question</${headingTag}>` : '';

this.innerHTML = `
<style>
.srOnly {
Expand All @@ -150,7 +215,7 @@ export default class Ebsr extends HTMLElement {
}
${this._model?.extraCSSRules?.rules}
</style>
<h2 class="srOnly">Two-Part Question</h2>
${srHeading}
<${MC_TAG_NAME} id="a"></${MC_TAG_NAME}>
<${MC_TAG_NAME} id="b"></${MC_TAG_NAME}>
`;
Expand Down
2 changes: 1 addition & 1 deletion packages/elements-react/multiple-choice/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pie-element/multiple-choice",
"version": "13.0.1",
"version": "13.1.0",
"description": "React implementation of multiple-choice element synced from pie-elements",
"dependencies": {
"@emotion/react": "^11.14.0",
Expand Down
78 changes: 78 additions & 0 deletions packages/elements-react/multiple-choice/src/delivery/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,51 @@ export const isComplete = (session, model, audioComplete, elementContext) => {
return true;
};

function getPlayerAttributes(element) {
const player =
element.closest('pie-player') ||
element.closest('pie-item-player');

if (!player) {
return { baseHeadingLevel: undefined, includeSrHeading: true };
}

const getRaw = (camelCaseName, hyphenatedName, allLowerName) => {
let raw = player[camelCaseName];

// fallback in case someone sets via HTML attribute manually
if (raw == null) {
raw =
player.getAttribute(hyphenatedName) ??
player.getAttribute(allLowerName);
}

return raw;
};

const levelRaw = getRaw('baseHeadingLevel', 'base-heading-level', 'baseheadinglevel');
const level = parseInt(levelRaw, 10);
const baseHeadingLevel = Number.isFinite(level) && level >= 1 && level <= 6 ? level : undefined;

const srRaw = getRaw('includeSrHeading', 'include-sr-heading', 'includesrheading');
const includeSrHeading = srRaw == null ? true : srRaw !== false && srRaw !== 'false';

console.log('getPlayerAttributes', { baseHeadingLevel, includeSrHeading });
return { baseHeadingLevel, includeSrHeading };
}

// Resolves heading attributes for a custom element, preferring explicit instance
// properties (set by a parent element such as EBSR) over player-level attributes.
function resolveHeadingProps(element) {
const fromPlayer = getPlayerAttributes(element);

console.log('element._baseHeadingLevel', element._baseHeadingLevel, 'element._includeSrHeading', element._includeSrHeading);
return {
baseHeadingLevel: element._baseHeadingLevel !== undefined ? element._baseHeadingLevel : fromPlayer.baseHeadingLevel,
includeSrHeading: element._includeSrHeading !== undefined ? element._includeSrHeading : fromPlayer.includeSrHeading,
};
}

export default class MultipleChoice extends HTMLElement {
constructor() {
super();
Expand All @@ -105,6 +150,7 @@ export default class MultipleChoice extends HTMLElement {
options: this._options,
onChoiceChanged: this._onChange.bind(this),
onShowCorrectToggle: this.onShowCorrectToggle.bind(this),
...resolveHeadingProps(this),
});

//TODO: aria-label is set in the _rerender because we need to change it when the model.choiceMode is updated. Consider revisiting the placement of the aria-label setting in the _rerender
Expand Down Expand Up @@ -220,6 +266,16 @@ export default class MultipleChoice extends HTMLElement {
this._rerender();
}

set baseHeadingLevel(level) {
this._baseHeadingLevel = level;
this._rerender();
}

set includeSrHeading(value) {
this._includeSrHeading = value;
this._rerender();
}

set session(s) {
this._session = s;
this._rerender();
Expand Down Expand Up @@ -262,6 +318,7 @@ export default class MultipleChoice extends HTMLElement {

connectedCallback() {
this._initMathObserver();
this._initPlayerObserver();
this._rerender();

// Observation: audio in Chrome will have the autoplay attribute,
Expand Down Expand Up @@ -350,8 +407,29 @@ export default class MultipleChoice extends HTMLElement {
}
}

_initPlayerObserver() {
const player = this.closest('pie-player') || this.closest('pie-item-player');
if (!player) return;

this._playerObserver = new MutationObserver(() => {
this._rerender();
});
this._playerObserver.observe(player, {
attributes: true,
attributeFilter: ['base-heading-level', 'baseheadinglevel', 'include-sr-heading', 'includesrheading'],
});
}

_disconnectPlayerObserver() {
if (this._playerObserver) {
this._playerObserver.disconnect();
this._playerObserver = null;
}
}

disconnectedCallback() {
this._disconnectMathObserver();
this._disconnectPlayerObserver();
if (this._keyboardEventsEnabled) {
window.removeEventListener('keydown', this._boundHandleKeyDown);
this._keyboardEventsEnabled = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class Main extends React.Component {
names: PropTypes.arrayOf(PropTypes.string),
rules: PropTypes.string,
}),
baseHeadingLevel: PropTypes.number,
includeSrHeading: PropTypes.bool,
};

static defaultProps = {
Expand All @@ -60,7 +62,7 @@ class Main extends React.Component {
};

render() {
const { model, onChoiceChanged, session, onShowCorrectToggle, options } = this.props;
const { model, onChoiceChanged, session, onShowCorrectToggle, options, baseHeadingLevel, includeSrHeading } = this.props;
const { extraCSSRules, fontSizeFactor } = model;

// model.partLabel is a property used for ebsr
Expand All @@ -72,6 +74,8 @@ class Main extends React.Component {
session={session}
onChoiceChanged={onChoiceChanged}
onShowCorrectToggle={onShowCorrectToggle}
baseHeadingLevel={baseHeadingLevel}
includeSrHeading={includeSrHeading}
/>
</PreviewLayout>
);
Expand Down
Loading
Loading