first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

139
core/themes/stable9/js/tour.js Executable file
View File

@@ -0,0 +1,139 @@
/**
* @file
* Provides backwards compatibility for Tours that no longer use Joyride.
*/
((Drupal) => {
/**
* Converts the markup of a Shepherd tour tip to match Joyride.
*
* @param {Tour} shepherdTour
* A ShepherdJS tour object.
*
* @internal
*/
Drupal.tour.convertToJoyrideMarkup = (shepherdTour) => {
/**
* Changes the tag of an element.
*
* @param {HTMLElement} element
* The element that will have its tag changed.
* @param {string} tag
* The tag the element should be changed to.
*/
const changeTag = (element, tag) => {
if (element) {
const newTagElement = document.createElement(tag);
[...element.attributes].forEach((attr) => {
newTagElement.setAttribute(attr.name, attr.value);
});
newTagElement.innerHTML = element.innerHTML;
element.parentNode.replaceChild(newTagElement, element);
}
};
// Create variables for the elements that will be rearranged.
const shepherdElement = shepherdTour.currentStep.el;
const shepherdContent = shepherdElement.querySelector('.shepherd-content');
const shepherdCancel = shepherdElement.querySelector(
'.shepherd-cancel-icon',
);
const shepherdTitle = shepherdElement.querySelector('.shepherd-title');
const shepherdText = shepherdElement.querySelector('.shepherd-text');
const shepherdNext = shepherdElement.querySelector('footer .button');
const tourProgress = shepherdElement.querySelector('.tour-progress');
// Add attributes to the elements so they match what they were when Joyride
// was providing Tour functionality.
shepherdElement.classList.add('joyride-tip-guide');
shepherdContent.classList.add('joyride-content-wrapper');
shepherdNext.classList.add('joyride-next-tip');
shepherdNext.setAttribute('href', '#');
shepherdNext.setAttribute('role', 'button');
shepherdNext.removeAttribute('type');
shepherdCancel.classList.add('joyride-close-tip');
shepherdCancel.removeAttribute('type');
shepherdCancel.setAttribute('href', '#');
shepherdCancel.setAttribute('role', 'button');
shepherdElement.setAttribute(
'data-index',
shepherdTour.currentStep.options.index,
);
shepherdElement.querySelector('footer').remove();
// Rearrange elements so their structure matches Joyride's.
shepherdContent.insertBefore(shepherdTitle, shepherdContent.firstChild);
shepherdContent.insertBefore(tourProgress, shepherdText.nextSibling);
shepherdContent.appendChild(shepherdCancel);
shepherdContent.querySelector('.shepherd-header').remove();
shepherdContent.insertBefore(shepherdNext, tourProgress.nextSibling);
shepherdCancel.innerHTML = '<span aria-hidden="true">×</span>';
shepherdTitle.classList.add('tour-tip-label');
// Convert elements to use the tags they used in Joyride.
changeTag(shepherdTitle, 'h2');
// Remove the wrapper Shepherd adds for tip content.
shepherdText.outerHTML = shepherdText.innerHTML;
// Convert the next and cancel buttons to links so they match Joyride's
// markup. They must be re-queried as they were potentially moved elsewhere
// in the DOM.
changeTag(shepherdElement.querySelector('.joyride-close-tip'), 'a');
changeTag(shepherdElement.querySelector('.joyride-next-tip'), 'a');
// The arrow protruding from a tip pointing to the element it references.
const shepherdArrow = shepherdElement.querySelector('.shepherd-arrow');
if (shepherdArrow) {
shepherdArrow.classList.add('joyride-nub');
if (shepherdTour.currentStep.options.attachTo.on) {
// Shepherd's positions are opposite of Joyride's as they specify the
// tip location relative to the corresponding element as opposed to
// their location on the tip itself.
const stepToTipPosition = {
bottom: 'top',
top: 'bottom',
left: 'right',
right: 'left',
};
shepherdArrow.classList.add(
// Split at '-' as shepherd positioning accommodates dash-delimited
// secondary axis positioning.
// shepherdTour.currentStep.options.attachTo.on.split('-')[0]
stepToTipPosition[
// Split at '-' as shepherd positioning accommodates dash-delimited
// secondary axis positioning.
shepherdTour.currentStep.options.attachTo.on.split('-')[0]
],
);
}
changeTag(shepherdArrow, 'span');
} else {
// If there is no Shepherd arrow, there still needs to be markup for a
// non-displayed nub to match Joyride's markup.
const nub = document.createElement('span');
nub.classList.add('joyride-nub');
nub.setAttribute('style', 'display: none;');
shepherdElement.insertBefore(nub, shepherdElement.firstChild);
}
// When the next and cancel buttons were converted to links, they became
// new DOM elements that no longer have their associated event listeners.
// The events must be reintroduced here.
shepherdElement
.querySelector('.joyride-next-tip')
.addEventListener('click', (e) => {
e.preventDefault();
shepherdTour.next();
});
shepherdElement
.querySelector('.joyride-close-tip')
.addEventListener('click', (e) => {
e.preventDefault();
shepherdTour.cancel();
});
shepherdElement.querySelector('.joyride-next-tip').focus();
};
})(Drupal);

View File

@@ -0,0 +1,49 @@
/**
* @file
* Stable 9 theme overrides for user password forms.
*/
((Drupal) => {
/**
* Constructs a password confirm message element.
*
* @param {object} passwordSettings
* An object containing password related settings and translated text to
* display.
* @param {string} passwordSettings.confirmTitle
* The translated confirm description that labels the actual confirm text.
*
* @return {string}
* Markup for the password confirm message.
*/
Drupal.theme.passwordConfirmMessage = ({ confirmTitle }) => {
const confirmTextWrapper =
'<span data-drupal-selector="password-match-status-text"></span>';
return `<div aria-live="polite" aria-atomic="true" class="password-confirm-message js-password-confirm-message" data-drupal-selector="password-confirm-message">${confirmTitle} ${confirmTextWrapper}</div>`;
};
/**
* Constructs a password strength message.
*
* @param {object} passwordSettings
* An object containing password related settings and translated text to
* display.
* @param {string} passwordSettings.strengthTitle
* The title that precedes the strength text.
*
* @return {string}
* Markup for password strength message.
*/
Drupal.theme.passwordStrength = ({ strengthTitle }) => {
const strengthIndicator =
'<div class="password-strength__indicator js-password-strength__indicator" data-drupal-selector="password-strength-indicator"></div>';
const strengthText =
'<span class="password-strength__text js-password-strength__text" data-drupal-selector="password-strength-text"></span>';
return `
<div class="password-strength">
<div class="password-strength__meter" data-drupal-selector="password-strength-meter">${strengthIndicator}</div>
<div aria-live="polite" aria-atomic="true" class="password-strength__title">${strengthTitle} ${strengthText}</div>
</div>
`;
};
})(Drupal);