New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@microsoft/atlas-js

Package Overview
Dependencies
Maintainers
4
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@microsoft/atlas-js - npm Package Compare versions

Comparing version 1.3.0 to 1.4.0

15

dist/elements/form-behavior.d.ts

@@ -0,1 +1,10 @@

export declare const defaultMessageStrings: {
contentHasChanged: string;
inputMaxLength: string;
inputMinLength: string;
inputRequired: string;
pleaseFixTheFollowingIssues: string;
thereAreNoEditsToSubmit: string;
weEncounteredAnUnexpectedError: string;
};
declare class FormBehaviorElement extends HTMLElement {

@@ -15,3 +24,2 @@ submitting: boolean;

weEncounteredAnUnexpectedError: string;
youMustSelectBetweenMinAndMaxTags: string;
} & {

@@ -46,7 +54,6 @@ [key: string]: string;

validateMaxLength(input: HTMLValueElement, label: string): string | null;
validateTagSelector(input: HTMLInputElement | HTMLValueElement, label: string): string | null;
validateForm(form: HTMLFormElement, displayValidity?: boolean, scope?: Element): Promise<FormValidationResult>;
clearValidationErrors(target: EventTarget | null): void;
showNoChangesMessage(form: HTMLFormElement): void;
runBasicValidation(input: Element, displayValidity: boolean | undefined, errors: FormValidationError[], errorList: HTMLElement, isTagSelector: boolean, isCustomElement: boolean): void;
runBasicValidation(input: Element, displayValidity: boolean | undefined, errors: FormValidationError[], errorList: HTMLElement, isCustomElement: boolean): void;
}

