JavaScript modularization

This commit is contained in:
Lucas Larroche 2021-07-09 17:42:10 +07:00
parent 366e0a55d6
commit 9575624834
21 changed files with 1629 additions and 1048 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
*.DS_Store *.DS_Store
TODO.md TODO.md
prepros-6.config prepros.config
test.html test.html

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
css/pico.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1238,7 +1238,8 @@
</main><!-- ./ Main --> </main><!-- ./ Main -->
<!-- JavaScript --> <!-- JavaScript -->
<script src="js/pico.docs.min.js"></script> <script src="https://unpkg.com/most-visible@1.5.0/dist/most-visible.min.js"></script>
<script type="module" src="js/pico.docs.min.js"></script>
</body> </body>

View file

@ -0,0 +1,30 @@
/*
* Aside adjustment
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
export const aside = {
// Config
_minWidth: '992px',
_targets: {
nav: 'aside nav',
details: 'aside details',
},
// Init
init() {
if (window.matchMedia('(min-width: ' + this._minWidth + ')').matches) {
let nav = document.querySelector(this._targets.nav);
let details = document.querySelectorAll(this._targets.details);
if (nav.clientHeight < nav.scrollHeight) {
details.forEach(function(detail) {
detail.removeAttribute("open");
});
}
}
}
}

View file

@ -0,0 +1,177 @@
/*
* Color Picker
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
export const colorPicker = {
// Config
_colors: null,
_buttonsTarget: '#customization article[data-theme="generated"]',
_selectorButton: '#customization button[data-color]',
_selectorSection: '#customization',
_buttons: null,
_generatedStyles: null,
// Set colors
set colors(colors) {
this._colors = colors;
},
// Init
init() {
this.generateButtons();
this.setActiveButton('pink');
this.generateTheme('pink');
},
// Generate Buttons
generateButtons() {
// Init
let innerButtons = '';
let innerStyles = '';
// Loop colors
for (const color in this._colors) {
// Buttons
innerButtons += '<button data-color="'+ color +'" aria-label="Activate '+ color +' theme"></button>';
// Styles
innerStyles += `
button[data-color="${color}"] {
background-color: ${this._colors[color]['600']};
}
[data-theme="light"] button[data-color="${color}"]:hover,
[data-theme="light"] button[data-color="${color}"]:active,
[data-theme="light"] button[data-color="${color}"]:focus {
background-color: ${this._colors[color]['700']}; '
}
[data-theme="dark"] button[data-color="${color}"]:hover,
[data-theme="dark"] button[data-color="${color}"]:active,
[data-theme="dark"] button[data-color="${color}"]:focus {
background-color: ${this._colors[color]['500']};
}`;
}
// Insert buttons
let containerButtons = document.createElement('FIGURE');
containerButtons.innerHTML = innerButtons;
document.querySelector(this._buttonsTarget).before(containerButtons);
// Buttons listeners
this._buttons = document.querySelectorAll(this._selectorButton);
this._buttons.forEach(function(button) {
button.addEventListener('click', function(event) {
let color = event.target.getAttribute('data-color');
this.setActiveButton(color);
this.generateTheme(color);
}.bind(this), false);
}.bind(this));
// Insert CSS Styles
let containerStyles = document.createElement('STYLE');
containerStyles.setAttribute('title', 'color-picker');
this._generatedStyles = this.minifyCSS(innerStyles);
containerStyles.innerHTML = this._generatedStyles;
document.querySelector('head').appendChild(containerStyles);
},
// Set active button
setActiveButton(color) {
// Remove all active states
this._buttons.forEach(function(button) {
button.removeAttribute('class');
}.bind(this));
// Set active state
let buttonPicked = document.querySelector(this._selectorButton + '[data-color="' + color + '"]');
buttonPicked.setAttribute('class', 'picked');
},
// Set active button
generateTheme(color) {
let name = color;
let data = this._colors[color];
// 1. Update name and colors in demo code
let swaps = {
'.name': name.charAt(0).toUpperCase() + name.substring(1) + ' ',
'.c500': data[500],
'.c600': data[600],
'.c700': data[700],
'.c600-outline-light': this.hexToRgbA(data[600], .125),
'.c600-outline-dark': this.hexToRgbA(data[600], .25),
'.inverse': data['inverse'],
}
Object.keys(swaps).forEach(function(swap) {
let targets = document.querySelectorAll(this._selectorSection + ' ' + swap);
targets.forEach(function(target) {
target.innerHTML = swaps[swap];
}.bind(this));
}.bind(this));
// 2. Update CSS Styles
const innerStyles = `
[data-theme="generated"] {
--h4-color: ${data[700]};
--primary: ${data[600]};
--primary-hover: ${data[700]};
--primary-focus: ${this.hexToRgbA(data[600], .125)};
--primary-inverse: ${data['inverse']};
}
@media only screen and (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) [data-theme="generated"] {
--h4-color: ${data[400]};
--primary: ${data[600]};
--primary-hover: ${data[500]};
--primary-focus: ${this.hexToRgbA(data[600], .25)};
--primary-inverse: ${data['inverse']};
}
}
[data-theme="dark"] [data-theme="generated"] {
--h4-color: ${data[500]};
--primary: ${data[600]};
--primary-hover: ${data[500]};
--primary-focus: ${this.hexToRgbA(data[600], .25)};
--primary-inverse: ${data['inverse']};
}
[data-theme="generated"] {
--form-element-active-border-color: var(--primary);
--form-element-focus-color: var(--primary-focus);
--switch-color: var(--primary-inverse);
--switch-checked-background-color: var(--primary);
}`;
document.querySelector('style[title="color-picker"]').innerHTML = this._generatedStyles + this.minifyCSS(innerStyles);
},
// Minify CSS
minifyCSS(css) {
return css.replace(/^ +/gm, '')
},
// Hexadecimal to Rgba
hexToRgbA(hex, alpha) {
var c;
if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c= hex.substring(1).split('');
if(c.length== 3) {
c= [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c= '0x' + c.join('');
return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
}
throw new Error('Bad Hex');
}
}

104
docs/js/components/grid.js Normal file
View file

@ -0,0 +1,104 @@
/*
* Grid Interaction
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
export const grid = {
// Config
_buttons: {
text: {
add: 'Add column',
remove: 'Remove column'
},
target: '#grids article'
},
_grid: {
current: 4,
min: 1,
max: 12,
gridTarget: '#grids .grid',
codeTarget: '#grids pre code'
},
// Init
init() {
this.addButtons();
this.generateGrid()
},
// Add buttons
addButtons() {
// Insert buttons
let buttons = document.createElement('P');
buttons.innerHTML = `
<button class="secondary add">
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12">'</line>
</svg>
${this._buttons.text.add}
</button>
<button class="secondary remove">
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
${this._buttons.text.remove}
</button>`;
document.querySelector(this._buttons.target).before(buttons);
// Add button listener
document.querySelector('#grids button.add').addEventListener('click', function() {
this.addColumn();
}.bind(this), false);
// Remove button listener
document.querySelector('#grids button.remove').addEventListener('click', function() {
this.removeColumn();
}.bind(this), false);
},
// Generate grid
generateGrid() {
// Config
let htmlInner = '';
let codeInner = '&lt;<b>div</b> <i>class</i>=<u>"grid"</u>&gt;\n';
// Build
for (let col = 0; col < this._grid.current; col++) {
htmlInner += '<div>' + (col + 1) + '</div>';
codeInner += ' &lt;<b>div</b>&gt;' + (col+1) + '&lt;/<b>div</b>&gt;\n';
}
// Display
codeInner += '&lt;/<b>div</b>&gt;';
document.querySelector(this._grid.gridTarget).innerHTML = htmlInner;
document.querySelector(this._grid.codeTarget).innerHTML = codeInner;
},
// Add column
addColumn() {
if (this._grid.current < this._grid.max) {
this._grid.current++;
this.generateGrid();
}
},
// Remove column
removeColumn() {
if (this._grid.current > this._grid.min) {
this._grid.current--;
this.generateGrid();
}
}
};

View file

@ -0,0 +1,301 @@
// Source: https://material.io/design/color/the-color-system.html
export const materialDesignColors = {
red: {
50: "#ffebee",
100: "#ffcdd2",
200: "#ef9a9a",
300: "#e57373",
400: "#ef5350",
500: "#f44336",
600: "#e53935",
700: "#d32f2f",
800: "#c62828",
900: "#b71c1c",
a100: "#ff8a80",
a200: "#ff5252",
a400: "#ff1744",
a700: "#d50000",
inverse: "#FFF"
},
pink: {
50: "#fce4ec",
100: "#f8bbd0",
200: "#f48fb1",
300: "#f06292",
400: "#ec407a",
500: "#e91e63",
600: "#d81b60",
700: "#c2185b",
800: "#ad1457",
900: "#880e4f",
a100: "#ff80ab",
a200: "#ff4081",
a400: "#f50057",
a700: "#c51162",
inverse: "#FFF"
},
purple: {
50: "#f3e5f5",
100: "#e1bee7",
200: "#ce93d8",
300: "#ba68c8",
400: "#ab47bc",
500: "#9c27b0",
600: "#8e24aa",
700: "#7b1fa2",
800: "#6a1b9a",
900: "#4a148c",
a100: "#ea80fc",
a200: "#e040fb",
a400: "#d500f9",
a700: "#aa00ff",
inverse: "#FFF"
},
"deep-purple": {
50: "#ede7f6",
100: "#d1c4e9",
200: "#b39ddb",
300: "#9575cd",
400: "#7e57c2",
500: "#673ab7",
600: "#5e35b1",
700: "#512da8",
800: "#4527a0",
900: "#311b92",
a100: "#b388ff",
a200: "#7c4dff",
a400: "#651fff",
a700: "#6200ea",
inverse: "#FFF"
},
indigo: {
50: "#e8eaf6",
100: "#c5cae9",
200: "#9fa8da",
300: "#7986cb",
400: "#5c6bc0",
500: "#3f51b5",
600: "#3949ab",
700: "#303f9f",
800: "#283593",
900: "#1a237e",
a100: "#8c9eff",
a200: "#536dfe",
a400: "#3d5afe",
a700: "#304ffe",
inverse: "#FFF"
},
blue: {
50: "#e3f2fd",
100: "#bbdefb",
200: "#90caf9",
300: "#64b5f6",
400: "#42a5f5",
500: "#2196f3",
600: "#1e88e5",
700: "#1976d2",
800: "#1565c0",
900: "#0d47a1",
a100: "#82b1ff",
a200: "#448aff",
a400: "#2979ff",
a700: "#2962ff",
inverse: "#FFF"
},
"light-blue": {
50: "#e1f5fe",
100: "#b3e5fc",
200: "#81d4fa",
300: "#4fc3f7",
400: "#29b6f6",
500: "#03a9f4",
600: "#039be5",
700: "#0288d1",
800: "#0277bd",
900: "#01579b",
a100: "#80d8ff",
a200: "#40c4ff",
a400: "#00b0ff",
a700: "#0091ea",
inverse: "#FFF"
},
cyan: {
50: "#e0f7fa",
100: "#b2ebf2",
200: "#80deea",
300: "#4dd0e1",
400: "#26c6da",
500: "#00bcd4",
600: "#00acc1",
700: "#0097a7",
800: "#00838f",
900: "#006064",
a100: "#84ffff",
a200: "#18ffff",
a400: "#00e5ff",
a700: "#00b8d4",
inverse: "#FFF"
},
teal: {
50: "#e0f2f1",
100: "#b2dfdb",
200: "#80cbc4",
300: "#4db6ac",
400: "#26a69a",
500: "#009688",
600: "#00897b",
700: "#00796b",
800: "#00695c",
900: "#004d40",
a100: "#a7ffeb",
a200: "#64ffda",
a400: "#1de9b6",
a700: "#00bfa5",
inverse: "#FFF"
},
green: {
50: "#e8f5e9",
100: "#c8e6c9",
200: "#a5d6a7",
300: "#81c784",
400: "#66bb6a",
500: "#4caf50",
600: "#43a047",
700: "#388e3c",
800: "#2e7d32",
900: "#1b5e20",
a100: "#b9f6ca",
a200: "#69f0ae",
a400: "#00e676",
a700: "#00c853",
inverse: "#FFF"
},
"light-green": {
50: "#f1f8e9",
100: "#dcedc8",
200: "#c5e1a5",
300: "#aed581",
400: "#9ccc65",
500: "#8bc34a",
600: "#7cb342",
700: "#689f38",
800: "#558b2f",
900: "#33691e",
a100: "#ccff90",
a200: "#b2ff59",
a400: "#76ff03",
a700: "#64dd17",
inverse: "#FFF"
},
lime: {
50: "#f9fbe7",
100: "#f0f4c3",
200: "#e6ee9c",
300: "#dce775",
400: "#d4e157",
500: "#cddc39",
600: "#c0ca33",
700: "#afb42b",
800: "#9e9d24",
900: "#827717",
a100: "#f4ff81",
a200: "#eeff41",
a400: "#c6ff00",
a700: "#aeea00",
inverse: "rgba(0, 0, 0, 0.75)"
},
yellow: {
50: "#fffde7",
100: "#fff9c4",
200: "#fff59d",
300: "#fff176",
400: "#ffee58",
500: "#ffeb3b",
600: "#fdd835",
700: "#fbc02d",
800: "#f9a825",
900: "#f57f17",
a100: "#ffff8d",
a200: "#ffff00",
a400: "#ffea00",
a700: "#ffd600",
inverse: "rgba(0, 0, 0, 0.75)"
},
amber: {
50: "#fff8e1",
100: "#ffecb3",
200: "#ffe082",
300: "#ffd54f",
400: "#ffca28",
500: "#ffc107",
600: "#ffb300",
700: "#ffa000",
800: "#ff8f00",
900: "#ff6f00",
a100: "#ffe57f",
a200: "#ffd740",
a400: "#ffc400",
a700: "#ffab00",
inverse: "rgba(0, 0, 0, 0.75)"
},
orange: {
50: "#fff3e0",
100: "#ffe0b2",
200: "#ffcc80",
300: "#ffb74d",
400: "#ffa726",
500: "#ff9800",
600: "#fb8c00",
700: "#f57c00",
800: "#ef6c00",
900: "#e65100",
a100: "#ffd180",
a200: "#ffab40",
a400: "#ff9100",
a700: "#ff6d00",
inverse: "#FFF"
},
"deep-orange": {
50: "#fbe9e7",
100: "#ffccbc",
200: "#ffab91",
300: "#ff8a65",
400: "#ff7043",
500: "#ff5722",
600: "#f4511e",
700: "#e64a19",
800: "#d84315",
900: "#bf360c",
a100: "#ff9e80",
a200: "#ff6e40",
a400: "#ff3d00",
a700: "#dd2c00",
inverse: "#FFF"
},
grey: {
50: "#fafafa",
100: "#f5f5f5",
200: "#eeeeee",
300: "#e0e0e0",
400: "#bdbdbd",
500: "#9e9e9e",
600: "#757575",
700: "#616161",
800: "#424242",
900: "#212121",
inverse: "#FFF"
},
"blue-grey": {
50: "#eceff1",
100: "#cfd8dc",
200: "#b0bec5",
300: "#90a4ae",
400: "#78909c",
500: "#607d8b",
600: "#546e7a",
700: "#455a64",
800: "#37474f",
900: "#263238",
inverse: "#FFF"
}
};

View file

@ -0,0 +1,63 @@
/*
* Scrollspy
* Automatically update nav targets based on scroll position
*
* Require `most-visible.js` (https://github.com/andyexeter/most-visible)
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
export const scrollspy = {
// Config
_minWidth: '992px',
_interval: 75,
_targets: {
sections: '[role="document"] > section',
nav: 'main aside nav',
active: 'active',
},
// Init
init() {
if (window.matchMedia('(min-width: ' + this._minWidth + ')').matches) {
this.setActiveNav();
this.scrollStop();
}
},
// Set active section in nav
setActiveNav() {
// Get active section
let currentSection = mostVisible(this._targets.sections).getAttribute('id');
// Remove all active states
let links = document.querySelectorAll(this._targets.nav + ' a.' + this._targets.active);
links.forEach(function(link) {
link.classList.remove(this._targets.active);
}.bind(this));
// Set active state
let activeLink = document.querySelector(this._targets.nav + ' a[href="#' + currentSection + '"]');
activeLink.classList.add(this._targets.active);
// Open details parent
activeLink.closest('details').setAttribute('open', '');
},
// Scroll stop
scrollStop() {
let isScrolling;
window.addEventListener('scroll', function (event) {
window.clearTimeout(isScrolling);
isScrolling = setTimeout(function() {
this.setActiveNav();
}.bind(this), this._interval);
}.bind(this), false);
}
}

View file

@ -0,0 +1,105 @@
/*
* Theme switcher
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
export const themeSwitcher = {
// Config
_change: {
light: '<i>Turn on dark mode</i>',
dark: '<i>Turn off dark mode</i>'
},
_buttonsTarget: '.theme-switcher',
_scheme: 'auto',
// Init
init() {
this.scheme = this._scheme;
this.initSwitchers();
},
// Prefered color scheme
get preferedColorScheme() {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
else {
return 'light';
}
},
// Init switchers
initSwitchers() {
const buttons = document.querySelectorAll(this._buttonsTarget);
buttons.forEach(function(button) {
button.addEventListener('click', function(event) {
if (this._scheme == 'dark') {
this.scheme = 'light';
}
else {
this.scheme = 'dark';
}
}.bind(this), false);
}.bind(this));
},
// Add new button
addButton(config) {
// Insert Switcher
let button = document.createElement(config.tag);
button.className = config.class;
document.querySelector(config.target).appendChild(button);
},
// Set scheme
set scheme(scheme) {
if (scheme == 'auto') {
if (this.preferedColorScheme == 'dark') {
this._scheme = 'dark';
}
else {
this._scheme = 'light';
}
}
// Set to Dark
else if (scheme == 'dark' || scheme == 'light') {
this._scheme = scheme;
}
// Set to Apply theme
this.applyScheme();
},
// Apply scheme
applyScheme() {
// Root attribute
document.querySelector('html').setAttribute('data-theme', this._scheme);
// Buttons text
const buttons = document.querySelectorAll(this._buttonsTarget);
let text;
buttons.forEach(function(button) {
if (this._scheme == 'dark') {
text = this._change.dark;
}
else {
text = this._change.light;
}
button.innerHTML = text;
button.setAttribute('aria-label', text.replace(/<[^>]*>?/gm, ''));
}.bind(this));
}
}

View file

@ -1,13 +1,35 @@
/*! /*
* Add some magic to Pico docs * Add some magic to Pico docs
* *
* Pico.css - https://picocss.com * Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT * Copyright 2019-2021 - Licensed under MIT
*/ */
// @append src/aside.js // Imports
// @append src/theme-switcher.js import { aside } from './components/aside.js';
// @append src/grid.js import { themeSwitcher } from './components/theme-switcher.js';
// @append src/color-picker.js import { materialDesignColors } from './components/material-design-colors.js';
// @append src/most-visible.js import { colorPicker } from './components/color-picker.js';
// @append src/scrollspy.js import { grid } from './components/grid.js';
import { scrollspy } from './components/scrollspy.js';
// Aside initial state
aside.init();
// Theme switcher
themeSwitcher.addButton({
tag: 'BUTTON',
class: 'contrast switcher theme-switcher',
target: 'body',
});
themeSwitcher.init();
// Color Picker
colorPicker.colors = materialDesignColors;
colorPicker.init();
// Grid Interaction
grid.init();
// Scrollspy
scrollspy.init();

