VulpesOS/gaia/distros/spark/apps/sharing/components/gaia-checkbox/gaia-checkbox.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

272 lines
6.1 KiB
JavaScript
Executable file

/* global define */
(function(define){'use strict';define(['require','exports','module','gaia-icons','gaia-component'],function(require,exports,module){
/**
* Dependencies
*/
require('gaia-icons');
var component = require('gaia-component');
/**
* Exports
*/
module.exports = component.register('gaia-checkbox', {
extends: HTMLInputElement.prototype,
created: function() {
this.setupShadowRoot();
this.els = { inner: this.shadowRoot.querySelector('.inner') };
this.addEventListener('click', this.onClick.bind(this));
// Setup initial attributes
this.checked = this.getAttribute('checked');
this.danger = this.getAttribute('danger');
this.name = this.getAttribute('name');
// process everything that doesn't affect user interaction
// after the component is created
setTimeout(() => this.makeAccessible());
},
makeAccessible: function() {
this.setAttribute('role', 'checkbox');
// Make tabable
this.tabIndex = 0;
this.setAttr('aria-checked', this.checked);
},
onClick: function(e) {
e.stopPropagation();
this.checked = !this.checked;
},
toggle: function(value) {
value = arguments.length ? value : !this.checked;
if (value || value === '') { this.check(); }
else { this.uncheck(); }
},
check: function() {
if (this.checked) { return; }
this.setAttr('checked', '');
this.setAttribute('aria-checked', true);
this._checked = true;
},
uncheck: function() {
if (!this.checked) { return; }
this.removeAttr('checked');
this.setAttribute('aria-checked', false);
this._checked = false;
},
attrs: {
checked: {
get: function() { return !!this._checked; },
set: function() { this.toggle(); }
},
danger: {
get: function() { return this._danger; },
set: function(value) {
if (value || value === '') { this.setAttr('danger', value); }
else { this.removeAttr('danger'); }
this._danger = value;
}
},
name: {
get: function() { return this._name; },
set: function(value) {
if (value === null) { this.removeAttr('name'); }
else { this.setAttr('name', value); }
this._name = value;
}
}
},
template: `<div class="inner">
<div class="background"></div>
<div class="tick"></div>
</div>
<style>
/** Host
---------------------------------------------------------*/
:host {
position: relative;
display: inline-block;
cursor: pointer;
outline: 0;
}
/** Inner
---------------------------------------------------------*/
.inner {
display: block;
box-sizing: border-box;
position: relative;
width: 28px;
height: 28px;
border-radius: 50%;
border: 2px solid #a6a6a6;
z-index: 0;
--gaia-checkbox-background:
var(--checkbox-background,
var(--input-background,
var(--button-background,
var(--background-plus))));
background:
var(--gaia-checkbox-background);
border-color:
var(--checkbox-border-color,
var(--border-color,
var(--background-minus)));
}
/**
* Increase hit area
*/
.inner:before {
content: '';
position: absolute;
top: -10px; right: -10px;
bottom: -10px; left: -10px;
}
/** Background
---------------------------------------------------------*/
.background {
width: 100%;
height: 100%;
border-radius: 50%;
top: 0px;
left: 0px;
position: absolute;
z-index: -1;
opacity: 0;
background: var(--highlight-color, #000);
}
/**
* .active
*/
.inner[checked] .background {
animation-name: gaia-checkbox-animation;
animation-duration: 350ms;
animation-fill-mode: forwards;
}
/** Tick
---------------------------------------------------------*/
.tick {
text-align: center;
line-height: 26px;
margin-left: -1px;
opacity: 0;
transition-property: opacity;
transition-duration: 100ms;
color: var(--highlight-color, #000);
}
/**
* [checked]
*/
[checked] .tick {
opacity: 1;
transition-delay: 140ms;
}
/** Icon
---------------------------------------------------------*/
.tick:before {
font-family: 'gaia-icons';
content: 'tick';
font-style: normal;
font-weight: 500;
text-rendering: optimizeLegibility;
font-size: 16px;
line-height: 1;
}
</style>`,
globalCss: `@keyframes gaia-checkbox-animation {
0% {
transform: scale(0);
opacity: 1;
}
65% {
transform: scale(1);
opacity: 1;
}
100% {
opacity: 0;
transform: scale(1);
}
}`
});
// Makes checkboxs togglable via keboard
addEventListener('keypress', function(e) {
if (e.which !== 32) { return; }
var el = document.activeElement;
var isCheckbox = el.tagName === 'GAIA-CHECKBOX';
if (isCheckbox) { el.click(); }
});
// Bind a 'click' delegate to the
// window to listen for all clicks
// and toggle checkboxes when required.
addEventListener('click', function(e) {
var label = getLabel(e.target);
var gaiaCheckbox = getLinkedCheckbox(label);
if (gaiaCheckbox) { gaiaCheckbox.toggle(); }
}, true);
/**
* Find a checkbox when given a <label>.
*
* @param {Element} label
* @return {GaiaCheckbox|null}
*/
function getLinkedCheckbox(label) {
if (!label) { return; }
var id = label.getAttribute('for');
var el = id && document.getElementById(id);
return el && el.tagName === 'GAIA-CHECKBOX' ? el : null;
}
/**
* Walk up the DOM tree from a given
* element until a <label> is found.
*
* @param {Element} el
* @return {HTMLLabelElement|undefined}
*/
function getLabel(el) {
return el && (el.tagName == 'LABEL' ? el : getLabel(el.parentNode));
}
});})(typeof define=='function'&&define.amd?define
:(function(n,w){'use strict';return typeof module=='object'?function(c){
c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){
return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-checkbox',this));