Checkpoint current UI and ink integration state
This commit is contained in:
@@ -13,7 +13,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
this.markupParser = null;
|
||||
this.container = null;
|
||||
this.choices = [];
|
||||
this.inputMode = 'text';
|
||||
this.inputMode = 'none';
|
||||
this.processState = document.documentElement.dataset.processState || 'loading';
|
||||
this.template = {
|
||||
cells: {
|
||||
@@ -52,7 +52,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
this.handleChoices(event.detail || []);
|
||||
});
|
||||
this.addEventListener(document, 'story:input-mode', (event) => {
|
||||
this.handleInputMode(event.detail || 'text');
|
||||
this.handleInputMode(event.detail || 'none');
|
||||
});
|
||||
this.addEventListener(document, 'story:process-state', (event) => {
|
||||
this.handleProcessState(event.detail?.state || 'ready');
|
||||
@@ -103,7 +103,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
}
|
||||
|
||||
handleInputMode(inputMode) {
|
||||
this.inputMode = ['text', 'choice', 'end'].includes(inputMode) ? inputMode : 'text';
|
||||
this.inputMode = ['text', 'choice', 'end', 'none'].includes(inputMode) ? inputMode : 'none';
|
||||
this.render();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
}
|
||||
|
||||
normalizeChoices(choices) {
|
||||
return this.assignLetters(choices.slice(0, 26).map((choice, order) => {
|
||||
return this.assignLetters(choices.slice(0, 36).map((choice, order) => {
|
||||
const tags = Array.isArray(choice.tags) ? choice.tags : [];
|
||||
const category = choice.category || this.getTagValue(tags, 'action');
|
||||
return {
|
||||
@@ -145,6 +145,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
text: String(choice.text || ''),
|
||||
tags,
|
||||
category,
|
||||
optional: this.hasTag(tags, 'optional'),
|
||||
letter: '',
|
||||
templateCell: this.getTemplateCell({ ...choice, tags, category })
|
||||
};
|
||||
@@ -152,7 +153,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
}
|
||||
|
||||
assignLetters(choices) {
|
||||
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||
const keySequence = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||
const reserved = new Set();
|
||||
|
||||
choices.forEach((choice) => {
|
||||
@@ -165,7 +166,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
.charAt(0)
|
||||
.toUpperCase();
|
||||
const reservedLetter = explicit || keyExplicit;
|
||||
if (alphabet.includes(reservedLetter) && !reserved.has(reservedLetter)) {
|
||||
if (keySequence.includes(reservedLetter) && !reserved.has(reservedLetter)) {
|
||||
choice.letter = reservedLetter;
|
||||
reserved.add(reservedLetter);
|
||||
}
|
||||
@@ -174,11 +175,11 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
let nextLetterIndex = 0;
|
||||
choices.forEach((choice) => {
|
||||
if (choice.letter) return;
|
||||
while (nextLetterIndex < alphabet.length && reserved.has(alphabet[nextLetterIndex])) {
|
||||
while (nextLetterIndex < keySequence.length && reserved.has(keySequence[nextLetterIndex])) {
|
||||
nextLetterIndex += 1;
|
||||
}
|
||||
if (nextLetterIndex < alphabet.length) {
|
||||
choice.letter = alphabet[nextLetterIndex];
|
||||
if (nextLetterIndex < keySequence.length) {
|
||||
choice.letter = keySequence[nextLetterIndex];
|
||||
reserved.add(choice.letter);
|
||||
nextLetterIndex += 1;
|
||||
}
|
||||
@@ -202,6 +203,11 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
return tag?.value;
|
||||
}
|
||||
|
||||
hasTag(tags, key) {
|
||||
const normalizedKey = String(key).toLowerCase();
|
||||
return Array.isArray(tags) && tags.some((item) => String(item?.key || '').toLowerCase() === normalizedKey);
|
||||
}
|
||||
|
||||
render() {
|
||||
this.setupContainer();
|
||||
if (!this.container) return;
|
||||
@@ -226,6 +232,7 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
this.choices.forEach((choice) => {
|
||||
const item = document.createElement('li');
|
||||
item.className = 'choice-list-item';
|
||||
item.classList.toggle('choice-optional', Boolean(choice.optional));
|
||||
item.dataset.choiceIndex = String(choice.index);
|
||||
item.dataset.choiceLetter = choice.letter;
|
||||
item.dataset.templateCell = choice.templateCell;
|
||||
@@ -233,7 +240,9 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'choice-button';
|
||||
button.innerHTML = `<kbd>${this.escapeHtml(choice.letter)}</kbd><span>${this.renderChoiceText(choice.text)}</span>`;
|
||||
const renderedText = this.renderChoiceText(choice.text);
|
||||
const displayKey = this.formatChoiceKey(choice.letter);
|
||||
button.innerHTML = `<kbd>${this.escapeHtml(displayKey)}</kbd><span>${choice.optional ? `<em>${renderedText}</em>` : renderedText}</span>`;
|
||||
button.addEventListener('click', () => this.selectChoice(choice.index));
|
||||
item.appendChild(button);
|
||||
list.appendChild(item);
|
||||
@@ -290,6 +299,11 @@ class ChoiceDisplayModule extends BaseModule {
|
||||
.replace(/\*([^*\s][^*]*?)\*/g, '<em>$1</em>')
|
||||
.replace(/_([^_\s][^_]*?)_/g, '<em>$1</em>');
|
||||
}
|
||||
|
||||
formatChoiceKey(key) {
|
||||
const value = String(key || '').trim().charAt(0);
|
||||
return /^[A-Z]$/.test(value) ? value.toLowerCase() : value;
|
||||
}
|
||||
}
|
||||
|
||||
const choiceDisplay = new ChoiceDisplayModule();
|
||||
|
||||
Reference in New Issue
Block a user