File diff suppressed because one or more lines are too long

View file

@ -1,23 +0,0 @@
/*!
* Aside adjustment
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
(function() {
if (window.matchMedia("(min-width: 992px)").matches) {
// Close details if aside > nav have a scrollbar
var nav = document.querySelector("aside nav");
var navDetails = document.querySelectorAll("aside details");
if (nav.clientHeight < nav.scrollHeight) {
for (var i = 1; i < navDetails.length; i++) {
navDetails[i].removeAttribute("open");
}
}
}
})();

View file

@ -1,508 +0,0 @@
/*!
* Color Picker
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
(function() {
/**
* Config
*/
var colors = {
target: '#customization article[data-theme="generated"]', // Buttons inserted before target
selectorButton: '#customization button[data-color]', // Button selector in Dom
selectorTheme: '#customization', // Theme selector in Dom
styles: '',
// Source: https://material.io/design/color/the-color-system.html
system: {
"red": {
"50": "#ffebee",
"100": "#ffcdd2",
"200": "#ef9a9a",
"300": "#e57373",
"400": "#ef5350",
"500": "#f44336",
"600": "#e53935",
"700": "#d32f2f",
"800": "#c62828",
"900": "#b71c1c",
"a100": "#ff8a80",
"a200": "#ff5252",
"a400": "#ff1744",
"a700": "#d50000",
"inverse": "#FFF"
},
"pink": {
"50": "#fce4ec",
"100": "#f8bbd0",
"200": "#f48fb1",
"300": "#f06292",
"400": "#ec407a",
"500": "#e91e63",
"600": "#d81b60",
"700": "#c2185b",
"800": "#ad1457",
"900": "#880e4f",
"a100": "#ff80ab",
"a200": "#ff4081",
"a400": "#f50057",
"a700": "#c51162",
"inverse": "#FFF"
},
"purple": {
"50": "#f3e5f5",
"100": "#e1bee7",
"200": "#ce93d8",
"300": "#ba68c8",
"400": "#ab47bc",
"500": "#9c27b0",
"600": "#8e24aa",
"700": "#7b1fa2",
"800": "#6a1b9a",
"900": "#4a148c",
"a100": "#ea80fc",
"a200": "#e040fb",
"a400": "#d500f9",
"a700": "#aa00ff",
"inverse": "#FFF"
},
"deep-purple": {
"50": "#ede7f6",
"100": "#d1c4e9",
"200": "#b39ddb",
"300": "#9575cd",
"400": "#7e57c2",
"500": "#673ab7",
"600": "#5e35b1",
"700": "#512da8",
"800": "#4527a0",
"900": "#311b92",
"a100": "#b388ff",
"a200": "#7c4dff",
"a400": "#651fff",
"a700": "#6200ea",
"inverse": "#FFF"
},
"indigo": {
"50": "#e8eaf6",
"100": "#c5cae9",
"200": "#9fa8da",
"300": "#7986cb",
"400": "#5c6bc0",
"500": "#3f51b5",
"600": "#3949ab",
"700": "#303f9f",
"800": "#283593",
"900": "#1a237e",
"a100": "#8c9eff",
"a200": "#536dfe",
"a400": "#3d5afe",
"a700": "#304ffe",
"inverse": "#FFF"
},
"blue": {
"50": "#e3f2fd",
"100": "#bbdefb",
"200": "#90caf9",
"300": "#64b5f6",
"400": "#42a5f5",
"500": "#2196f3",
"600": "#1e88e5",
"700": "#1976d2",
"800": "#1565c0",
"900": "#0d47a1",
"a100": "#82b1ff",
"a200": "#448aff",
"a400": "#2979ff",
"a700": "#2962ff",
"inverse": "#FFF"
},
"light-blue": {
"50": "#e1f5fe",
"100": "#b3e5fc",
"200": "#81d4fa",
"300": "#4fc3f7",
"400": "#29b6f6",
"500": "#03a9f4",
"600": "#039be5",
"700": "#0288d1",
"800": "#0277bd",
"900": "#01579b",
"a100": "#80d8ff",
"a200": "#40c4ff",
"a400": "#00b0ff",
"a700": "#0091ea",
"inverse": "#FFF"
},
"cyan": {
"50": "#e0f7fa",
"100": "#b2ebf2",
"200": "#80deea",
"300": "#4dd0e1",
"400": "#26c6da",
"500": "#00bcd4",
"600": "#00acc1",
"700": "#0097a7",
"800": "#00838f",
"900": "#006064",
"a100": "#84ffff",
"a200": "#18ffff",
"a400": "#00e5ff",
"a700": "#00b8d4",
"inverse": "#FFF"
},
"teal": {
"50": "#e0f2f1",
"100": "#b2dfdb",
"200": "#80cbc4",
"300": "#4db6ac",
"400": "#26a69a",
"500": "#009688",
"600": "#00897b",
"700": "#00796b",
"800": "#00695c",
"900": "#004d40",
"a100": "#a7ffeb",
"a200": "#64ffda",
"a400": "#1de9b6",
"a700": "#00bfa5",
"inverse": "#FFF"
},
"green": {
"50": "#e8f5e9",
"100": "#c8e6c9",
"200": "#a5d6a7",
"300": "#81c784",
"400": "#66bb6a",
"500": "#4caf50",
"600": "#43a047",
"700": "#388e3c",
"800": "#2e7d32",
"900": "#1b5e20",
"a100": "#b9f6ca",
"a200": "#69f0ae",
"a400": "#00e676",
"a700": "#00c853",
"inverse": "#FFF"
},
"light-green": {
"50": "#f1f8e9",
"100": "#dcedc8",
"200": "#c5e1a5",
"300": "#aed581",
"400": "#9ccc65",
"500": "#8bc34a",
"600": "#7cb342",
"700": "#689f38",
"800": "#558b2f",
"900": "#33691e",
"a100": "#ccff90",
"a200": "#b2ff59",
"a400": "#76ff03",
"a700": "#64dd17",
"inverse": "#FFF"
},
"lime": {
"50": "#f9fbe7",
"100": "#f0f4c3",
"200": "#e6ee9c",
"300": "#dce775",
"400": "#d4e157",
"500": "#cddc39",
"600": "#c0ca33",
"700": "#afb42b",
"800": "#9e9d24",
"900": "#827717",
"a100": "#f4ff81",
"a200": "#eeff41",
"a400": "#c6ff00",
"a700": "#aeea00",
"inverse": "rgba(0, 0, 0, 0.75)"
},
"yellow": {
"50": "#fffde7",
"100": "#fff9c4",
"200": "#fff59d",
"300": "#fff176",
"400": "#ffee58",
"500": "#ffeb3b",
"600": "#fdd835",
"700": "#fbc02d",
"800": "#f9a825",
"900": "#f57f17",
"a100": "#ffff8d",
"a200": "#ffff00",
"a400": "#ffea00",
"a700": "#ffd600",
"inverse": "rgba(0, 0, 0, 0.75)"
},
"amber": {
"50": "#fff8e1",
"100": "#ffecb3",
"200": "#ffe082",
"300": "#ffd54f",
"400": "#ffca28",
"500": "#ffc107",
"600": "#ffb300",
"700": "#ffa000",
"800": "#ff8f00",
"900": "#ff6f00",
"a100": "#ffe57f",
"a200": "#ffd740",
"a400": "#ffc400",
"a700": "#ffab00",
"inverse": "rgba(0, 0, 0, 0.75)"
},
"orange": {
"50": "#fff3e0",
"100": "#ffe0b2",
"200": "#ffcc80",
"300": "#ffb74d",
"400": "#ffa726",
"500": "#ff9800",
"600": "#fb8c00",
"700": "#f57c00",
"800": "#ef6c00",
"900": "#e65100",
"a100": "#ffd180",
"a200": "#ffab40",
"a400": "#ff9100",
"a700": "#ff6d00",
"inverse": "#FFF"
},
"deep-orange": {
"50": "#fbe9e7",
"100": "#ffccbc",
"200": "#ffab91",
"300": "#ff8a65",
"400": "#ff7043",
"500": "#ff5722",
"600": "#f4511e",
"700": "#e64a19",
"800": "#d84315",
"900": "#bf360c",
"a100": "#ff9e80",
"a200": "#ff6e40",
"a400": "#ff3d00",
"a700": "#dd2c00",
"inverse": "#FFF"
},
"grey": {
"50": "#fafafa",
"100": "#f5f5f5",
"200": "#eeeeee",
"300": "#e0e0e0",
"400": "#bdbdbd",
"500": "#9e9e9e",
"600": "#757575",
"700": "#616161",
"800": "#424242",
"900": "#212121",
"inverse": "#FFF"
},
"blue-grey": {
"50": "#eceff1",
"100": "#cfd8dc",
"200": "#b0bec5",
"300": "#90a4ae",
"400": "#78909c",
"500": "#607d8b",
"600": "#546e7a",
"700": "#455a64",
"800": "#37474f",
"900": "#263238",
"inverse": "#FFF"
}
}
}
/**
* Init
*/
generateButtons(colors.system);
pickColor('pink', colors.system['pink']);
/**
* Generate Buttons
*
* @param {object} data
*/
function generateButtons(data) {
// Vars
var colorButtons = '';
// Colors
for (var color in data) {
if (data.hasOwnProperty(color)) {
// Buttons
colorButtons += '<button data-color="'+ color +'" aria-label="Activate '+ color +' theme"></button>';
// CSS Styles
colors.styles += 'button[data-color="'+ color +'"] {'
+ 'background-color: '+ data[color]['600'] +'; '
+ '}'
+ '[data-theme="light"] button[data-color="'+ color +'"]:hover, '
+ '[data-theme="light"] button[data-color="'+ color +'"]:active, '
+ '[data-theme="light"] button[data-color="'+ color +'"]:focus {'
+ 'background-color: '+ data[color]['700'] +'; '
+ '}'
+ '[data-theme="dark"] button[data-color="'+ color +'"]:hover, '
+ '[data-theme="dark"] button[data-color="'+ color +'"]:active, '
+ '[data-theme="dark"] button[data-color="'+ color +'"]:focus {'
+ 'background-color: '+ data[color]['500'] +'; '
+ '}';
}
}
// Insert buttons
var buttons = document.createElement('FIGURE');
buttons.innerHTML = colorButtons;
document.querySelector(colors.target).before(buttons);
// Buttons listeners
var buttonsAll = document.querySelectorAll(colors.selectorButton);
for (var i = 0; i < buttonsAll.length; i++) {
buttonsAll[i].addEventListener('click', function(event) {
buttonColor = event.target.getAttribute('data-color');
pickColor(buttonColor, data[buttonColor]);
}, false);
}
// Insert CSS Styles
var styles = document.createElement('STYLE');
styles.setAttribute('title', 'color-picker');
styles.innerHTML = colors.styles;
document.querySelector('head').appendChild(styles);
}
/**
* Pick Color
*
* @param {string} name
* @param {object} data
*/
function pickColor(name, data) {
// Generate theme
generateTheme(name, data);
// Clear picked state
var buttonsAll = document.querySelectorAll(colors.selectorButton);
for (var i = 0; i < buttonsAll.length; i++) {
buttonsAll[i].removeAttribute("class");
}
// Set Picked state
var buttonPicked = document.querySelector(colors.selectorButton + '[data-color="' + name + '"]');
buttonPicked.setAttribute('class', 'picked');
}
/**
* Generate theme
*
* @param {string} name
* @param {object} data
*/
function generateTheme(name, data) {
// Update name and colors in demo code
var swap = {
'.name' : name.charAt(0).toUpperCase() + name.substring(1) + ' ',
'.c500' : data[500],
'.c600' : data[600],
'.c700' : data[700],
'.c600-outline-light' : hexToRgbA(data[600], .125),
'.c600-outline-dark' : hexToRgbA(data[600], .25),
'.inverse' : data['inverse'],
}
Object.keys(swap).forEach(function(key) {
var target = document.querySelectorAll(colors.selectorTheme + ' ' + key);
for (var i = 0; i < target.length; ++i) {
target[i].innerHTML = swap[key];
}
});
// Update CSS Style
var generatedStyles = '[data-theme="generated"] {'
+ '--h4-color:' + data[700] + ';'
+ '--primary:' + data[600] + ';'
+ '--primary-hover:' + data[700] + ';'
+ '--primary-focus:' + hexToRgbA(data[600], .125) + ';'
+ '--primary-inverse:' + data['inverse'] + ';'
+ '}'
+ '@media only screen and (prefers-color-scheme: dark) {'
+ ':root:not([data-theme="light"]) [data-theme="generated"] {'
+ '--h4-color:' + data[400] + ';'
+ '--primary:' + data[600] + ';'
+ '--primary-hover:' + data[500] + ';'
+ '--primary-focus:' + hexToRgbA(data[600], .25) + ';'
+ '--primary-inverse:' + data['inverse'] + ';'
+ '}'
+ '}'
+ '[data-theme="dark"] [data-theme="generated"] {'
+ '--h4-color:' + data[500] + ';'
+ '--primary:' + data[600] + ';'
+ '--primary-hover:' + data[500] + ';'
+ '--primary-focus:' + hexToRgbA(data[600], .25) + ';'
+ '--primary-inverse:' + data['inverse'] + ';'
+ '}'
+ '[data-theme="generated"] {'
+ '--form-element-active-border-color: var(--primary);'
+ '--form-element-focus-color: var(--primary-focus);'
+ '--switch-color: var(--primary-inverse);'
+ '--switch-checked-background-color: var(--primary);'
+ '}';
// Insert CSS Styles
document.querySelector('style[title="color-picker"]').innerHTML = colors.styles + generatedStyles;
}
/**
* Hexadecimal to Rgba
*
* @param {string} hex
* @param {number} alpha
* @return {rgba}
*/
function hexToRgbA(hex, alpha) {
var c;
if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c= hex.substring(1).split('');
if(c.length== 3) {
c= [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c= '0x' + c.join('');
return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
}
throw new Error('Bad Hex');
}
})();

View file

@ -1,131 +0,0 @@
/*!
* Grid Interaction
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
(function() {
/**
* Config
*/
var grid = {
columnsCurrent: 4,
columnsMin: 1,
columnsMax: 12,
targetButtons: '#grids article', // Buttons inserted before target
targetGrid: '#grids .grid', // Grid target
targetCode: '#grids pre code', // Code target
selectorAdd: '#grids button.add', // Add button selector in Dom
selectorRemove: '#grids button.remove', // Remove Button selector in Dom
};
/**
* Init
*/
initGridInteraction();
/**
* Init grid interaction
*/
function initGridInteraction() {
// Add buttons
addButtons();
// Add button listener
document.querySelector(grid.selectorAdd).addEventListener('click', function() {
addColumn();
}, false);
// Remove button listener
document.querySelector(grid.selectorRemove).addEventListener('click', function() {
removeColumn();
}, false);
}
/**
* Add buttons
*/
function addButtons() {
var buttons = document.createElement('P');
buttons.innerHTML = '<button class="secondary add">'
+ '<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">'
+ '<line x1="12" y1="5" x2="12" y2="19">'
+ '</line><line x1="5" y1="12" x2="19" y2="12">'
+ '</line>'
+ '</svg>'
+ ' Add column'
+ '</button>'
+ '<button class="secondary remove">'
+ '<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">'
+ '<line x1="5" y1="12" x2="19" y2="12"></line>'
+ '</svg>'
+ ' Remove column'
+ '</button>';
document.querySelector(grid.targetButtons).before(buttons);
}
/**
* Add column
*/
function addColumn() {
if (grid.columnsCurrent < grid.columnsMax) {
grid.columnsCurrent++;
generateGrid(grid.columnsCurrent);
}
}
/**
* Remove column
*/
function removeColumn() {
if (grid.columnsCurrent > grid.columnsMin) {
grid.columnsCurrent--;
generateGrid(grid.columnsCurrent);
}
}
/**
* Generate grid
*
* @param {number} cols
*/
function generateGrid(cols) {
var colsHTML = '';
var colsCode = '';
var colsCodePref = '&lt;<b>div</b> <i>class</i>=<u>"grid"</u>&gt;\n';
var colsCodeSuff = '&lt;/<b>div</b>&gt;';
for (var i=0; i<cols; i++) {
colsHTML += '<div>' + (i+1) + '</div>';
colsCode += ' &lt;<b>div</b>&gt;' + (i+1) + '&lt;/<b>div</b>&gt;\n';
}
document.querySelector(grid.targetGrid).innerHTML = colsHTML;
document.querySelector(grid.targetCode).innerHTML = colsCodePref+colsCode+colsCodeSuff;
}
})();

View file

@ -1,161 +0,0 @@
/**
* Most Visible v1.4.0
*
* @author Andy Palmer <andy@andypalmer.me>
* @license MIT
*/
(function (root, factory) {
// Universal Module Definition
/* jshint strict:false */
/* global define: false, module: false */
if (typeof define === 'function' && define.amd) {
define([], function () {
return factory(root);
});
} else if (typeof module === 'object' && module.exports) {
module.exports = factory(root);
} else {
root.mostVisible = factory(root);
}
}(typeof self !== 'undefined' ? self : this, function (window) {
/* jshint unused: vars */
'use strict';
/**
* MostVisible constructor
*
* @param {NodeList|string} elements
* @param {Object} options
* @constructor
*/
function MostVisible(elements, options) {
if (!(this instanceof MostVisible)) {
return (new MostVisible(elements, options)).getMostVisible();
}
if (typeof elements === 'string') {
elements = document.querySelectorAll(elements);
}
this.elements = elements;
this.options = extend({}, MostVisible.defaults, options);
}
/**
* MostVisible default options
*
* @namespace
* @property {object} defaults Default options hash.
* @property {boolean} defaults.percentage Whether to calculate visibility as a percentage of height.
* @property {number} defaults.offset An offset to take into account when calculating visibility.
*/
MostVisible.defaults = {
percentage: false,
offset: 0
};
MostVisible.prototype = {
/**
* Returns the most visible element from the instance's NodeList.
*
* @returns {Element} Most visible element.
*/
getMostVisible: function () {
var element = null,
viewportHeight = document.documentElement.clientHeight,
maxVisible = 0;
for (var i = 0; i < this.elements.length; i++) {
var currentVisible = this.getVisibleHeight(this.elements[i], viewportHeight);
if (currentVisible > maxVisible) {
maxVisible = currentVisible;
element = this.elements[i];
}
}
return element;
},
/**
* Returns the visible height of an element.
*
* @param {Element} element Element to check the visibility of.
* @param {number} viewportHeight
* @returns {number} Visible height of the element in pixels or a percentage of the element's total height.
*/
getVisibleHeight: function (element, viewportHeight) {
var rect = element.getBoundingClientRect(),
rectTopOffset = rect.top - this.options.offset,
rectBottomOffset = rect.bottom - this.options.offset,
height = rect.bottom - rect.top,
visible = {
top: rectTopOffset >= 0 && rectTopOffset < viewportHeight,
bottom: rectBottomOffset > 0 && rectBottomOffset < viewportHeight
},
visiblePx = 0;
if (visible.top && visible.bottom) {
// Whole element is visible
visiblePx = height;
} else if (visible.top) {
visiblePx = viewportHeight - rect.top;
} else if (visible.bottom) {
visiblePx = rectBottomOffset;
} else if (height > viewportHeight && rectTopOffset < 0) {
var absTop = Math.abs(rectTopOffset);
if (absTop < height) {
// Part of the element is visible
visiblePx = height - absTop;
}
}
if (this.options.percentage) {
return (visiblePx / height) * 100;
}
return visiblePx;
}
};
/*
MostVisible.makeJQueryPlugin = function ($) {
if (!$) {
return;
}
$.fn.mostVisible = function (options) {
var instance = new MostVisible(this.get(), options);
return this.filter(instance.getMostVisible());
};
};
*/
// Try adding the jQuery plugin to window.jQuery
// MostVisible.makeJQueryPlugin(window.jQuery);
/**
* Extends obj by adding the properties of all other objects passed to the function.
*
* @param {...Object} obj
* @returns {Object} The extended object.
*/
function extend(obj) {
for (var i = 1; i < arguments.length; i++) {
for (var key in arguments[i]) {
if (arguments[i].hasOwnProperty(key)) {
obj[key] = arguments[i][key];
}
}
}
return obj;
}
//noinspection JSAnnotator
return MostVisible;
}));

View file

@ -1,85 +0,0 @@
/*!
* Scrollspy
* Automatically update nav targets based on scroll position
*
* Require `most-visible.js` from https://github.com/andyexeter/most-visible
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
(function() {
/**
* Config
*/
var scrollspy = {
interval: 75, // Delay for detect scroll stop
sections: '[role="document"] > section', // Target for sections
nav: 'main aside nav', // Target for nav
active: 'active', // .class for active element
};
/**
* Init
*/
if (window.matchMedia("(min-width: 992px)").matches) {
activeNav();
scrollStop(
function () {
activeNav()
}
);
}
/**
* Set active section in nav
*/
function activeNav() {
// Get active section
var section = mostVisible(scrollspy.sections).getAttribute('id');
// Remove all active states
var allActive = document.querySelectorAll(scrollspy.nav + ' a.' + scrollspy.active);
for (var i = 0; i < allActive.length; i++) {
allActive[i].classList.remove(scrollspy.active);
}
// Set active state
var active = document.querySelector(scrollspy.nav + ' a[href="#' + section + '"]');
active.classList.add(scrollspy.active);
// Open details parent
active.parentNode.parentNode.parentNode.setAttribute('open', '');
}
/**
* Scroll stop
* Detect when the user stop scrolling
* Source: https://vanillajstoolkit.com/helpers/scrollstop/
*
* @param {Function} callback The function to run after scrolling
*
*/
function scrollStop(callback) {
var isScrolling;
window.addEventListener('scroll', function (event) {
window.clearTimeout(isScrolling);
isScrolling = setTimeout(function() {
callback();
}, scrollspy.interval);
}, false);
}
})();

View file

@ -1,125 +0,0 @@
/*!
* Theme Switcher
*
* Pico.css - https://picocss.com
* Copyright 2019-2021 - Licensed under MIT
*/
(function() {
/**
* Config
*/
var switcher = {
button: {
element: 'BUTTON',
class: 'contrast switcher theme-switcher',
on: '<i>Turn on dark mode</i>',
off: '<i>Turn off dark mode</i>'
},
target: 'body', // Button append in target
selector: 'button.theme-switcher', // Button selector in Dom
currentTheme: systemColorScheme()
};
/**
* Init
*/
themeSwitcher();
/**
* Get System Color Scheme
*
* @return {string}
*/
function systemColorScheme() {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
else {
return 'light';
}
}
/**
* Display Theme Switcher
*/
function themeSwitcher() {
// Insert Switcher
var button = document.createElement(switcher.button.element);
button.className = switcher.button.class;
document.querySelector(switcher.target).appendChild(button);
// Set Current Theme
setTheme(switcher.currentTheme);
// Click Listener on Switcher
var switchers = document.querySelectorAll(switcher.selector);
for (var i = 0; i < switchers.length; i++) {
switchers[i].addEventListener('click', function(event) {
// Switch Theme
if (switcher.currentTheme == 'light') {
setTheme('dark');
}
else {
setTheme('light');
}
}, false);
}
}
/**
* Set Theme
*
* @param {string} set
*/
function setTheme(set) {
// Text toggle
if (set == 'light') {
var label = switcher.button.on;
}
else {
var label = switcher.button.off;
}
// Apply theme
document.querySelector('html').setAttribute('data-theme', set);
var switchers = document.querySelectorAll(switcher.selector);
for (var i = 0; i < switchers.length; i++) {
switchers[i].innerHTML = label;
switchers[i].setAttribute('aria-label', stripTags(label));
}
switcher.currentTheme = set;
}
/**
* Strip tags
*
* @param {string} html
* @return {string}
*/
function stripTags(html) {
return html.replace(/<[^>]*>?/gm, '');
}
})();