@microsoft/atlas-js
Advanced tools
Comparing version 1.1.1 to 1.2.0
@@ -7,2 +7,3 @@ export declare class StarRatingElement extends HTMLElement { | ||
set disabled(val: boolean); | ||
get form(): HTMLFormElement | null; | ||
get name(): string; | ||
@@ -16,8 +17,9 @@ set name(val: string); | ||
get valueAsNumber(): number; | ||
/** TODO: add form related properties (i.e validity, etc */ | ||
get validity(): ValidityState | undefined; | ||
connectedCallback(): void; | ||
disconnectedCallback(): void; | ||
attributeChangedCallback(name: string, oldValue: string, newValue: string): void; | ||
updateContent(name: string, newValue: string): void; | ||
updateContent(name: string, newValue: string, target?: HTMLInputElement): void; | ||
handleEvent(event: Event): void; | ||
handleFormData(event: FormDataEvent): void; | ||
updateStarFill(newValue: number): void; | ||
@@ -24,0 +26,0 @@ } |
const starRatingTemplate = document.createElement('template'); | ||
starRatingTemplate.id = 'star-rating-template'; | ||
/* TODO: Consider replacing with constructable stylesheets when there is broader support for Firefox and Safari. | ||
https://web.dev/custom-elements-v1/ | ||
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet */ | ||
/** TODO: Consider replacing with constructable stylesheets when there is broader support for Firefox and Safari. | ||
* https://web.dev/custom-elements-v1/ | ||
* https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet | ||
* | ||
* TODO: Turn into form associated custom element when element internals is more supported | ||
* https://web.dev/more-capable-form-controls/ | ||
* https://caniuse.com/?search=internals | ||
*/ | ||
starRatingTemplate.innerHTML = ` | ||
@@ -26,3 +31,3 @@ <style type="text/css"> | ||
} | ||
fieldset { | ||
@@ -34,3 +39,7 @@ display: contents; | ||
} | ||
legend { | ||
margin-inline-end: 0.25rem; | ||
} | ||
.star-container { | ||
@@ -48,3 +57,3 @@ display: flex; | ||
.star-container > input:not(.is-selected) ~ label svg, | ||
.star-container > input + label:hover ~ label svg, | ||
.star-container > input + label:hover ~ input:not(.is-selected) + label svg, | ||
.star-container > input:checked ~ label svg { | ||
@@ -55,2 +64,3 @@ fill: none; | ||
.star-container:hover > input + label svg, | ||
.star-container:hover ~ input.is-selected + label svg, | ||
.star-container > input.is-selected + label svg, | ||
@@ -118,4 +128,4 @@ .star-container input:focus-visible:not(:disabled) + label svg { | ||
} | ||
</style> | ||
<fieldset> | ||
</style> | ||
<fieldset> | ||
<legend><slot name="legend" id="legend">Enter rating</slot></legend> | ||
@@ -167,3 +177,3 @@ | ||
<span id="alert"> | ||
<output id="alert" for="radio-1 radio-2 radio-3 radio-4 radio-5" class="star-rating-output"> | ||
<span id="label-1"><slot name="label-1"></slot></span> | ||
@@ -174,5 +184,5 @@ <span id="label-2"><slot name="label-2"></slot></span> | ||
<span id="label-5"><slot name="label-5"></slot></span> | ||
</span> | ||
</output> | ||
</div> | ||
</fieldset> | ||
</fieldset> | ||
`; | ||
@@ -182,3 +192,3 @@ const template = starRatingTemplate; | ||
static get observedAttributes() { | ||
return ['disabled', 'name', 'value']; | ||
return ['disabled', 'name', 'required', 'value']; | ||
} | ||
@@ -197,2 +207,5 @@ coercedValue = ''; | ||
} | ||
get form() { | ||
return this.closest(`form`); | ||
} | ||
get name() { | ||
@@ -208,3 +221,3 @@ return this.getAttribute('name') ?? ''; | ||
set required(val) { | ||
this.setAttribute('required', val.toString()); | ||
this.toggleAttribute('required', val); | ||
} | ||
@@ -233,12 +246,18 @@ get type() { | ||
} | ||
/** TODO: add form related properties (i.e validity, etc */ | ||
get validity() { | ||
// borrow radio input's native validity | ||
return this.shadowRoot?.querySelector('input')?.validity; | ||
} | ||
connectedCallback() { | ||
this.shadowRoot?.addEventListener('change', this); | ||
// arrow function to bind `this` value to star rating in handleFormData | ||
this.closest('form')?.addEventListener('formdata', this); | ||
this.form?.addEventListener('formdata', e => this.handleFormData(e)); | ||
this.shadowRoot?.addEventListener('slotchange', this); | ||
this.setAttribute('aria-label', this.querySelector('legend[slot="legend"]') | ||
? this.querySelector('legend[slot="legend"]')?.innerText | ||
: 'star rating'); | ||
} | ||
disconnectedCallback() { | ||
this.shadowRoot?.removeEventListener('change', this); | ||
this.closest('form')?.removeEventListener('formdata', this); | ||
this.form?.removeEventListener('formdata', this); | ||
} | ||
@@ -250,3 +269,3 @@ attributeChangedCallback(name, oldValue, newValue) { | ||
} | ||
updateContent(name, newValue) { | ||
updateContent(name, newValue, target) { | ||
if (name === 'name') { | ||
@@ -260,2 +279,6 @@ this.shadowRoot?.querySelectorAll('input[type="radio"]').forEach(input => { | ||
this.updateStarFill(parseInt(newValue)); | ||
const outputElement = this.shadowRoot?.querySelector('.star-rating-output'); | ||
if (target?.nextElementSibling) { | ||
outputElement.textContent = target?.nextElementSibling?.textContent.trimStart(); | ||
} | ||
} | ||
@@ -266,2 +289,6 @@ if (name === 'disabled') { | ||
} | ||
if (name === 'required') { | ||
const input = this.shadowRoot?.querySelectorAll('input[type="radio"]')[0]; | ||
input.required = newValue !== null; | ||
} | ||
} | ||
@@ -272,9 +299,5 @@ handleEvent(event) { | ||
const target = event.target; | ||
this.updateContent('value', target.value); | ||
this.updateContent('value', target.value, target); | ||
this.dispatchEvent(new Event('change', { bubbles: true })); | ||
break; | ||
case 'formdata': | ||
// https://web.dev/more-capable-form-controls/ | ||
event.formData.append(this.name, this.value.toString()); | ||
break; | ||
case 'slotchange': | ||
@@ -301,2 +324,10 @@ const slot = event.target; | ||
} | ||
handleFormData(event) { | ||
if (this.disabled) { | ||
return; | ||
} | ||
if (this.name) { | ||
event.formData.append(this.name, this.value); | ||
} | ||
} | ||
updateStarFill(newValue) { | ||
@@ -303,0 +334,0 @@ const stars = this.shadowRoot.querySelectorAll('input'); |
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.1.1", | ||
"version": "1.2.0", | ||
"public": true, | ||
@@ -5,0 +5,0 @@ "description": "Scripts backing the Atlas Design System used by Microsoft's Developer Relations.", |
const starRatingTemplate = document.createElement('template'); | ||
starRatingTemplate.id = 'star-rating-template'; | ||
/* TODO: Consider replacing with constructable stylesheets when there is broader support for Firefox and Safari. | ||
https://web.dev/custom-elements-v1/ | ||
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet */ | ||
/** TODO: Consider replacing with constructable stylesheets when there is broader support for Firefox and Safari. | ||
* https://web.dev/custom-elements-v1/ | ||
* https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet | ||
* | ||
* TODO: Turn into form associated custom element when element internals is more supported | ||
* https://web.dev/more-capable-form-controls/ | ||
* https://caniuse.com/?search=internals | ||
*/ | ||
@@ -28,3 +33,3 @@ starRatingTemplate.innerHTML = ` | ||
} | ||
fieldset { | ||
@@ -36,3 +41,7 @@ display: contents; | ||
} | ||
legend { | ||
margin-inline-end: 0.25rem; | ||
} | ||
.star-container { | ||
@@ -50,3 +59,3 @@ display: flex; | ||
.star-container > input:not(.is-selected) ~ label svg, | ||
.star-container > input + label:hover ~ label svg, | ||
.star-container > input + label:hover ~ input:not(.is-selected) + label svg, | ||
.star-container > input:checked ~ label svg { | ||
@@ -57,2 +66,3 @@ fill: none; | ||
.star-container:hover > input + label svg, | ||
.star-container:hover ~ input.is-selected + label svg, | ||
.star-container > input.is-selected + label svg, | ||
@@ -120,4 +130,4 @@ .star-container input:focus-visible:not(:disabled) + label svg { | ||
} | ||
</style> | ||
<fieldset> | ||
</style> | ||
<fieldset> | ||
<legend><slot name="legend" id="legend">Enter rating</slot></legend> | ||
@@ -169,3 +179,3 @@ | ||
<span id="alert"> | ||
<output id="alert" for="radio-1 radio-2 radio-3 radio-4 radio-5" class="star-rating-output"> | ||
<span id="label-1"><slot name="label-1"></slot></span> | ||
@@ -176,5 +186,5 @@ <span id="label-2"><slot name="label-2"></slot></span> | ||
<span id="label-5"><slot name="label-5"></slot></span> | ||
</span> | ||
</output> | ||
</div> | ||
</fieldset> | ||
</fieldset> | ||
`; | ||
@@ -186,3 +196,3 @@ | ||
static get observedAttributes() { | ||
return ['disabled', 'name', 'value']; | ||
return ['disabled', 'name', 'required', 'value']; | ||
} | ||
@@ -206,2 +216,6 @@ | ||
get form() { | ||
return this.closest(`form`); | ||
} | ||
get name() { | ||
@@ -220,3 +234,3 @@ return this.getAttribute('name') ?? ''; | ||
set required(val) { | ||
this.setAttribute('required', val.toString()); | ||
this.toggleAttribute('required', val); | ||
} | ||
@@ -251,3 +265,6 @@ | ||
/** TODO: add form related properties (i.e validity, etc */ | ||
get validity() { | ||
// borrow radio input's native validity | ||
return this.shadowRoot?.querySelector('input')?.validity; | ||
} | ||
@@ -257,4 +274,10 @@ connectedCallback() { | ||
// arrow function to bind `this` value to star rating in handleFormData | ||
this.closest('form')?.addEventListener('formdata', this); | ||
this.form?.addEventListener('formdata', e => this.handleFormData(e)); | ||
this.shadowRoot?.addEventListener('slotchange', this); | ||
this.setAttribute( | ||
'aria-label', | ||
this.querySelector('legend[slot="legend"]') | ||
? (this.querySelector('legend[slot="legend"]') as HTMLLegendElement)?.innerText | ||
: 'star rating' | ||
); | ||
} | ||
@@ -264,3 +287,3 @@ | ||
this.shadowRoot?.removeEventListener('change', this); | ||
this.closest('form')?.removeEventListener('formdata', this); | ||
this.form?.removeEventListener('formdata', this); | ||
} | ||
@@ -274,3 +297,3 @@ | ||
updateContent(name: string, newValue: string) { | ||
updateContent(name: string, newValue: string, target?: HTMLInputElement) { | ||
if (name === 'name') { | ||
@@ -284,2 +307,8 @@ this.shadowRoot?.querySelectorAll('input[type="radio"]').forEach(input => { | ||
this.updateStarFill(parseInt(newValue)); | ||
const outputElement = this.shadowRoot?.querySelector( | ||
'.star-rating-output' | ||
) as HTMLOutputElement; | ||
if (target?.nextElementSibling) { | ||
outputElement.textContent = target?.nextElementSibling?.textContent!.trimStart(); | ||
} | ||
} | ||
@@ -290,2 +319,6 @@ if (name === 'disabled') { | ||
} | ||
if (name === 'required') { | ||
const input = this.shadowRoot?.querySelectorAll('input[type="radio"]')[0] as HTMLInputElement; | ||
input.required = newValue !== null; | ||
} | ||
} | ||
@@ -297,9 +330,5 @@ | ||
const target = event.target as HTMLInputElement; | ||
this.updateContent('value', target.value); | ||
this.updateContent('value', target.value, target); | ||
this.dispatchEvent(new Event('change', { bubbles: true })); | ||
break; | ||
case 'formdata': | ||
// https://web.dev/more-capable-form-controls/ | ||
(event as FormDataEvent).formData.append(this.name, this.value.toString()); | ||
break; | ||
case 'slotchange': | ||
@@ -329,2 +358,11 @@ const slot = event.target as HTMLSlotElement; | ||
handleFormData(event: FormDataEvent) { | ||
if (this.disabled) { | ||
return; | ||
} | ||
if (this.name) { | ||
event.formData.append(this.name, this.value); | ||
} | ||
} | ||
updateStarFill(newValue: number) { | ||
@@ -331,0 +369,0 @@ const stars = this.shadowRoot!.querySelectorAll('input'); |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
84666
26
2173
2