@@ -69,3 +76,3 @@ declare global {

}
declare type NavigationSteps = 'follow' | 'hash-reload' | 'replace' | 'reload' | null;
export declare type NavigationSteps = 'follow' | 'hash-reload' | 'replace' | 'reload' | null;
export interface FormValidationError {

@@ -72,0 +79,0 @@ message: string;

import { generateElementId, kebabToCamelCase } from '../utilities/util';
const defaultMessageStrings = {
export const defaultMessageStrings = {
contentHasChanged: 'Content has changed, please reload the page to get the latest changes.',

@@ -9,4 +9,3 @@ inputMaxLength: '{inputLabel} cannot be longer than {maxLength} characters.',

thereAreNoEditsToSubmit: 'There are no edits to submit.',
weEncounteredAnUnexpectedError: 'We encountered an unexpected error. Please try again later. If this issue continues, please contact site support.',
youMustSelectBetweenMinAndMaxTags: 'You must select between {min} and {max} {tagLabel}.'
weEncounteredAnUnexpectedError: 'We encountered an unexpected error. Please try again later. If this issue continues, please contact site support.'
};

@@ -29,4 +28,3 @@ // <form-behavior>

this.validateRequired.bind(this),
this.validateMaxLength.bind(this),
this.validateTagSelector.bind(this)
this.validateMaxLength.bind(this)
];

@@ -54,3 +52,3 @@ constructor() {

const errorSummaryContainer = document.createElement('div');
errorSummaryContainer.classList.add('form-error-container', 'margin-bottom-sm');
errorSummaryContainer.classList.add('form-error-container');
this.insertAdjacentElement('afterend', errorSummaryContainer);

@@ -138,10 +136,5 @@ this.initialData = new FormData(form);

const form = event.currentTarget;
const validationErrorEvent = new CustomEvent('validationerror', {
bubbles: true,
cancelable: true
});
// reject the submit if no edits have been made (overridable with the new attribute)
if (!this.canSave) {
this.showNoChangesMessage(form);
this.dispatchEvent(validationErrorEvent);
return;

@@ -152,5 +145,4 @@ }

setBusySubmitButton(form, this.submitting);
const valid = await this.validateForm(form);
if (!valid.valid) {
this.dispatchEvent(validationErrorEvent);
const result = await this.validateForm(form);
if (!result.valid) {
return;

@@ -212,2 +204,9 @@ }

}
this.dispatchEvent(new CustomEvent('submission-error', {
detail: {
request,
response
},
bubbles: true
}));
errorList.appendChild(errorText);

@@ -225,3 +224,2 @@ errorAlert.hidden = false;

const formLayout = form.querySelector('.form-error-container') || form;
formLayout.setAttribute('role', 'alert');
const alertId = generateElementId();

@@ -282,20 +280,2 @@ const errorAlert = document.createElement('div');

}
validateTagSelector(input, label) {
if (input instanceof HTMLInputElement && input.classList.contains('tag-input')) {
const min = input.getAttribute('minTags');
const max = input.getAttribute('maxTags');
const tagCount = input.value === '' ? 0 : input.value.split(',').length;
// if no min or max, no need to validate
if (!min || !max) {
return null;
}
if (!tagCount || tagCount < Number(min) || tagCount > Number(max)) {
return `${this.locStrings.youMustSelectBetweenMinAndMaxTags
.replace('{min}', min)
.replace('{max}', max)
.replace('{tagLabel}', label.toLocaleLowerCase())}`;
}
}
return null;
}
async validateForm(form, displayValidity = true, scope = form) {

@@ -313,4 +293,3 @@ const errors = [];

}
const isTagSelector = input.classList.contains('tag-input');
if (input.hasAttribute('aria-hidden') && !isTagSelector) {
if (input.hasAttribute('aria-hidden')) {
continue;

@@ -327,3 +306,11 @@ }

const isCustomElement = !!customElements.find(el => el === input);
this.runBasicValidation(input, displayValidity, errors, errorList, isTagSelector, isCustomElement);
this.runBasicValidation(input, displayValidity, errors, errorList, isCustomElement);
const validationErrorEvent = new CustomEvent('form-validating', {
detail: {
errors,
form
},
bubbles: true
});
this.dispatchEvent(validationErrorEvent);
}

@@ -334,2 +321,3 @@ if (errors.length === 0) {

if (displayValidity) {
errorAlert.classList.add('margin-bottom-sm');
errorAlert.hidden = false;

@@ -356,2 +344,6 @@ errorAlert.focus();

}
const clearValidationEvent = new CustomEvent('clear-validation-errors', {
bubbles: true
});
this.dispatchEvent(clearValidationEvent);
}

@@ -374,3 +366,3 @@ showNoChangesMessage(form) {

}
runBasicValidation(input, displayValidity = true, errors, errorList, isTagSelector, isCustomElement) {
runBasicValidation(input, displayValidity = true, errors, errorList, isCustomElement) {
if (!canValidate(input, this.form)) {

@@ -395,6 +387,3 @@ return;

if (displayValidity) {
const inputId = isTagSelector
? input.parentElement?.querySelector('input.autocomplete-input')?.id
: input.id;
if (!inputId) {
if (!input.id) {
continue;

@@ -407,11 +396,17 @@ }

const a = document.createElement('a');
a.href = `#${inputId}`;
a.href = `#${input.id}`;
a.textContent = message;
a.classList.add('help', 'help-danger');
// ensure focus is set on the custom element
a.addEventListener('click', e => {
if (isCustomElement) {
const target = e.target.getAttribute('href');
if (target) {
document.querySelector(target).focus();
}
}
});
child.appendChild(a);
errorList.appendChild(child);
if (!isCustomElement) {
if (isTagSelector) {
input.nextElementSibling?.classList.add('border-color-danger');
}
input.classList.add(`${input.localName}-danger`);

@@ -536,5 +531,6 @@ }

const formData = Object.fromEntries(new FormData(form));
const formElements = Object.keys(form.elements);
const customElementList = [];
const customElements = Object.keys(formData).filter(el => formElements.indexOf(el) === -1);
const customElements = Object.keys(formData).filter(key => {
return !form.elements.namedItem(key);
});
customElements.forEach(name => {

@@ -549,6 +545,2 @@ const element = form.querySelector(`[name="${name}"]`);

function clearInputErrorBorder(input) {
const isTagSelector = input.classList.contains('tag-input');
if (isTagSelector) {
input.nextElementSibling?.classList.remove('border-color-danger');
}
input.classList.remove(`${input.localName}-danger`);

@@ -555,0 +547,0 @@ }

@@ -24,2 +24,3 @@ export declare class StarRatingElement extends HTMLElement {

updateStarFill(newValue: number): void;
focus(): void;
}

@@ -26,0 +27,0 @@ declare global {

@@ -84,3 +84,4 @@ const starRatingTemplate = document.createElement('template');

input:focus-visible + label {
input:focus-visible + label,
input:focus + label {
border-radius: 0.5em;

@@ -186,3 +187,3 @@ outline: 3px dashed;

static get observedAttributes() {
return ['disabled', 'name', 'required', 'value'];
return ['disabled', 'name', 'required', 'value', 'focus', 'blur'];
}

@@ -250,2 +251,4 @@ coercedValue = '';

: 'star rating');
this.addEventListener('focus', this);
this.addEventListener('blur', this);
}

@@ -286,2 +289,5 @@ disconnectedCallback() {

switch (event.type) {
case 'blur':
this.removeAttribute('tabindex');
break;
case 'change':

@@ -292,2 +298,7 @@ const target = event.target;

break;
case 'focus':
if (!this.shadowRoot?.activeElement) {
this.shadowRoot?.querySelectorAll('input')[0].focus();
}
break;
case 'slotchange':

@@ -333,2 +344,5 @@ const slot = event.target;

}
focus() {
this.setAttribute('tabindex', '-1');
}
}

@@ -335,0 +349,0 @@ if (!window.customElements.get('star-rating')) {

export * from './behaviors/popover';
export * from './behaviors/tag-inputs';
export * from './elements/form-behavior';
export * from './elements/star-rating';
//# sourceMappingURL=index.d.ts.map
export * from './behaviors/popover';
export * from './behaviors/tag-inputs';
export * from './elements/form-behavior';
export * from './elements/star-rating';
{
"name": "@microsoft/atlas-js",
"version": "1.3.0",
"version": "1.4.0",
"public": true,

@@ -5,0 +5,0 @@ "description": "Scripts backing the Atlas Design System used by Microsoft's Developer Relations.",

import { generateElementId, kebabToCamelCase } from '../utilities/util';
const defaultMessageStrings = {
export const defaultMessageStrings = {
contentHasChanged: 'Content has changed, please reload the page to get the latest changes.',

@@ -11,4 +11,3 @@ inputMaxLength: '{inputLabel} cannot be longer than {maxLength} characters.',

weEncounteredAnUnexpectedError:
'We encountered an unexpected error. Please try again later. If this issue continues, please contact site support.',
youMustSelectBetweenMinAndMaxTags: 'You must select between {min} and {max} {tagLabel}.'
'We encountered an unexpected error. Please try again later. If this issue continues, please contact site support.'
};

@@ -36,4 +35,3 @@ // <form-behavior>

this.validateRequired.bind(this),
this.validateMaxLength.bind(this),
this.validateTagSelector.bind(this)
this.validateMaxLength.bind(this)
];

@@ -67,3 +65,3 @@

const errorSummaryContainer = document.createElement('div');
errorSummaryContainer.classList.add('form-error-container', 'margin-bottom-sm');
errorSummaryContainer.classList.add('form-error-container');
this.insertAdjacentElement('afterend', errorSummaryContainer);

@@ -174,6 +172,2 @@

const form = event.currentTarget as HTMLFormElement;
const validationErrorEvent = new CustomEvent('validationerror', {
bubbles: true,
cancelable: true
});

@@ -183,3 +177,2 @@ // reject the submit if no edits have been made (overridable with the new attribute)

this.showNoChangesMessage(form);
this.dispatchEvent(validationErrorEvent);
return;

@@ -191,5 +184,4 @@ }

setBusySubmitButton(form, this.submitting);
const valid = await this.validateForm(form);
if (!valid.valid) {
this.dispatchEvent(validationErrorEvent);
const result = await this.validateForm(form);
if (!result.valid) {
return;

@@ -259,2 +251,11 @@ }

}
this.dispatchEvent(
new CustomEvent('submission-error', {
detail: {
request,
response
},
bubbles: true
})
);

@@ -276,3 +277,2 @@ errorList.appendChild(errorText);

const formLayout = form.querySelector('.form-error-container') || form;
formLayout.setAttribute('role', 'alert');
const alertId = generateElementId();

@@ -350,23 +350,2 @@

validateTagSelector(input: HTMLInputElement | HTMLValueElement, label: string): string | null {
if (input instanceof HTMLInputElement && input.classList.contains('tag-input')) {
const min = input.getAttribute('minTags');
const max = input.getAttribute('maxTags');
const tagCount = input.value === '' ? 0 : input.value.split(',').length;
// if no min or max, no need to validate
if (!min || !max) {
return null;
}
if (!tagCount || tagCount < Number(min) || tagCount > Number(max)) {
return `${this.locStrings.youMustSelectBetweenMinAndMaxTags
.replace('{min}', min)
.replace('{max}', max)
.replace('{tagLabel}', label.toLocaleLowerCase())}`;
}
}
return null;
}
async validateForm(

@@ -391,4 +370,3 @@ form: HTMLFormElement,

const isTagSelector = input.classList.contains('tag-input');
if (input.hasAttribute('aria-hidden') && !isTagSelector) {
if (input.hasAttribute('aria-hidden')) {
continue;

@@ -409,10 +387,11 @@ }

this.runBasicValidation(
input,
displayValidity,
errors,
errorList,
isTagSelector,
isCustomElement
);
this.runBasicValidation(input, displayValidity, errors, errorList, isCustomElement);
const validationErrorEvent = new CustomEvent('form-validating', {
detail: {
errors,
form
},
bubbles: true
});
this.dispatchEvent(validationErrorEvent);
}

@@ -425,2 +404,3 @@

if (displayValidity) {
errorAlert.classList.add('margin-bottom-sm');
errorAlert.hidden = false;

@@ -453,2 +433,7 @@ errorAlert.focus();

}
const clearValidationEvent = new CustomEvent('clear-validation-errors', {
bubbles: true
});
this.dispatchEvent(clearValidationEvent);
}

@@ -479,3 +464,2 @@

errorList: HTMLElement,
isTagSelector: boolean,
isCustomElement: boolean

@@ -506,7 +490,3 @@ ) {

if (displayValidity) {
const inputId = isTagSelector
? input.parentElement?.querySelector('input.autocomplete-input')?.id
: input.id;
if (!inputId) {
if (!input.id) {
continue;

@@ -521,6 +501,16 @@ }

const a = document.createElement('a');
a.href = `#${inputId}`;
a.href = `#${input.id}`;
a.textContent = message;
a.classList.add('help', 'help-danger');
// ensure focus is set on the custom element
a.addEventListener('click', e => {
if (isCustomElement) {
const target = (e.target as HTMLAnchorElement).getAttribute('href');
if (target) {
(document.querySelector(target) as HTMLElement).focus();
}
}
});
child.appendChild(a);

@@ -530,5 +520,2 @@ errorList.appendChild(child);

if (!isCustomElement) {
if (isTagSelector) {
input.nextElementSibling?.classList.add('border-color-danger');
}
input.classList.add(`${input.localName}-danger`);

@@ -575,6 +562,5 @@ }

weEncounteredAnUnexpectedError: string;
youMustSelectBetweenMinAndMaxTags: string;
}
type NavigationSteps = 'follow' | 'hash-reload' | 'replace' | 'reload' | null;
export type NavigationSteps = 'follow' | 'hash-reload' | 'replace' | 'reload' | null;

@@ -730,5 +716,7 @@ export interface FormValidationError {

const formData = Object.fromEntries(new FormData(form));
const formElements = Object.keys(form.elements);
const customElementList: Element[] = [];
const customElements = Object.keys(formData).filter(el => formElements.indexOf(el) === -1);
const customElements = Object.keys(formData).filter(key => {
return !form.elements.namedItem(key);
});
customElements.forEach(name => {

@@ -744,6 +732,2 @@ const element = form.querySelector(`[name="${name}"]`);

function clearInputErrorBorder(input: HTMLValueElement) {
const isTagSelector = input.classList.contains('tag-input');
if (isTagSelector) {
input.nextElementSibling?.classList.remove('border-color-danger');
}
input.classList.remove(`${input.localName}-danger`);

@@ -750,0 +734,0 @@ }

@@ -86,3 +86,4 @@ const starRatingTemplate = document.createElement('template');

input:focus-visible + label {
input:focus-visible + label,
input:focus + label {
border-radius: 0.5em;

@@ -190,3 +191,3 @@ outline: 3px dashed;

static get observedAttributes() {
return ['disabled', 'name', 'required', 'value'];
return ['disabled', 'name', 'required', 'value', 'focus', 'blur'];
}

@@ -273,2 +274,4 @@

);
this.addEventListener('focus', this);
this.addEventListener('blur', this);
}

@@ -315,2 +318,5 @@

switch (event.type) {
case 'blur':
this.removeAttribute('tabindex');
break;
case 'change':

@@ -321,2 +327,7 @@ const target = event.target as HTMLInputElement;

break;
case 'focus':
if (!this.shadowRoot?.activeElement) {
this.shadowRoot?.querySelectorAll('input')[0].focus();
}
break;
case 'slotchange':

@@ -365,2 +376,6 @@ const slot = event.target as HTMLSlotElement;

}
focus() {
this.setAttribute('tabindex', '-1');
}
}

@@ -367,0 +382,0 @@

export * from './behaviors/popover';
export * from './behaviors/tag-inputs';
export * from './elements/form-behavior';
export * from './elements/star-rating';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc