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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,37 @@
{
"name": "gaia-text-input",
"authors": [
"Wilson Page <wilsonpage@me.com>"
],
"main": "gaia-text-input.js",
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"README.md"
],
"dependencies": {
"gaia-icons": "gaia-components/gaia-icons#~0.10.0",
"gaia-component": "gaia-components/gaia-component#~0.3.3"
},
"devDependencies": {
"gaia-fonts": "gaia-components/gaia-fonts#~0.2.1",
"gaia-theme": "gaia-components/gaia-theme#~0.4.3",
"base": "gaia-components/base",
"gaia-icons": "gaia-components/gaia-icons#master"
},
"homepage": "https://github.com/gaia-components/gaia-text-input",
"version": "0.2.1",
"_release": "0.2.1",
"_resolution": {
"type": "version",
"tag": "v0.2.1",
"commit": "c0669b5f4a2a79f2e7ae36d322df1fc713574120"
},
"_source": "git://github.com/gaia-components/gaia-text-input.git",
"_target": "v0.2.1",
"_originalSource": "gaia-components/gaia-text-input"
}

View file

@ -0,0 +1,26 @@
{
"name": "gaia-text-input",
"authors": [
"Wilson Page <wilsonpage@me.com>"
],
"main": "gaia-text-input.js",
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"README.md"
],
"dependencies": {
"gaia-icons": "gaia-components/gaia-icons#~0.10.0",
"gaia-component": "gaia-components/gaia-component#~0.3.3"
},
"devDependencies": {
"gaia-fonts": "gaia-components/gaia-fonts#~0.2.1",
"gaia-theme": "gaia-components/gaia-theme#~0.4.3",
"base": "gaia-components/base",
"gaia-icons": "gaia-components/gaia-icons#master"
}
}

View file

@ -0,0 +1,214 @@
(define=>{define((require,exports,module)=>{
'use strict';
/**
* Dependencies
*/
var component = require('gaia-component');
/**
* Exports
*/
module.exports = component.register('gaia-text-input-multiline', {
created() {
this.setupShadowRoot();
this.els = {
inner: this.shadowRoot.querySelector('.inner'),
field: this.shadowRoot.querySelector('textarea')
};
this.type = this.getAttribute('type');
this.disabled = this.hasAttribute('disabled');
this.placeholder = this.getAttribute('placeholder');
this.required = this.getAttribute('required');
this.value = this.getAttribute('value');
},
clear(e) {
this.value = '';
},
attrs: {
placeholder: {
get: function() { return this.els.field.placeholder; },
set: function(value) { this.els.field.placeholder = value || ''; }
},
value: {
get: function() { return this.els.field.value; },
set: function(value) { this.els.field.value = value; }
},
required: {
get: function() { return this.els.field.required; },
set: function(value) { this.els.field.required = value; }
},
disabled: {
get: function() { return this.els.field.disabled; },
set: function(value) {
value = !!(value === '' || value);
this.els.field.disabled = value;
}
}
},
template: `<div class="inner">
<content select="label"></content>
<div class="fields">
<textarea></textarea>
<div class="focus focus-1"></div>
<div class="focus focus-2"></div>
</div>
</div>
<style>
/** Reset
---------------------------------------------------------*/
textarea {
box-sizing: border-box;
border: 0;
margin: 0;
padding: 0;
}
/** Host
---------------------------------------------------------*/
:host {
display: block;
margin-top: var(--base-m, 18px);
margin-bottom: var(--base-m, 18px);
font-size: 17px;
}
/** Inner
---------------------------------------------------------*/
.inner {
height: 100%;
}
/** Label
---------------------------------------------------------*/
label {
font-size: 14px;
display: block;
margin: 0 0 4px 16px;
}
/**
* [disbled]
*/
[disabled] label {
opacity: 0.3;
}
/** Fields
---------------------------------------------------------*/
.fields {
box-sizing: border-box;
position: relative;
width: 100%;
height: 100%;
--gi-border-color:
var(--input-border-color,
var(--border-color,
var(--background-plus,
#e7e7e7)));
border-color:
var(--gi-border-color);
border:
var(--input-border,
var(--border,
1px solid var(--gi-border-color)));
}
/** Textarea
---------------------------------------------------------*/
textarea {
display: block;
width: 100%;
height: 100%;
min-height: 86px;
padding: 10px 16px;
font-size: inherit;
border: none;
margin: 0;
font: inherit;
resize: none;
/* dynamic */
color:
var(--text-color, #000);
background:
var(--text-input-background,
var(--input-background,
var(--background-minus,
#fff)));
}
/**
* [disabled]
*/
textarea[disabled] {
background: transparent;
}
/** Placeholder Text
---------------------------------------------------------*/
::-moz-placeholder {
font-style: italic;
color:
var(--input-placeholder-color, #909ca7);
}
/** Focus Bar
---------------------------------------------------------*/
.focus {
position: absolute;
bottom: 0px;
width: 100%;
height: 3px;
transition: all 200ms;
transform: scaleX(0);
visibility: hidden;
background: var(--highlight-color, #000);
}
/**
* input:focus
*/
:focus ~ .focus {
transform: scaleX(1);
transition-delay: 200ms;
visibility: visible;
}
.focus-2 {
top: 0;
bottom: auto;
}
</style>`
});
})})(((n,w)=>{return(typeof define)[0]=='f'&&define.amd?define:(typeof module)[0]=='o'?c =>{c(require,exports,module)}:c=>{var m={exports:{}},r=n=>w[n];w[n]=c(r,m.exports,m)||m.exports;};})('gaia-text-input-multiline',this));/*jshint ignore:line*/

View file

@ -0,0 +1,273 @@
(define=>{define((require,exports,module)=>{
'use strict';
/**
* Dependencies
*/
var component = require('gaia-component');
/**
* Locals
*/
var DEFAULT_LENGTH = 4;
/**
* Exports
*/
module.exports = component.register('gaia-text-input-pin', {
created() {
this.setupShadowRoot();
this.els = {
inner: this.shadowRoot.querySelector('.inner'),
fields: this.shadowRoot.querySelector('.fields'),
input: this.shadowRoot.querySelector('input')
};
this.disabled = this.hasAttribute('disabled');
this.length = this.getAttribute('length') || DEFAULT_LENGTH;
this.addEventListener('keyup', () => this.updateCells());
},
updateCells() {
var l = this.els.input.value.length;
this.els.cells.forEach((cell, i) => {
cell.classList.toggle('populated', i < l);
cell.classList.toggle('focused', i == l);
});
},
onBackspace(e) {
var input = e.target;
var empty = !input.value;
var previous = input.previousElementSibling;
if (!empty && previous) {
previous.clear();
previous.focus();
} else if (empty && previous) {
previous.focus();
}
},
setupFields() {
this.els.fields.innerHTML = '';
this.els.cells = [];
for (var i = 0, l = this.length; i < l; i++) {
var el = document.createElement('div');
el.className = 'cell';
this.els.fields.appendChild(el);
this.els.cells.push(el);
}
},
clear(e) {
this.value = '';
},
/**
* Attributes
*/
attrs: {
length: {
get: function() { return this._length; },
set: function(value) {
value = Number(value);
this._length = value;
this.els.input.setAttribute('maxlength', this.length);
this.setupFields();
}
},
value: {
get: function() { return this.els.input.value; },
set: function(value) { this.els.input.value = value; }
},
disabled: {
get: function() { return this.els.input.disabled; },
set: function(value) {
value = !!(value === '' || value);
this.els.input.disabled = value;
}
}
},
template: `
<div class="inner">
<content select="label"></content>
<div class="container">
<input />
<div class="fields"></div>
</div>
</div>
<style>
/** Host
---------------------------------------------------------*/
:host {
display: block;
height: 40px;
margin-top: var(--base-m, 18px);
margin-bottom: var(--base-m, 18px);
font-size: 40px;
}
/** Inner
---------------------------------------------------------*/
.inner {
height: 100%;
}
/** Label
---------------------------------------------------------*/
label {
font-size: 14px;
display: block;
margin: 0 0 4px 16px;
}
/** Container
---------------------------------------------------------*/
.container {
position: relative;
z-index: 0;
height: 100%;
}
/** Input (hidden)
---------------------------------------------------------*/
input {
opacity: 0;
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
z-index: 1;
}
/** Fields
---------------------------------------------------------*/
.fields {
display: flex;
position: relative;
height: 100%;
margin-left: -1rem;
}
/**
* [disbled]
*/
[disabled] + .fields {
pointer-events: none;
}
/** Cell
---------------------------------------------------------*/
.cell {
position: relative;
height: 100%;
margin-left: 1rem;
flex: 1;
/* dynamic */
--gi-border-color:
var(--input-border-color,
var(--border-color,
var(--background-plus,
#e7e7e7)));
border-color:
var(--gi-border-color);
border:
var(--input-border,
var(--border,
1px solid var(--gi-border-color)));
background:
var(--text-input-background,
var(--input-background,
var(--background-minus,
#fff)));
}
/**
* [disbled]
*/
[disabled] + .fields .cell {
background: none;
}
/** Dot
---------------------------------------------------------*/
.cell::after {
content: '';
position: absolute;
left: 50%;
top: 50%;
width: 14px;
height: 14px;
margin: -7px;
border-radius: 50%;
opacity: 0;
/* dynamic */
background:
var(--text-color);
}
/**
* .populated
*/
.cell.populated::after {
opacity: 1;
}
.cell::before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 3px;
visibility: hidden;
background: var(--highlight-color, #000);
}
/**
* input:focus
*/
input:focus + .fields .cell::before {
visibility: visible;
}
</style>
`
});
})})(((n,w)=>{return(typeof define)[0]=='f'&&define.amd?define:(typeof module)[0]=='o'?c =>{c(require,exports,module)}:c=>{var m={exports:{}},r=n=>w[n];w[n]=c(r,m.exports,m)||m.exports;};})('gaia-text-input-pin',this));/*jshint ignore:line*/

View file

@ -0,0 +1,366 @@
(define=>{define((require,exports,module)=>{
'use strict';
/**
* Dependencies
*/
var component = require('gaia-component');
require('gaia-icons'); // Load gaia-icons
/**
* Mini logger
*
* @type {Function}
*/
var debug = 0 ? (...args) => console.log('[GaiaTextInput]', ...args) : () => {};
/**
* Exports
*/
module.exports = component.register('gaia-text-input', {
created() {
this.setupShadowRoot();
this.els = {
inner: this.shadowRoot.querySelector('.inner'),
input: this.shadowRoot.querySelector('input'),
clear: this.shadowRoot.querySelector('.clear')
};
this.type = this.getAttribute('type');
this.disabled = this.hasAttribute('disabled');
this.clearable = this.hasAttribute('clearable');
this.placeholder = this.getAttribute('placeholder');
this.required = this.getAttribute('required');
this.value = this.getAttribute('value');
// Don't take focus from the input field
this.els.clear.addEventListener('mousedown', e => e.preventDefault());
this.els.clear.addEventListener('click', e => this.clear(e));
this.els.input.addEventListener('input', e => this.onInput(e));
this.els.input.addEventListener('focus', e => this.onFocus(e));
this.els.input.addEventListener('blur', e => this.onBlur(e));
},
/**
* Clear the field.
*
* @public
*/
clear() {
debug('clear');
this.value = '';
this.emit('clear');
},
/**
* Focus the field.
*
* @public
*/
focus() {
debug('focus');
this.els.input.focus();
},
/**
* Unfocus the field.
*
* @public
*/
blur() {
debug('blur');
this.els.input.blur();
},
/**
* Runs when the field is focused.
*
* @private
*/
onFocus() {
debug('on focus');
this.els.inner.classList.add('focused');
this.emit('focus');
},
/**
* Runs when the field is unfocused.
*
* @private
*/
onBlur() {
debug('on blur');
this.els.inner.classList.remove('focused');
this.emit('blur');
},
/**
* Runs when the value of the
* input is manually changed.
*
* @private
*/
onInput() {
debug('on input');
this.onValueChanged();
},
/**
* Runs when the values changes
* programatically or via keystrokes.
*
* @private
*/
onValueChanged() {
debug('value changed');
var hasValue = !!this.value.length;
this.els.inner.classList.toggle('has-value', hasValue);
this.emit('input');
},
/**
* Emit a DOM event on the component.
*
* @param {String} name
* @param {*} detail
* @private
*/
emit(name, detail) {
var e = new CustomEvent(name, { detail: detail });
this.dispatchEvent(e);
},
/**
* Attributes
*/
attrs: {
type: {
get: function() { return this.els.input.getAttribute('type'); },
set: function(value) {
if (!value) { return; }
this.els.inner.setAttribute('type', value);
this.els.input.setAttribute('type', value);
}
},
placeholder: {
get: function() { return this.field.placeholder; },
set: function(value) {
if (!value && value !== '') { return; }
this.els.input.placeholder = value;
}
},
clearable: {
get: function() { return this._clearable; },
set: function(value) {
var clearable = !!(value === '' || value);
if (clearable === this.clearable) { return; }
if (clearable) this.setAttr('clearable', '');
else this.removeAttr('clearable');
this._clearable = clearable;
}
},
value: {
get: function() { return this.els.input.value; },
set: function(value) {
debug('set value', value);
this.els.input.value = value;
this.onValueChanged();
}
},
required: {
get: function() { return this.els.input.required; },
set: function(value) { this.els.input.required = value; }
},
maxlength: {
get: function() { return this.els.input.getAttribute('maxlength'); },
set: function(value) { this.els.input.setAttribute('maxlength', value); }
},
disabled: {
get: function() { return this.els.input.disabled; },
set: function(value) {
value = !!(value === '' || value);
this.els.input.disabled = value;
}
}
},
template: `
<div class="inner">
<content select="label"></content>
<div class="fields">
<input type="text"/>
<button class="clear" tabindex="-1"></button>
<div class="focus"></div>
</div>
</div>
<style>
:host {
display: block;
height: 40px;
margin-top: var(--base-m, 18px);
margin-bottom: var(--base-m, 18px);
font-size: 17px;
overflow: hidden;
--this-background:
var(--text-input-background,
var(--input-background,
var(--background-minus,
#fff)));
--this-border-color:
var(--input-border-color,
var(--border-color,
var(--background-plus,
#e7e7e7)));
}
.inner {
height: 100%;
}
label {
font-size: 14px;
display: block;
margin: 0 0 4px 16px;
}
[disabled] label {
opacity: 0.3;
}
.fields {
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
border-color:
var(--this-border-color);
border:
var(--input-border,
var(--border,
1px solid var(--this-border-color)));
}
[type='search'] .fields {
border-radius: 30px;
overflow: hidden;
}
input {
display: block;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0 16px;
margin: 0;
border: 0;
font: inherit;
resize: none;
/* Dynamic */
color: var(--text-color, #000);
background: var(--this-background);
}
input[disabled] {
background: var(--background);
}
::-moz-placeholder {
font-style: italic;
color:
var(--input-placeholder-color, #909ca7);
}
.clear {
position: absolute;
offset-inline-end: 0;
top: 0;
display: none;
width: 18px;
height: 18px;
padding: 0;
margin: 0;
border: solid 10px transparent;
box-sizing: content-box;
border-radius: 50%;
color: var(--background);
cursor: pointer;
background: var(--input-clear-background, #999);
background-clip: padding-box;
opacity: 0;
pointer-events: none;
}
[clearable] .clear {
display: block;
}
[clearable].has-value.focused .clear {
pointer-events: all;
transition: opacity 200ms;
opacity: 1;
}
.clear:before {
content: 'close';
display: block;
font: normal 500 19px/17px 'gaia-icons';
text-rendering: optimizeLegibility;
}
.focus {
position: absolute;
left: 0;
bottom: 0px;
width: 100%;
height: 3px;
transition: transform 200ms;
transform: scaleX(0);
visibility: hidden;
background: var(--highlight-color, #000);
}
[type='search'] .focus {
border-radius: 0 0 60px 60px;
left: 10px;
width: calc(100% - 20px);
}
/**
* .focused
*/
.focused .focus {
transform: scaleX(1);
transition-delay: 200ms;
visibility: visible;
}
</style>`
});
})})(((n,w)=>{return(typeof define)[0]=='f'&&define.amd?define:(typeof module)[0]=='o'?c =>{c(require,exports,module)}:c=>{var m={exports:{}},r=n=>w[n];w[n]=c(r,m.exports,m)||m.exports;};})('gaia-text-input',this));/*jshint ignore:line*/

View file

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>&lt;gaia-text-input&gt;</title>
<meta name="description" content="gaia-text-input demo">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<link rel="stylesheet" type="text/css" href="bower_components/base/base.css">
<link rel="stylesheet" type="text/css" href="bower_components/gaia-icons/gaia-icons.css">
<link rel="stylesheet" type="text/css" href="bower_components/gaia-theme/gaia-theme.css">
<link rel="stylesheet" type="text/css" href="bower_components/gaia-fonts/style.css">
<script src="bower_components/gaia-theme/lib/gaia-theme-selector.js"></script>
<script src="bower_components/gaia-component/gaia-component.js"></script>
<script src="gaia-text-input.js"></script>
<script src="gaia-text-input-multiline.js"></script>
<script src="gaia-text-input-pin.js"></script>
<style type="text/css">
body {
padding: 48px 24px 24px;
}
</style>
</head>
<body>
<gaia-theme-selector></gaia-theme-selector>
<button id="btn">Focus</button>
<gaia-text-input id="field" placeholder="Default"></gaia-text-input>
<gaia-text-input placeholder="Search" type="search"></gaia-text-input>
<gaia-text-input placeholder="Email" type="email" clearable></gaia-text-input>
<gaia-text-input-multiline placeholder="Multiline"></gaia-text-input-multiline>
<gaia-text-input-pin length="4"></gaia-text-input-pin>
<gaia-text-input placeholder="Disabled" disabled></gaia-text-input>
<gaia-text-input placeholder="Search" type="search" disabled></gaia-text-input>
<gaia-text-input placeholder="Email" type="email" clearable disabled></gaia-text-input>
<gaia-text-input-multiline placeholder="Multiline" disabled></gaia-text-input-multiline>
<gaia-text-input-pin length="4" disabled></gaia-text-input-pin>
<!-- <gaia-text-input-password></gaia-text-input-password> -->
<script>
btn.onclick = e => field.focus();
</script>
</body>
</html>

View file

@ -0,0 +1,4 @@
{
"name": "gaia-text-input demo",
"launch_path": "/index.html"
}

View file

@ -0,0 +1,34 @@
{
"name": "gaia-text-input",
"version": "0.2.1",
"homepage": "https://github.com/gaia-components/gaia-text-input",
"license": "ISC",
"main": "gaia-text-input.js",
"directories": {
"test": "test"
},
"devDependencies": {
"bower": "^1.6.5",
"jshint": "^2.8.0",
"karma": "^0.13.15",
"karma-firefox-launcher": "^0.1.6",
"karma-mocha": "^0.2.0",
"karma-sinon-chai": "^1.1.0",
"mocha": "^2.3.3"
},
"scripts": {
"postinstall": "bower install",
"test": "npm run --silent test-unit && npm run --silent test-lint",
"test-lint": "./node_modules/jshint/bin/jshint *.js",
"test-unit": "./node_modules/karma/bin/karma start test/karma.conf.js --single-run",
"test-unit-dev": "./node_modules/karma/bin/karma start test/karma.conf.js",
"gh-pages": "git co gh-pages; git merge master; git push upstrea gh-pages; git co -"
},
"repository": {
"type": "git",
"url": "git://github.com/gaia-components/gaia-text-input.git"
},
"bugs": {
"url": "https://github.com/gaia-components/gaia-text-input/issues"
}
}