mirror of
https://github.com/locomotivemtl/locomotive-boilerplate.git
synced 2026-01-15 00:55:08 +08:00
Compare commits
94 Commits
feature/bu
...
feature/mo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
344f4bc98c | ||
|
|
d593fe5409 | ||
|
|
f8a46043a6 | ||
|
|
25823286d5 | ||
|
|
605f30c948 | ||
|
|
27a41aba66 | ||
|
|
353a38915d | ||
|
|
6d37049989 | ||
|
|
bc3fd3a492 | ||
|
|
45d8be5525 | ||
|
|
ea8f98a52d | ||
|
|
56bbd9e3c5 | ||
|
|
dcb7e91b91 | ||
|
|
2b1eb8e0dd | ||
|
|
f4afd9c6b2 | ||
|
|
7578397a8e | ||
|
|
27effb470d | ||
|
|
7a91cbce61 | ||
|
|
65a265c0ea | ||
|
|
afb3a4aa6a | ||
|
|
40521c3f2b | ||
|
|
2d395cf73a | ||
|
|
81d47b88b8 | ||
|
|
c16407c8c1 | ||
|
|
522c9c0bcb | ||
|
|
ddd12ffc38 | ||
|
|
9e6d7ae182 | ||
|
|
d5bff3ab50 | ||
|
|
962ba66b96 | ||
|
|
5b6bca6ce3 | ||
|
|
4ae90a5821 | ||
|
|
31061daf60 | ||
|
|
ceefeb554e | ||
|
|
276b5eebc0 | ||
|
|
a37c5b047a | ||
|
|
0af2be4599 | ||
|
|
98ba8c4972 | ||
|
|
3f7077b488 | ||
|
|
a674a16c4b | ||
|
|
dd2c783938 | ||
|
|
61b6222525 | ||
|
|
5acd27d1b0 | ||
|
|
9a5a91b221 | ||
|
|
7021666c46 | ||
|
|
43c86c3b50 | ||
|
|
0b4c82ceda | ||
|
|
b72fdabe23 | ||
|
|
f1ebc27a69 | ||
|
|
f2898c8c8e | ||
|
|
12d65db09f | ||
|
|
657fd41f70 | ||
|
|
65c486b910 | ||
|
|
3d0e4d26a2 | ||
|
|
df1a3a6f3c | ||
|
|
7f1b6dad2e | ||
|
|
63e46cde26 | ||
|
|
6564fb330a | ||
|
|
b5753148f1 | ||
|
|
7b415af8c2 | ||
|
|
dc0bc2042c | ||
|
|
e9dbb03207 | ||
|
|
95caf9ebb5 | ||
|
|
596ff7a8ee | ||
|
|
70b36052e6 | ||
|
|
f1e2e2270f | ||
|
|
13735c64f9 | ||
|
|
659ef3767b | ||
|
|
e162af17dd | ||
|
|
93559a0c84 | ||
|
|
c1bcf7fb0d | ||
|
|
d0fcfaac86 | ||
|
|
4a958c5fb5 | ||
|
|
5e7e92c7f5 | ||
|
|
380fbd40c3 | ||
|
|
e16ba2ca16 | ||
|
|
43a5eb1ad3 | ||
|
|
99801a2d8b | ||
|
|
217a1adba7 | ||
|
|
a11e98e31e | ||
|
|
6ef90dbe11 | ||
|
|
6726d665f2 | ||
|
|
dca6c5de1d | ||
|
|
05a00c4258 | ||
|
|
7517be0e76 | ||
|
|
dcec21adf4 | ||
|
|
297e0b4ec8 | ||
|
|
9a2083d894 | ||
|
|
1a81c865ae | ||
|
|
d6b5784cdd | ||
|
|
8894664743 | ||
|
|
be71474633 | ||
|
|
810df92a61 | ||
|
|
bf28fe21a3 | ||
|
|
7b3cefd8df |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -3,4 +3,11 @@ node_modules
|
||||
Thumbs.db
|
||||
loconfig.*.json
|
||||
!loconfig.example.json
|
||||
.prettierrc
|
||||
.prettierrc
|
||||
|
||||
www/assets/scripts/*
|
||||
!www/assets/scripts/.gitkeep
|
||||
www/assets/styles/*
|
||||
!www/assets/styles/.gitkeep
|
||||
|
||||
assets.json
|
||||
|
||||
@@ -23,8 +23,8 @@ Learn more about [languages and technologies](docs/technologies.md).
|
||||
|
||||
Make sure you have the following installed:
|
||||
|
||||
* [Node] — at least 17.9, the latest LTS is recommended.
|
||||
* [NPM] — at least 8.0, the latest LTS is recommended.
|
||||
* [Node] — at least 20, the latest LTS is recommended.
|
||||
* [NPM] — at least 10, the latest LTS is recommended.
|
||||
|
||||
> 💡 You can use [NVM] to install and use different versions of Node via the command-line.
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"version": 1675955478084
|
||||
}
|
||||
@@ -1,60 +1,137 @@
|
||||
import modular from 'modujs';
|
||||
import * as modules from './modules';
|
||||
import globals from './globals';
|
||||
import { html } from './utils/environment';
|
||||
import config from './config'
|
||||
import { debounce } from './utils/tickers';
|
||||
import { $html } from './utils/dom';
|
||||
import { ENV, FONT, CUSTOM_EVENT, CSS_CLASS } from './config'
|
||||
import { isFontLoadingAPIAvailable, loadFonts } from './utils/fonts';
|
||||
|
||||
const app = new modular({
|
||||
modules: modules,
|
||||
modules,
|
||||
});
|
||||
|
||||
window.onload = (event) => {
|
||||
function init() {
|
||||
bindEvents();
|
||||
globals();
|
||||
setViewportSizes();
|
||||
|
||||
app.init(app);
|
||||
|
||||
$html.classList.add(CSS_CLASS.LOADED, CSS_CLASS.READY);
|
||||
$html.classList.remove(CSS_CLASS.LOADING);
|
||||
|
||||
/**
|
||||
* Debug focus
|
||||
*/
|
||||
// document.addEventListener(
|
||||
// "focusin",
|
||||
// function () {
|
||||
// console.log('focused: ', document.activeElement)
|
||||
// }, true
|
||||
// );
|
||||
|
||||
/**
|
||||
* Eagerly load the following fonts.
|
||||
*/
|
||||
if (isFontLoadingAPIAvailable) {
|
||||
loadFonts(FONT.EAGER, ENV.IS_DEV).then((eagerFonts) => {
|
||||
$html.classList.add(CSS_CLASS.FONTS_LOADED);
|
||||
|
||||
/**
|
||||
* Debug fonts loading
|
||||
*/
|
||||
// if (ENV.IS_DEV) {
|
||||
// console.group('Eager fonts loaded!', eagerFonts.length, '/', document.fonts.size);
|
||||
// console.group('State of eager fonts:');
|
||||
// eagerFonts.forEach(font => console.log(font.family, font.style, font.weight, font.status));
|
||||
// console.groupEnd();
|
||||
// console.group('State of all fonts:');
|
||||
// document.fonts.forEach(font => console.log(font.family, font.style, font.weight, font.status));
|
||||
// console.groupEnd();
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Global events
|
||||
////////////////
|
||||
function bindEvents() {
|
||||
|
||||
// Resize event
|
||||
const resizeEndEvent = new CustomEvent(CUSTOM_EVENT.RESIZE_END)
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
debounce(() => {
|
||||
window.dispatchEvent(resizeEndEvent)
|
||||
}, 200, false)
|
||||
)
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
onResize
|
||||
)
|
||||
}
|
||||
|
||||
function onResize() {
|
||||
setViewportSizes()
|
||||
}
|
||||
|
||||
function setViewportSizes() {
|
||||
|
||||
// Document styles
|
||||
const documentStyles = document.documentElement.style;
|
||||
|
||||
// Viewport width
|
||||
const vw = document.body.clientWidth * 0.01;
|
||||
documentStyles.setProperty('--vw', `${vw}px`);
|
||||
|
||||
// Return if browser supports vh, svh, dvh, & lvh
|
||||
if (ENV.SUPPORTS_VH) {
|
||||
return
|
||||
}
|
||||
|
||||
// Viewport height
|
||||
const svh = document.documentElement.clientHeight * 0.01;
|
||||
documentStyles.setProperty('--svh', `${svh}px`);
|
||||
|
||||
const dvh = window.innerHeight * 0.01;
|
||||
documentStyles.setProperty('--dvh', `${dvh}px`);
|
||||
|
||||
if (document.body) {
|
||||
const fixed = document.createElement('div');
|
||||
fixed.style.width = '1px';
|
||||
fixed.style.height = '100vh';
|
||||
fixed.style.position = 'fixed';
|
||||
fixed.style.left = '0';
|
||||
fixed.style.top = '0';
|
||||
fixed.style.bottom = '0';
|
||||
fixed.style.visibility = 'hidden';
|
||||
|
||||
document.body.appendChild(fixed);
|
||||
|
||||
var fixedHeight = fixed.clientHeight;
|
||||
|
||||
fixed.remove();
|
||||
|
||||
const lvh = fixedHeight * 0.01;
|
||||
|
||||
documentStyles.setProperty('--lvh', `${lvh}px`);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Execute
|
||||
////////////////
|
||||
window.addEventListener('load', () => {
|
||||
const $style = document.getElementById('main-css');
|
||||
|
||||
if ($style) {
|
||||
if ($style.isLoaded) {
|
||||
init();
|
||||
} else {
|
||||
$style.addEventListener('load', (event) => {
|
||||
init();
|
||||
});
|
||||
$style.addEventListener('load', init);
|
||||
}
|
||||
} else {
|
||||
console.warn('The "main-css" stylesheet not found');
|
||||
}
|
||||
};
|
||||
|
||||
export const EAGER_FONTS = [
|
||||
{ family: 'Source Sans', style: 'normal', weight: 400 },
|
||||
{ family: 'Source Sans', style: 'normal', weight: 700 },
|
||||
];
|
||||
|
||||
function init() {
|
||||
globals();
|
||||
|
||||
app.init(app);
|
||||
|
||||
html.classList.add('is-loaded');
|
||||
html.classList.add('is-ready');
|
||||
html.classList.remove('is-loading');
|
||||
|
||||
/**
|
||||
* Eagerly load the following fonts.
|
||||
*/
|
||||
if (isFontLoadingAPIAvailable) {
|
||||
loadFonts(EAGER_FONTS, config.IS_DEV).then((eagerFonts) => {
|
||||
html.classList.add('fonts-loaded');
|
||||
|
||||
if (config.IS_DEV) {
|
||||
console.group('Eager fonts loaded!', eagerFonts.length, '/', document.fonts.size);
|
||||
console.group('State of eager fonts:')
|
||||
eagerFonts.forEach((font) => console.log(font.family, font.style, font.weight, font.status/*, font*/))
|
||||
console.groupEnd()
|
||||
console.group('State of all fonts:')
|
||||
document.fonts.forEach((font) => console.log(font.family, font.style, font.weight, font.status/*, font*/))
|
||||
console.groupEnd()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,18 +7,61 @@
|
||||
* > (since `process` is a Node API, not a web API).
|
||||
* > — https://esbuild.github.io/api/#platform
|
||||
*/
|
||||
const env = process.env.NODE_ENV
|
||||
|
||||
export default config = Object.freeze({
|
||||
// Environments
|
||||
ENV: env,
|
||||
IS_PROD: env === 'production',
|
||||
IS_DEV: env === 'development',
|
||||
const NODE_ENV = process.env.NODE_ENV
|
||||
const IS_MOBILE = window.matchMedia('(any-pointer:coarse)').matches
|
||||
|
||||
// CSS class names
|
||||
CSS_CLASS: {
|
||||
LOADING: 'is-loading',
|
||||
READY: 'is-ready',
|
||||
LOADED: 'is-loaded',
|
||||
},
|
||||
// Main environment variables
|
||||
const ENV = Object.freeze({
|
||||
// Node environment
|
||||
NAME: NODE_ENV,
|
||||
IS_PROD: NODE_ENV === 'production',
|
||||
IS_DEV: NODE_ENV === 'development',
|
||||
|
||||
// Device
|
||||
IS_MOBILE,
|
||||
IS_DESKTOP: !IS_MOBILE,
|
||||
|
||||
// Supports
|
||||
SUPPORTS_VH: (
|
||||
'CSS' in window
|
||||
&& 'supports' in window.CSS
|
||||
&& window.CSS.supports('height: 100svh')
|
||||
&& window.CSS.supports('height: 100dvh')
|
||||
&& window.CSS.supports('height: 100lvh')
|
||||
)
|
||||
})
|
||||
|
||||
// Main CSS classes used within the project
|
||||
const CSS_CLASS = Object.freeze({
|
||||
LOADING: 'is-loading',
|
||||
LOADED: 'is-loaded',
|
||||
READY: 'is-ready',
|
||||
FONTS_LOADED: 'fonts-loaded',
|
||||
LAZY_CONTAINER: 'c-lazy',
|
||||
LAZY_LOADED: '-lazy-loaded',
|
||||
// ...
|
||||
})
|
||||
|
||||
// Custom js events
|
||||
const CUSTOM_EVENT = Object.freeze({
|
||||
RESIZE_END: 'loco.resizeEnd',
|
||||
VISIT_START: 'visit.start',
|
||||
MODAL_OPEN: 'modal.open',
|
||||
// ...
|
||||
})
|
||||
|
||||
// Fonts parameters
|
||||
const FONT = Object.freeze({
|
||||
EAGER: [
|
||||
{ family: 'Source Sans', style: 'normal', weight: 400 },
|
||||
{ family: 'Source Sans', style: 'normal', weight: 700 },
|
||||
],
|
||||
})
|
||||
|
||||
export {
|
||||
ENV,
|
||||
CSS_CLASS,
|
||||
CUSTOM_EVENT,
|
||||
FONT,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import svg4everybody from 'svg4everybody';
|
||||
import config from './config';
|
||||
import { ENV } from './config';
|
||||
|
||||
// Dynamic imports for development mode only
|
||||
let gridHelper;
|
||||
(async () => {
|
||||
if (config.IS_DEV) {
|
||||
if (ENV.IS_DEV) {
|
||||
const gridHelperModule = await import('./utils/grid-helper');
|
||||
gridHelper = gridHelperModule?.gridHelper;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export {default as Example} from './modules/Example';
|
||||
export {default as Load} from './modules/Load';
|
||||
export {default as Modal} from './modules/Modal';
|
||||
export {default as Scroll} from './modules/Scroll';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { module } from 'modujs';
|
||||
import { EAGER_FONTS } from '../app';
|
||||
import { FONT } from '../config';
|
||||
import { whenReady } from '../utils/fonts';
|
||||
|
||||
export default class extends module {
|
||||
@@ -8,7 +8,7 @@ export default class extends module {
|
||||
}
|
||||
|
||||
init() {
|
||||
whenReady(EAGER_FONTS).then((fonts) => this.onFontsLoaded(fonts));
|
||||
whenReady(FONT.EAGER).then((fonts) => this.onFontsLoaded(fonts));
|
||||
}
|
||||
|
||||
onFontsLoaded(fonts) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { module } from 'modujs';
|
||||
import modularLoad from 'modularload';
|
||||
import { CUSTOM_EVENT } from '../config';
|
||||
|
||||
export default class extends module {
|
||||
constructor(m) {
|
||||
@@ -14,6 +15,12 @@ export default class extends module {
|
||||
}
|
||||
});
|
||||
|
||||
load.on('loading', (transition, oldContainer) => {
|
||||
const args = { transition, oldContainer };
|
||||
// Dispatch custom event
|
||||
window.dispatchEvent(new CustomEvent(CUSTOM_EVENT.VISIT_START, { detail: args }))
|
||||
});
|
||||
|
||||
load.on('loaded', (transition, oldContainer, newContainer) => {
|
||||
this.call('destroy', oldContainer, 'app');
|
||||
this.call('update', newContainer, 'app');
|
||||
|
||||
195
assets/scripts/modules/Modal.js
Normal file
195
assets/scripts/modules/Modal.js
Normal file
@@ -0,0 +1,195 @@
|
||||
import { createFocusTrap } from 'focus-trap'
|
||||
import { module as Module } from 'modujs'
|
||||
import { $html } from '../utils/dom'
|
||||
import { CUSTOM_EVENT } from '../config'
|
||||
|
||||
/**
|
||||
* Generic component to display a modal.
|
||||
*
|
||||
*/
|
||||
export default class Modal extends Module {
|
||||
/**
|
||||
* Creates a new Modal.
|
||||
*
|
||||
* @param {object} options - The module options.
|
||||
* @param {string} options.dataName - The module data attribute name.
|
||||
* @throws {TypeError} If the class does not have an active CSS class defined.
|
||||
*/
|
||||
|
||||
static CLASS = {
|
||||
EL: 'is-open',
|
||||
HTML: 'has-modal-open',
|
||||
}
|
||||
|
||||
constructor(options) {
|
||||
super(options)
|
||||
|
||||
// Data
|
||||
this.moduleName = options.name
|
||||
this.dataName = this.getData('name') || options.dataName
|
||||
|
||||
// Bindings
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.onModalOpen = this.onModalOpen.bind(this)
|
||||
this.onVisitStart = this.onVisitStart.bind(this)
|
||||
|
||||
// UI
|
||||
this.$togglers = document.querySelectorAll(`[data-${this.dataName}-toggler]`)
|
||||
this.$focusTrapTargets = Array.from(this.el.querySelectorAll(`[data-${this.dataName}-target]`))
|
||||
|
||||
// Focus trap options
|
||||
this.focusTrapOptions = {
|
||||
/**
|
||||
* There is a delay between when the class is applied
|
||||
* and when the element is focusable
|
||||
*/
|
||||
checkCanFocusTrap: (trapContainers) => {
|
||||
const results = trapContainers.map((trapContainer) => {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
if (
|
||||
getComputedStyle(trapContainer).visibility !==
|
||||
'hidden'
|
||||
) {
|
||||
resolve()
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, 5)
|
||||
})
|
||||
})
|
||||
|
||||
// Return a promise that resolves when all the trap containers are able to receive focus
|
||||
return Promise.all(results)
|
||||
},
|
||||
|
||||
onActivate: () => {
|
||||
this.el.classList.add(Modal.CLASS.EL)
|
||||
$html.classList.add(Modal.CLASS.HTML)
|
||||
$html.classList.add('has-'+this.dataName+'-open')
|
||||
this.el.setAttribute('aria-hidden', false)
|
||||
this.isOpen = true
|
||||
|
||||
this.onActivate?.();
|
||||
},
|
||||
|
||||
onPostActivate: () => {
|
||||
this.$togglers.forEach(($toggler) => {
|
||||
$toggler.setAttribute('aria-expanded', true)
|
||||
})
|
||||
},
|
||||
|
||||
onDeactivate: () => {
|
||||
this.el.classList.remove(Modal.CLASS.EL)
|
||||
$html.classList.remove(Modal.CLASS.HTML)
|
||||
$html.classList.remove('has-'+this.dataName+'-open')
|
||||
this.el.setAttribute('aria-hidden', true)
|
||||
this.isOpen = false
|
||||
|
||||
this.onDeactivate?.();
|
||||
},
|
||||
|
||||
onPostDeactivate: () => {
|
||||
this.$togglers.forEach(($toggler) => {
|
||||
$toggler.setAttribute('aria-expanded', false)
|
||||
})
|
||||
},
|
||||
|
||||
clickOutsideDeactivates: true,
|
||||
}
|
||||
|
||||
this.isOpen = false
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Lifecycle
|
||||
/////////////////
|
||||
init() {
|
||||
this.onBeforeInit?.()
|
||||
|
||||
this.focusTrap = createFocusTrap(
|
||||
this.$focusTrapTargets.length > 0 ? this.$focusTrapTargets : [this.el],
|
||||
this.focusTrapOptions
|
||||
)
|
||||
|
||||
this.bindEvents()
|
||||
|
||||
this.onInit?.()
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.focusTrap?.deactivate?.({
|
||||
returnFocus: false,
|
||||
})
|
||||
|
||||
this.unbindEvents()
|
||||
|
||||
this.onDestroy?.()
|
||||
|
||||
super.destroy()
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Events
|
||||
/////////////////
|
||||
bindEvents() {
|
||||
window.addEventListener(CUSTOM_EVENT.VISIT_START, this.onVisitStart)
|
||||
window.addEventListener(CUSTOM_EVENT.MODAL_OPEN, this.onModalOpen)
|
||||
|
||||
this.$togglers.forEach(($toggler) => {
|
||||
$toggler.addEventListener('click', this.toggle)
|
||||
})
|
||||
}
|
||||
|
||||
unbindEvents() {
|
||||
window.removeEventListener(CUSTOM_EVENT.VISIT_START, this.onVisitStart)
|
||||
window.removeEventListener(CUSTOM_EVENT.MODAL_OPEN, this.onModalOpen)
|
||||
|
||||
this.$togglers.forEach(($toggler) => {
|
||||
$toggler.removeEventListener('click', this.toggle)
|
||||
})
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Callbacks
|
||||
/////////////////
|
||||
onVisitStart() {
|
||||
// Close the modal on page change
|
||||
this.close()
|
||||
}
|
||||
|
||||
onModalOpen(event) {
|
||||
// Close the modal if another one is opened
|
||||
if (event.detail !== this.el) {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Methods
|
||||
/////////////////
|
||||
toggle(event) {
|
||||
if (this.el.classList.contains(Modal.CLASS.EL)) {
|
||||
this.close(event)
|
||||
} else {
|
||||
this.open(event)
|
||||
}
|
||||
}
|
||||
|
||||
open(args) {
|
||||
if (this.isOpen) return
|
||||
|
||||
this.focusTrap?.activate?.()
|
||||
|
||||
this.onOpen?.(args)
|
||||
|
||||
window.dispatchEvent(new CustomEvent(CUSTOM_EVENT.MODAL_OPEN, { detail: this.el }))
|
||||
}
|
||||
|
||||
close(args) {
|
||||
if (!this.isOpen) return
|
||||
|
||||
this.focusTrap?.deactivate?.()
|
||||
|
||||
this.onClose?.(args)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { module } from 'modujs';
|
||||
import { lazyLoadImage } from '../utils/image';
|
||||
import LocomotiveScroll from 'locomotive-scroll';
|
||||
import { module } from 'modujs'
|
||||
import { lazyLoadImage } from '../utils/image'
|
||||
import LocomotiveScroll from 'locomotive-scroll'
|
||||
|
||||
export default class extends module {
|
||||
constructor(m) {
|
||||
@@ -9,18 +9,14 @@ export default class extends module {
|
||||
|
||||
init() {
|
||||
this.scroll = new LocomotiveScroll({
|
||||
el: this.el,
|
||||
smooth: true
|
||||
});
|
||||
|
||||
this.scroll.on('call', (func, way, obj, id) => {
|
||||
// Using modularJS
|
||||
this.call(func[0], { way, obj }, func[1], func[2]);
|
||||
});
|
||||
|
||||
this.scroll.on('scroll', (args) => {
|
||||
// console.log(args.scroll);
|
||||
modularInstance: this,
|
||||
})
|
||||
|
||||
// // Force scroll to top
|
||||
// if (history.scrollRestoration) {
|
||||
// history.scrollRestoration = 'manual'
|
||||
// window.scrollTo(0, 0)
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,11 +37,22 @@ export default class extends module {
|
||||
* @param {LocomotiveScroll} args - The Locomotive Scroll instance.
|
||||
*/
|
||||
lazyLoad(args) {
|
||||
lazyLoadImage(args.obj.el, null, () => {
|
||||
lazyLoadImage(args.target, null, () => {
|
||||
//callback
|
||||
})
|
||||
}
|
||||
|
||||
scrollTo(params) {
|
||||
let { target, ...options } = params
|
||||
|
||||
options = Object.assign({
|
||||
// Defaults
|
||||
duration: 1,
|
||||
}, options)
|
||||
|
||||
this.scroll?.scrollTo(target, options)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.scroll.destroy();
|
||||
}
|
||||
|
||||
7
assets/scripts/utils/dom.js
Normal file
7
assets/scripts/utils/dom.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const $html = document.documentElement
|
||||
const $body = document.body
|
||||
|
||||
export {
|
||||
$html,
|
||||
$body,
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
const APP_NAME = 'Boilerplate';
|
||||
const DATA_API_KEY = '.data-api';
|
||||
|
||||
const html = document.documentElement;
|
||||
const body = document.body;
|
||||
const isDebug = html.hasAttribute('data-debug');
|
||||
|
||||
|
||||
export { APP_NAME, DATA_API_KEY, html, body, isDebug };
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CSS_CLASS } from '../config'
|
||||
|
||||
/**
|
||||
* Get an image meta data
|
||||
*
|
||||
@@ -89,14 +91,14 @@ const lazyLoadImage = async ($el, url, callback) => {
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
let lazyParent = $el.closest('.c-lazy')
|
||||
let lazyParent = $el.closest(`.${CSS_CLASS.LAZY_CONTAINER}`)
|
||||
|
||||
if(lazyParent) {
|
||||
lazyParent.classList.add('-lazy-loaded')
|
||||
lazyParent.classList.add(CSS_CLASS.LAZY_LOADED)
|
||||
lazyParent.style.backgroundImage = ''
|
||||
}
|
||||
|
||||
$el.classList.add('-lazy-loaded')
|
||||
$el.classList.add(CSS_CLASS.LAZY_LOADED)
|
||||
|
||||
callback?.()
|
||||
})
|
||||
|
||||
@@ -28,7 +28,7 @@ const lerp = (x, y, a) => x * (1 - a) + y * a
|
||||
* @return {number} inverted lerp value
|
||||
*/
|
||||
|
||||
const invlerp = (x, y, a) => clamp((v - x)/(a - x))
|
||||
const invlerp = (x, y, a) => clamp((a - x)/(y - x))
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ $input-icon-color: 424242; // No #
|
||||
.c-form_input {
|
||||
padding: rem(10px);
|
||||
border: 1px solid lightgray;
|
||||
background-color: $color-lightest;
|
||||
background-color: color(lightest);
|
||||
|
||||
&:hover {
|
||||
border-color: darkgray;
|
||||
@@ -71,7 +71,7 @@ $checkbox-icon-color: $input-icon-color;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background-color: $color-lightest;
|
||||
background-color: color(lightest);
|
||||
border: 1px solid lightgray;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,30 +2,78 @@
|
||||
// Components / Headings
|
||||
// ==========================================================================
|
||||
|
||||
// Font sizes
|
||||
// ==========================================================================
|
||||
:root {
|
||||
// Default
|
||||
--font-size-h1: #{responsive-value(38px, 90px, $from-xl)};
|
||||
--font-size-h2: #{responsive-value(34px, 72px, $from-xl)};
|
||||
--font-size-h3: #{responsive-value(28px, 54px, $from-xl)};
|
||||
--font-size-h4: #{responsive-value(24px, 40px, $from-xl)};
|
||||
--font-size-h5: #{responsive-value(20px, 30px, $from-xl)};
|
||||
--font-size-h6: #{responsive-value(18px, 23px, $from-xl)};
|
||||
}
|
||||
|
||||
// Mixins
|
||||
// ==========================================================================
|
||||
|
||||
@mixin heading {
|
||||
font-family: ff('sans');
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
|
||||
@mixin heading-h1 {
|
||||
font-size: var(--font-size-h1);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
@mixin heading-h2 {
|
||||
font-size: var(--font-size-h2);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
@mixin heading-h3 {
|
||||
font-size: var(--font-size-h3);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
@mixin heading-h4 {
|
||||
font-size: var(--font-size-h4);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@mixin heading-h5 {
|
||||
font-size: var(--font-size-h5);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@mixin heading-h6 {
|
||||
font-size: var(--font-size-h6);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
// Styles
|
||||
// ==========================================================================
|
||||
|
||||
.c-heading {
|
||||
margin-bottom: rem(30px);
|
||||
@include heading;
|
||||
|
||||
&.-h1 {
|
||||
font-size: var(--font-size-h1);
|
||||
@include heading-h1;
|
||||
}
|
||||
|
||||
&.-h2 {
|
||||
font-size: var(--font-size-h2);
|
||||
@include heading-h2;
|
||||
}
|
||||
|
||||
&.-h3 {
|
||||
font-size: var(--font-size-h3);
|
||||
@include heading-h3;
|
||||
}
|
||||
|
||||
&.-h4 {
|
||||
font-size: var(--font-size-h4);
|
||||
@include heading-h4;
|
||||
}
|
||||
|
||||
&.-h5 {
|
||||
font-size: var(--font-size-h5);
|
||||
@include heading-h5;
|
||||
}
|
||||
|
||||
&.-h6 {
|
||||
font-size: var(--font-size-h6);
|
||||
@include heading-h6;
|
||||
}
|
||||
}
|
||||
|
||||
52
assets/styles/components/_modal.scss
Normal file
52
assets/styles/components/_modal.scss
Normal file
@@ -0,0 +1,52 @@
|
||||
// ==========================================================================
|
||||
// Components / Modal
|
||||
// ==========================================================================
|
||||
|
||||
.c-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100dvh;
|
||||
max-width: inherit;
|
||||
max-height: 100lvh;
|
||||
margin: 0;
|
||||
padding: 0 var(--grid-margin);
|
||||
background: transparent;
|
||||
border: none;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
|
||||
// Backdrop
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: color(darkest, 0.5);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
html.is-first-loaded & {
|
||||
transition: visibility speed(normal);
|
||||
}
|
||||
|
||||
&.is-open {
|
||||
pointer-events: auto;
|
||||
visibility: visible;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
.c-modal_inner {
|
||||
width: 100%;
|
||||
max-width: rem(500px);
|
||||
padding: $unit-small;
|
||||
background-color: color(lightest);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
width: 11px;
|
||||
height: 100vh;
|
||||
transform-origin: center right;
|
||||
transition: transform 0.3s, opacity 0.3s;
|
||||
transition: transform t(normal), opacity t(normal);
|
||||
opacity: 0;
|
||||
|
||||
&:hover {
|
||||
@@ -25,7 +25,7 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background-color: $color-darkest;
|
||||
background-color: color(darkest);
|
||||
opacity: 0.5;
|
||||
width: 7px;
|
||||
border-radius: 10px;
|
||||
|
||||
53
assets/styles/components/_text.scss
Normal file
53
assets/styles/components/_text.scss
Normal file
@@ -0,0 +1,53 @@
|
||||
// ==========================================================================
|
||||
// Components / Texts
|
||||
// ==========================================================================
|
||||
|
||||
// Font sizes
|
||||
// ==========================================================================
|
||||
:root {
|
||||
--font-size-body-regular: #{responsive-value(15px, 17px, $from-lg)};
|
||||
--font-size-body-medium: #{responsive-value(18px, 23px, $from-lg)};
|
||||
--font-size-body-small: #{responsive-value(13px, 16px, $from-lg)};
|
||||
}
|
||||
|
||||
// Mixins
|
||||
// ==========================================================================
|
||||
@mixin text {
|
||||
font-family: ff('sans');
|
||||
}
|
||||
|
||||
@mixin body-regular {
|
||||
font-size: var(--font-size-body-regular);
|
||||
font-weight: $font-weight-normal;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@mixin body-medium {
|
||||
font-size: var(--font-size-body-medium);
|
||||
font-weight: $font-weight-normal;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@mixin body-small {
|
||||
font-size: var(--font-size-body-small);
|
||||
font-weight: $font-weight-normal;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
// Styles
|
||||
// ==========================================================================
|
||||
.c-text {
|
||||
@include text;
|
||||
|
||||
&.-body-regular {
|
||||
@include body-regular;
|
||||
}
|
||||
|
||||
&.-body-medium {
|
||||
@include body-medium;
|
||||
}
|
||||
|
||||
&.-body-small {
|
||||
@include body-small;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// Simple page-level setup.
|
||||
//
|
||||
// 1. Include web fonts
|
||||
// 1. Includes fonts
|
||||
// 2. Ensure the page always fills at least the entire height of the viewport.
|
||||
// 3. Set the default `font-size` and `line-height` for the entire project,
|
||||
// sourced from our default variables.
|
||||
@@ -20,61 +20,37 @@ html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
@media (max-width: $to-small) {
|
||||
@media (max-width: $to-sm) {
|
||||
font-size: $font-size - 2px;
|
||||
}
|
||||
|
||||
@media (min-width: $from-small) and (max-width: $to-medium) {
|
||||
font-size: $font-size - 2px;
|
||||
}
|
||||
|
||||
@media (min-width: $from-medium) and (max-width: $to-large) {
|
||||
@media (min-width: $from-sm) and (max-width: $to-lg) {
|
||||
font-size: $font-size - 1px;
|
||||
}
|
||||
|
||||
@media (min-width: $from-large) and (max-width: $to-huge) {
|
||||
font-size: $font-size; // [1]
|
||||
@media (min-width: $from-lg) and (max-width: $to-2xl) {
|
||||
font-size: $font-size;
|
||||
}
|
||||
|
||||
@media (min-width: $from-huge) and (max-width: $to-gigantic) {
|
||||
@media (min-width: $from-2xl) and (max-width: $to-3xl) {
|
||||
font-size: $font-size + 1px;
|
||||
}
|
||||
|
||||
@media (min-width: $from-gigantic) and (max-width: $to-colossal) {
|
||||
@media (min-width: $from-3xl) {
|
||||
font-size: $font-size + 2px;
|
||||
}
|
||||
|
||||
@media (min-width: $from-colossal) {
|
||||
font-size: $font-size + 4px;
|
||||
}
|
||||
|
||||
&.is-loading {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
&.has-scroll-smooth {
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.has-scroll-dragging {
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
.has-scroll-smooth & {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: $selection-background-color;
|
||||
color: $selection-text-color;
|
||||
background-color: $color-selection-background;
|
||||
color: $color-selection-text;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
124
assets/styles/elements/_normalize.scss
Normal file
124
assets/styles/elements/_normalize.scss
Normal file
@@ -0,0 +1,124 @@
|
||||
// ==========================================================================
|
||||
// Elements / Normalize
|
||||
// ==========================================================================
|
||||
|
||||
// Modern CSS Normalize
|
||||
// Based on the reset by Andy.set with some tweaks.
|
||||
// Original by Andy.set: https://piccalil.li/blog/a-more-modern-css-reset/
|
||||
// Review by Chris collier: https://chriscoyier.net/2023/10/03/being-picky-about-a-css-reset-for-fun-pleasure/
|
||||
|
||||
|
||||
// Box sizing rules
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// Prevent font size inflation
|
||||
html {
|
||||
-moz-text-size-adjust: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
text-size-adjust: none;
|
||||
}
|
||||
|
||||
// Remove default margin in favour of better control in authored CSS
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
dl,
|
||||
dd,
|
||||
figure,
|
||||
blockquote {
|
||||
margin-block: unset;
|
||||
}
|
||||
|
||||
// Remove list styles on ul, ol elements with a class, which suggests default styling will be removed
|
||||
ul[class],
|
||||
ol[class] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
// Set core defaults
|
||||
html {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: unset;
|
||||
}
|
||||
|
||||
// Set shorter line heights on headings and interactive elements
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
input,
|
||||
label,
|
||||
button {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
// Balance text wrapping on headings
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
// Remove a elements default styles if they have a class
|
||||
a[class] {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
// Make assets easier to work with
|
||||
img,
|
||||
svg,
|
||||
canvas,
|
||||
picture {
|
||||
display: block;
|
||||
max-inline-size: 100%;
|
||||
block-size: auto;
|
||||
}
|
||||
|
||||
// Inherit fonts for inputs and buttons
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
textarea {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
// Make sure textareas without a rows attribute are not tiny
|
||||
textarea:not([rows]) {
|
||||
min-height: 10em;
|
||||
}
|
||||
|
||||
// Anything that has been anchored to should have extra scroll margin
|
||||
:target {
|
||||
scroll-margin-block: 1rlh;
|
||||
}
|
||||
|
||||
// Reduced mootion preference
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Generic / Buttons
|
||||
// ==========================================================================
|
||||
|
||||
// 1. Allow us to style box model properties.
|
||||
// 2. Fixes odd inner spacing in IE7.
|
||||
// 3. Reset/normalize some styles.
|
||||
// 4. Line different sized buttons up a little nicer.
|
||||
// 5. Make buttons inherit font styles (often necessary when styling `input`s as buttons).
|
||||
// 6. Force all button-styled elements to appear clickable.
|
||||
|
||||
button,
|
||||
.c-button {
|
||||
@include u-hocus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
display: inline-block; // [1]
|
||||
overflow: visible; // [2]
|
||||
margin: 0; // [3]
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
background: none transparent;
|
||||
color: inherit;
|
||||
vertical-align: middle; // [4]
|
||||
text-align: center; // [3]
|
||||
text-decoration: none;
|
||||
text-transform: none;
|
||||
font: inherit; // [5]
|
||||
line-height: normal;
|
||||
cursor: pointer; // [6]
|
||||
user-select: none;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Generic / Forms
|
||||
// ==========================================================================
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: none transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
select {
|
||||
text-transform: none;
|
||||
|
||||
&::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-ms-value {
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
// // Remove Firefox :focus dotted outline, breaks color inherit
|
||||
// // &:-moz-focusring {
|
||||
// // color: transparent;
|
||||
// // text-shadow: 0 0 0 #000000; // Text :focus color
|
||||
// // }
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Generic
|
||||
// ==========================================================================
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// Add the correct display in IE 10-.
|
||||
// 1. Add the correct display in IE.
|
||||
|
||||
template, // [1]
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
*,
|
||||
:before,
|
||||
:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
address {
|
||||
font-style: inherit;
|
||||
}
|
||||
|
||||
dfn,
|
||||
cite,
|
||||
em,
|
||||
i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
p,
|
||||
figure {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// 1. Single taps should be dispatched immediately on clickable elements
|
||||
|
||||
a, area, button, input, label, select, textarea, [tabindex] {
|
||||
-ms-touch-action: manipulation; // [1]
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
[hreflang] > abbr[title] {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
hr {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #CCCCCC;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Generic / Media
|
||||
// ==========================================================================
|
||||
|
||||
// 1. Setting `vertical-align` removes the whitespace that appears under `img`
|
||||
// elements when they are dropped into a page as-is. Safer alternative to
|
||||
// using `display: block;`.
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
iframe,
|
||||
img,
|
||||
svg,
|
||||
video {
|
||||
vertical-align: middle; // [1]
|
||||
}
|
||||
|
||||
// Add the correct display in iOS 4-7.
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
// 2. Fluid media for responsive purposes.
|
||||
|
||||
img,
|
||||
svg {
|
||||
max-width: 100%; // [2]
|
||||
height: auto;
|
||||
|
||||
// 4. If a `width` and/or `height` attribute have been explicitly defined,
|
||||
// let’s not make the image fluid.
|
||||
|
||||
&[width], // [4]
|
||||
&[height] {
|
||||
// [4]
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Offset `alt` text from surrounding copy.
|
||||
|
||||
img {
|
||||
font-style: italic; // [4]
|
||||
}
|
||||
|
||||
// 5. SVG elements should fallback to their surrounding text color.
|
||||
|
||||
svg {
|
||||
fill: currentColor; // [5]
|
||||
}
|
||||
@@ -1,16 +1,18 @@
|
||||
// ==========================================================================
|
||||
// Main
|
||||
// ==========================================================================
|
||||
|
||||
// Modules
|
||||
// ==========================================================================
|
||||
|
||||
@use "sass:math";
|
||||
|
||||
// ==========================================================================
|
||||
// Tools
|
||||
// ==========================================================================
|
||||
|
||||
@import "tools/maths";
|
||||
@import "tools/functions";
|
||||
@import "tools/mixins";
|
||||
@import "tools/fonts";
|
||||
// @import "tools/layout";
|
||||
// @import "tools/widths";
|
||||
// @import "tools/family";
|
||||
@@ -18,29 +20,29 @@
|
||||
// Settings
|
||||
// ==========================================================================
|
||||
|
||||
@import "settings/config.eases";
|
||||
@import "settings/config.colors";
|
||||
@import "settings/config";
|
||||
@import "settings/config.breakpoints";
|
||||
@import "settings/config.colors";
|
||||
@import "settings/config.eases";
|
||||
@import "settings/config.fonts";
|
||||
@import "settings/config.spacings";
|
||||
@import "settings/config.speeds";
|
||||
@import "settings/config.zindexes";
|
||||
@import "settings/config.variables";
|
||||
|
||||
// Generic
|
||||
// Vendors
|
||||
// ==========================================================================
|
||||
|
||||
@import "node_modules/normalize.css/normalize";
|
||||
@import "generic/generic";
|
||||
@import "generic/media";
|
||||
@import "generic/form";
|
||||
@import "generic/button";
|
||||
@import "node_modules/locomotive-scroll/dist/locomotive-scroll";
|
||||
|
||||
// Elements
|
||||
// ==========================================================================
|
||||
|
||||
@import "elements/normalize";
|
||||
@import "elements/document";
|
||||
|
||||
// Objects
|
||||
// ==========================================================================
|
||||
|
||||
@import "objects/scroll";
|
||||
@import "objects/container";
|
||||
@import "objects/ratio";
|
||||
@import "objects/icons";
|
||||
@@ -48,17 +50,14 @@
|
||||
// @import "objects/layout";
|
||||
// @import "objects/table";
|
||||
|
||||
// Vendors
|
||||
// ==========================================================================
|
||||
// @import "vendors/vendor";
|
||||
|
||||
// Components
|
||||
// ==========================================================================
|
||||
|
||||
@import "components/scrollbar";
|
||||
@import "components/heading";
|
||||
@import "components/text";
|
||||
@import "components/button";
|
||||
@import "components/form";
|
||||
@import "components/modal";
|
||||
|
||||
// Utilities
|
||||
// ==========================================================================
|
||||
@@ -69,5 +68,5 @@
|
||||
// @import "utilities/align";
|
||||
// @import "utilities/helpers";
|
||||
// @import "utilities/states";
|
||||
// @import "utilities/spacing";
|
||||
@import "utilities/spacing";
|
||||
// @import "utilities/print";
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
&.-col-#{$base-column-nb}\@from-medium {
|
||||
@media (min-width: $from-medium) {
|
||||
&.-col-#{$base-column-nb}\@from-md {
|
||||
@media (min-width: $from-md) {
|
||||
grid-template-columns: repeat(#{$base-column-nb}, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
vertical-align: middle;
|
||||
|
||||
svg {
|
||||
--icon-height: calc(var(--icon-width) * (1 / (var(--icon-ratio))));
|
||||
--icon-height: calc(var(--icon-width) * math.div(1, (var(--icon-ratio))));
|
||||
|
||||
display: block;
|
||||
width: var(--icon-width);
|
||||
@@ -48,7 +48,7 @@
|
||||
// // Logo
|
||||
// .svg-logo {
|
||||
// --icon-width: #{rem(100px)};
|
||||
// --icon-ratio: 20/30; // width/height based on svg viewBox
|
||||
// --icon-ratio: math.div(20, 30); // width/height based on svg viewBox
|
||||
|
||||
// // Sizes
|
||||
// .o-icon.-big & {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Objects / Scroll
|
||||
// ==========================================================================
|
||||
|
||||
.o-scroll {
|
||||
min-height: 100vh;
|
||||
}
|
||||
92
assets/styles/settings/_config.breakpoints.scss
Normal file
92
assets/styles/settings/_config.breakpoints.scss
Normal file
@@ -0,0 +1,92 @@
|
||||
// ==========================================================================
|
||||
// Settings / Config / Breakpoints
|
||||
// ==========================================================================
|
||||
|
||||
// Breakpoints
|
||||
// ==========================================================================
|
||||
|
||||
$breakpoints: (
|
||||
"2xs": 340px,
|
||||
"xs": 500px,
|
||||
"sm": 700px,
|
||||
"md": 1000px,
|
||||
"lg": 1200px,
|
||||
"xl": 1400px,
|
||||
"2xl": 1600px,
|
||||
"3xl": 1800px,
|
||||
"4xl": 2000px,
|
||||
"5xl": 2400px
|
||||
);
|
||||
|
||||
// Functions
|
||||
// ==========================================================================
|
||||
|
||||
// Creates a min-width or max-width media query expression.
|
||||
//
|
||||
// @param {string} $breakpoint The breakpoint.
|
||||
// @param {string} $type Either "min" or "max".
|
||||
// @return {string}
|
||||
|
||||
@function mq($breakpoint, $type: "min") {
|
||||
@if not map-has-key($breakpoints, $breakpoint) {
|
||||
@warn "Unknown media query breakpoint: `#{$breakpoint}`";
|
||||
}
|
||||
|
||||
$value: map-get($breakpoints, $breakpoint);
|
||||
|
||||
@if ($type == "min") {
|
||||
@return "(min-width: #{$value})";
|
||||
}
|
||||
@if ($type == "max") {
|
||||
@return "(max-width: #{$value - 1px})";
|
||||
}
|
||||
|
||||
@error "Unknown media query type: #{$type}";
|
||||
}
|
||||
|
||||
// Creates a min-width media query expression.
|
||||
//
|
||||
// @param {string} $breakpoint The breakpoint.
|
||||
// @return {string}
|
||||
|
||||
@function mq-min($breakpoint) {
|
||||
@return mq($breakpoint, "min");
|
||||
}
|
||||
|
||||
// Creates a max-width media query expression.
|
||||
//
|
||||
// @param {string} $breakpoint The breakpoint.
|
||||
// @return {string}
|
||||
|
||||
@function mq-max($breakpoint) {
|
||||
@return mq($breakpoint, "max");
|
||||
}
|
||||
|
||||
// Creates a min-width and max-width media query expression.
|
||||
//
|
||||
// @param {string} $from The min-width breakpoint.
|
||||
// @param {string} $until The max-width breakpoint.
|
||||
// @return {string}
|
||||
|
||||
@function mq-between($breakpointMin, $breakpointMax) {
|
||||
@return "#{mq-min($breakpointMin)} and #{mq-max($breakpointMax)}";
|
||||
}
|
||||
|
||||
|
||||
// Legacy
|
||||
// ==========================================================================
|
||||
|
||||
$from-xs: map-get($breakpoints, "xs") !default;
|
||||
$to-xs: map-get($breakpoints, "xs") - 1 !default;
|
||||
$from-sm: map-get($breakpoints, "sm") !default;
|
||||
$to-sm: map-get($breakpoints, "sm") - 1 !default;
|
||||
$from-md: map-get($breakpoints, "md") !default;
|
||||
$to-md: map-get($breakpoints, "md") - 1 !default;
|
||||
$from-lg: map-get($breakpoints, "lg") !default;
|
||||
$to-lg: map-get($breakpoints, "lg") - 1 !default;
|
||||
$from-xl: map-get($breakpoints, "xl") !default;
|
||||
$to-xl: map-get($breakpoints, "xl") - 1 !default;
|
||||
$from-2xl: map-get($breakpoints, "2xl") !default;
|
||||
$to-2xl: map-get($breakpoints, "2xl") - 1 !default;
|
||||
$from-3xl: map-get($breakpoints, "3xl") !default;
|
||||
$to-3xl: map-get($breakpoints, "3xl") - 1 !default;
|
||||
@@ -3,26 +3,56 @@
|
||||
// ==========================================================================
|
||||
|
||||
// Palette
|
||||
// =============================================================================
|
||||
// ==========================================================================
|
||||
|
||||
$color-lightest: #FFFFFF;
|
||||
$color-darkest: #000000;
|
||||
$colors: (
|
||||
primary: #3297FD,
|
||||
lightest: #FFFFFF,
|
||||
darkest: #000000,
|
||||
);
|
||||
|
||||
// Specific
|
||||
// =============================================================================
|
||||
// Function
|
||||
// ==========================================================================
|
||||
|
||||
// Returns color code.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// color: color(primary);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {string} $key - The color key in $colors.
|
||||
// @param {number} $alpha - The alpha for the color value.
|
||||
// @return {color}
|
||||
|
||||
@function color($key, $alpha: 1) {
|
||||
@if not map-has-key($colors, $key) {
|
||||
@error "Unknown '#{$key}' in $colors.";
|
||||
}
|
||||
|
||||
@if($alpha < 0 or $alpha > 1) {
|
||||
@error "Alpha '#{$alpha}' must be in range [0, 1].";
|
||||
}
|
||||
|
||||
$color: map-get($colors, $key);
|
||||
|
||||
@return rgba($color, $alpha);
|
||||
}
|
||||
|
||||
// Specifics
|
||||
// ==========================================================================
|
||||
|
||||
// Link
|
||||
$color-link: #1A0DAB;
|
||||
$color-link-focus: #1A0DAB;
|
||||
$color-link-hover: darken(#1A0DAB, 10%);
|
||||
$color-link: color(primary);
|
||||
$color-link-focus: color(primary);
|
||||
$color-link-hover: darken(color(primary), 10%);
|
||||
|
||||
// Selection
|
||||
$selection-text-color: #3297FD;
|
||||
$selection-background-color: #FFFFFF;
|
||||
|
||||
// Social Colors
|
||||
// =============================================================================
|
||||
$color-selection-text: color(darkest);
|
||||
$color-selection-background: color(lightest);
|
||||
|
||||
// Socials
|
||||
$color-facebook: #3B5998;
|
||||
$color-instagram: #E1306C;
|
||||
$color-youtube: #CD201F;
|
||||
|
||||
@@ -2,47 +2,77 @@
|
||||
// Settings / Config / Eases
|
||||
// ==========================================================================
|
||||
|
||||
// Power 1
|
||||
$ease-power1-in: cubic-bezier(0.550, 0.085, 0.680, 0.530);
|
||||
$ease-power1-out: cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
$ease-power1-in-out: cubic-bezier(0.455, 0.030, 0.515, 0.955);
|
||||
// Eases
|
||||
// ==========================================================================
|
||||
|
||||
// Power 2
|
||||
$ease-power2-in: cubic-bezier(0.550, 0.055, 0.675, 0.190);
|
||||
$ease-power2-out: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
$ease-power2-in-out: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
$eases: (
|
||||
// Power 1
|
||||
"power1.in": cubic-bezier(0.550, 0.085, 0.680, 0.530),
|
||||
"power1.out": cubic-bezier(0.250, 0.460, 0.450, 0.940),
|
||||
"power1.inOut": cubic-bezier(0.455, 0.030, 0.515, 0.955),
|
||||
|
||||
// Power 3
|
||||
$ease-power3-in: cubic-bezier(0.895, 0.030, 0.685, 0.220);
|
||||
$ease-power3-out: cubic-bezier(0.165, 0.840, 0.440, 1.000);
|
||||
$ease-power3-in-out: cubic-bezier(0.770, 0.000, 0.175, 1.000);
|
||||
// Power 2
|
||||
"power2.in": cubic-bezier(0.550, 0.055, 0.675, 0.190),
|
||||
"power2.out": cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
"power2.inOut": cubic-bezier(0.645, 0.045, 0.355, 1.000),
|
||||
|
||||
// Power 3
|
||||
$ease-power4-in: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
$ease-power4-out: cubic-bezier(0.230, 1.000, 0.320, 1.000);
|
||||
$ease-power4-in-out: cubic-bezier(0.860, 0.000, 0.070, 1.000);
|
||||
// Power 3
|
||||
"power3.in": cubic-bezier(0.895, 0.030, 0.685, 0.220),
|
||||
"power3.out": cubic-bezier(0.165, 0.840, 0.440, 1.000),
|
||||
"power3.inOut": cubic-bezier(0.770, 0.000, 0.175, 1.000),
|
||||
|
||||
// Expo
|
||||
$ease-expo-in: cubic-bezier(0.950, 0.050, 0.795, 0.035);
|
||||
$ease-expo-out: cubic-bezier(0.190, 1.000, 0.220, 1.000);
|
||||
$ease-expo-in-out: cubic-bezier(1.000, 0.000, 0.000, 1.000);
|
||||
// Power 4
|
||||
"power4.in": cubic-bezier(0.755, 0.050, 0.855, 0.060),
|
||||
"power4.out": cubic-bezier(0.230, 1.000, 0.320, 1.000),
|
||||
"power4.inOut": cubic-bezier(0.860, 0.000, 0.070, 1.000),
|
||||
|
||||
// Back
|
||||
$ease-back-in: cubic-bezier(0.600, -0.280, 0.735, 0.045);
|
||||
$ease-back-out: cubic-bezier(0.175, 00.885, 0.320, 1.275);
|
||||
$ease-back-in-out: cubic-bezier(0.680, -0.550, 0.265, 1.550);
|
||||
// Expo
|
||||
"expo.in": cubic-bezier(0.950, 0.050, 0.795, 0.035),
|
||||
"expo.out": cubic-bezier(0.190, 1.000, 0.220, 1.000),
|
||||
"expo.inOut": cubic-bezier(1.000, 0.000, 0.000, 1.000),
|
||||
|
||||
// Sine
|
||||
$ease-sine-in: cubic-bezier(0.470, 0.000, 0.745, 0.715);
|
||||
$ease-sine-out: cubic-bezier(0.390, 0.575, 0.565, 1.000);
|
||||
$ease-sine-in-out: cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
||||
// Back
|
||||
"back.in": cubic-bezier(0.600, -0.280, 0.735, 0.045),
|
||||
"back.out": cubic-bezier(0.175, 00.885, 0.320, 1.275),
|
||||
"back.inOut": cubic-bezier(0.680, -0.550, 0.265, 1.550),
|
||||
|
||||
// Circ
|
||||
$ease-circ-in: cubic-bezier(0.600, 0.040, 0.980, 0.335);
|
||||
$ease-circ-out: cubic-bezier(0.075, 0.820, 0.165, 1.000);
|
||||
$ease-circ-in-out: cubic-bezier(0.785, 0.135, 0.150, 0.860);
|
||||
// Sine
|
||||
"sine.in": cubic-bezier(0.470, 0.000, 0.745, 0.715),
|
||||
"sine.out": cubic-bezier(0.390, 0.575, 0.565, 1.000),
|
||||
"sine.inOut": cubic-bezier(0.445, 0.050, 0.550, 0.950),
|
||||
|
||||
// Misc
|
||||
$ease-bounce: cubic-bezier(0.17, 0.67, 0.3, 1.33);
|
||||
$ease-slow-out: cubic-bezier(.04,1.15,0.4,.99);
|
||||
$ease-smooth: cubic-bezier(0.380, 0.005, 0.215, 1);
|
||||
// Circ
|
||||
"circ.in": cubic-bezier(0.600, 0.040, 0.980, 0.335),
|
||||
"circ.out": cubic-bezier(0.075, 0.820, 0.165, 1.000),
|
||||
"circ.inOut": cubic-bezier(0.785, 0.135, 0.150, 0.860),
|
||||
|
||||
// Misc
|
||||
"bounce": cubic-bezier(0.17, 0.67, 0.3, 1.33),
|
||||
"slow.out": cubic-bezier(.04,1.15,0.4,.99),
|
||||
"smooth": cubic-bezier(0.380, 0.005, 0.215, 1),
|
||||
);
|
||||
|
||||
// Default value for ease()
|
||||
$ease-default: "power2.out" !default;
|
||||
|
||||
// Function
|
||||
// ==========================================================================
|
||||
|
||||
// Returns ease curve.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// transition-timing-function: ease("power2.out");
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {string} $key - The ease key in $eases.
|
||||
// @return {easing-function}
|
||||
|
||||
@function ease($key: $ease-default) {
|
||||
@if not map-has-key($eases, $key) {
|
||||
@error "Unknown '#{$key}' in $eases.";
|
||||
}
|
||||
|
||||
@return map-get($eases, $key);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
// ==========================================================================
|
||||
// Tools / Font Faces
|
||||
// Settings / Config / Breakpoints
|
||||
// ==========================================================================
|
||||
|
||||
// Font fallbacks (retrieved from systemfontstack.com on 2022-05-31)
|
||||
// ==========================================================================
|
||||
|
||||
$font-fallback-sans: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
$font-fallback-serif: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
$font-fallback-mono: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||
|
||||
// Typefaces
|
||||
// ==========================================================================
|
||||
|
||||
// List of custom font faces as tuples.
|
||||
//
|
||||
// ```
|
||||
// <font-name> <font-file-basename> <font-weight> <font-style>
|
||||
// ```
|
||||
$font-faces: (
|
||||
("Source Sans", "SourceSans3-Bold", 700, normal),
|
||||
("Source Sans", "SourceSans3-BoldIt", 700, italic),
|
||||
("Source Sans", "SourceSans3-Regular", 400, normal),
|
||||
("Source Sans", "SourceSans3-RegularIt", 400, italic),
|
||||
);
|
||||
|
||||
// Map of font families.
|
||||
//
|
||||
// ```
|
||||
// <font-id>: (<font-name>, <font-fallbacks>)
|
||||
// ```
|
||||
$font-families: (
|
||||
sans: join("Source Sans", $font-fallback-sans, $separator: comma),
|
||||
);
|
||||
|
||||
// Font directory
|
||||
$font-dir: "../fonts/";
|
||||
|
||||
// Functions
|
||||
// ==========================================================================
|
||||
|
||||
// Imports the custom font.
|
||||
@@ -11,45 +11,13 @@ $context: frontend !default;
|
||||
// Path is relative to the stylesheets directory.
|
||||
$assets-path: "../" !default;
|
||||
|
||||
// Typefaces
|
||||
// =============================================================================
|
||||
|
||||
// Font directory
|
||||
$font-dir: "../fonts/";
|
||||
|
||||
// Font fallbacks (retrieved from systemfontstack.com on 2022-05-31)
|
||||
$font-fallback-sans: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
$font-fallback-serif: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
$font-fallback-mono: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||
|
||||
// Map of font families.
|
||||
//
|
||||
// ```
|
||||
// <font-id>: (<font-name>, <font-fallbacks>)
|
||||
// ```
|
||||
$font-families: (
|
||||
sans: join("Source Sans", $font-fallback-sans, $separator: comma),
|
||||
);
|
||||
|
||||
// List of custom font faces as tuples.
|
||||
//
|
||||
// ```
|
||||
// <font-name> <font-file-basename> <font-weight> <font-style>
|
||||
// ```
|
||||
$font-faces: (
|
||||
("Source Sans", "SourceSans3-Bold", 700, normal),
|
||||
("Source Sans", "SourceSans3-BoldIt", 700, italic),
|
||||
("Source Sans", "SourceSans3-Regular", 400, normal),
|
||||
("Source Sans", "SourceSans3-RegularIt", 400, italic),
|
||||
);
|
||||
|
||||
// Typography
|
||||
// =============================================================================
|
||||
|
||||
// Base
|
||||
$font-size: 16px;
|
||||
$font-size: 16px;
|
||||
$line-height: math.div(24px, $font-size);
|
||||
$font-color: $color-darkest;
|
||||
$font-color: color(darkest);
|
||||
|
||||
// Weights
|
||||
$font-weight-light: 300;
|
||||
@@ -57,52 +25,21 @@ $font-weight-normal: 400;
|
||||
$font-weight-medium: 500;
|
||||
$font-weight-bold: 700;
|
||||
|
||||
// Transitions
|
||||
// Transition defaults
|
||||
// =============================================================================
|
||||
|
||||
$speed: 0.3s;
|
||||
$easing: $ease-power2-out;
|
||||
$speed: t(normal);
|
||||
$easing: ease("power2.out");
|
||||
|
||||
// Spacing Units
|
||||
// =============================================================================
|
||||
$unit: 60px;
|
||||
$unit-small: 20px;
|
||||
$unit: 60px;
|
||||
$unit-small: 20px;
|
||||
$vw-viewport: 1440;
|
||||
|
||||
// Container
|
||||
// ==========================================================================
|
||||
$padding: $unit;
|
||||
$padding: $unit;
|
||||
|
||||
// Grid
|
||||
// ==========================================================================
|
||||
$base-column-nb: 12;
|
||||
|
||||
// Breakpoints
|
||||
// =============================================================================
|
||||
|
||||
$from-tiny: 500px !default;
|
||||
$to-tiny: $from-tiny - 1 !default;
|
||||
$from-small: 700px !default;
|
||||
$to-small: $from-small - 1 !default;
|
||||
$from-medium: 1000px !default;
|
||||
$to-medium: $from-medium - 1 !default;
|
||||
$from-large: 1200px !default;
|
||||
$to-large: $from-large - 1 !default;
|
||||
$from-big: 1400px !default;
|
||||
$to-big: $from-big - 1 !default;
|
||||
$from-huge: 1600px !default;
|
||||
$to-huge: $from-huge - 1 !default;
|
||||
$from-enormous: 1800px !default;
|
||||
$to-enormous: $from-enormous - 1 !default;
|
||||
$from-gigantic: 2000px !default;
|
||||
$to-gigantic: $from-gigantic - 1 !default;
|
||||
$from-colossal: 2400px !default;
|
||||
$to-colossal: $from-colossal - 1 !default;
|
||||
|
||||
// Master z-indexe
|
||||
// =============================================================================
|
||||
|
||||
$z-indexes: (
|
||||
"header": 200,
|
||||
"above": 1,
|
||||
"below": -1
|
||||
);
|
||||
|
||||
69
assets/styles/settings/_config.spacings.scss
Normal file
69
assets/styles/settings/_config.spacings.scss
Normal file
@@ -0,0 +1,69 @@
|
||||
// ==========================================================================
|
||||
// Settings / Config / Spacings
|
||||
// ==========================================================================
|
||||
|
||||
:root {
|
||||
--spacing-2xs-mobile: 6;
|
||||
--spacing-2xs-desktop: 10;
|
||||
|
||||
--spacing-xs-mobile: 12;
|
||||
--spacing-xs-desktop: 16;
|
||||
|
||||
--spacing-sm-mobile: 22;
|
||||
--spacing-sm-desktop: 32;
|
||||
|
||||
--spacing-md-mobile: 32;
|
||||
--spacing-md-desktop: 56;
|
||||
|
||||
--spacing-lg-mobile: 48;
|
||||
--spacing-lg-desktop: 96;
|
||||
|
||||
--spacing-xl-mobile: 64;
|
||||
--spacing-xl-desktop: 128;
|
||||
|
||||
--spacing-2xl-mobile: 88;
|
||||
--spacing-2xl-desktop: 176;
|
||||
|
||||
--spacing-3xl-mobile: 122;
|
||||
--spacing-3xl-desktop: 224;
|
||||
}
|
||||
|
||||
// Spacings
|
||||
// ==========================================================================
|
||||
|
||||
$spacings: (
|
||||
'gutter': var(--grid-gutter),
|
||||
'2xs': #{size-clamp('2xs')},
|
||||
'xs': #{size-clamp('xs')},
|
||||
'sm': #{size-clamp('sm')},
|
||||
'md': #{size-clamp('md')},
|
||||
'lg': #{size-clamp('lg')},
|
||||
'xl': #{size-clamp('xl')},
|
||||
'2xl': #{size-clamp('2xl')},
|
||||
'3xl': #{size-clamp('3xl')},
|
||||
);
|
||||
|
||||
// Function
|
||||
// ==========================================================================
|
||||
|
||||
// Returns spacing.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// margin-top: spacing(gutter);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {string} $key - The spacing key in $spacings.
|
||||
// @param {number} $multiplier - The multiplier of the spacing value.
|
||||
// @return {size}
|
||||
|
||||
@function spacing($spacing: 'sm', $multiplier: 1) {
|
||||
@if not map-has-key($spacings, $spacing) {
|
||||
@error "Unknown master spacing: #{$spacing}";
|
||||
}
|
||||
|
||||
$index: map-get($spacings, $spacing);
|
||||
|
||||
@return calc(#{$index} * #{$multiplier});
|
||||
}
|
||||
38
assets/styles/settings/_config.speeds.scss
Normal file
38
assets/styles/settings/_config.speeds.scss
Normal file
@@ -0,0 +1,38 @@
|
||||
// ==========================================================================
|
||||
// Settings / Config / Speeds
|
||||
// ==========================================================================
|
||||
|
||||
// Speeds
|
||||
// ==========================================================================
|
||||
|
||||
$speeds: (
|
||||
fastest: 0.1s,
|
||||
faster: 0.15s,
|
||||
fast: 0.25s,
|
||||
normal: 0.3s,
|
||||
slow: 0.5s,
|
||||
slower: 0.75s,
|
||||
slowest: 1s,
|
||||
);
|
||||
|
||||
// Function
|
||||
// ==========================================================================
|
||||
|
||||
// Returns timing.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// transition-duration: speed(slow);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {string} $key - The speed key in $speeds.
|
||||
// @return {duration}
|
||||
|
||||
@function speed($key: "normal") {
|
||||
@if not map-has-key($speeds, $key) {
|
||||
@error "Unknown '#{$key}' in $speeds.";
|
||||
}
|
||||
|
||||
@return map-get($speeds, $key);
|
||||
}
|
||||
@@ -7,21 +7,12 @@
|
||||
// Grid
|
||||
--grid-columns: 4;
|
||||
--grid-gutter: #{rem(10px)};
|
||||
--grid-gutter-half: calc(0.5 * var(--grid-gutter));
|
||||
--grid-margin: #{rem(10px)};
|
||||
|
||||
// Container
|
||||
--container-width: calc(100% - 2 * var(--grid-margin));
|
||||
|
||||
// Font sizes
|
||||
--font-size-h1: #{rem(36px)};
|
||||
--font-size-h2: #{rem(28px)};
|
||||
--font-size-h3: #{rem(24px)};
|
||||
--font-size-h4: #{rem(20px)};
|
||||
--font-size-h5: #{rem(18px)};
|
||||
--font-size-h6: #{rem(16px)};
|
||||
|
||||
@media (min-width: $from-small) {
|
||||
@media (min-width: $from-sm) {
|
||||
--grid-columns: #{$base-column-nb};
|
||||
--grid-gutter: #{rem(16px)};
|
||||
--grid-margin: #{rem(20px)};
|
||||
|
||||
44
assets/styles/settings/_config.zindexes.scss
Normal file
44
assets/styles/settings/_config.zindexes.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
// ==========================================================================
|
||||
// Settings / Config / Z-indexes
|
||||
// ==========================================================================
|
||||
|
||||
// Timings
|
||||
// ==========================================================================
|
||||
|
||||
$z-indexes: (
|
||||
"header": 200,
|
||||
"above": 1,
|
||||
"default": 0,
|
||||
"below": -1
|
||||
);
|
||||
|
||||
// Default z-index for z()
|
||||
$z-index-default: "above" !default;
|
||||
|
||||
// Function
|
||||
// ==========================================================================
|
||||
|
||||
// Retrieves the z-index from the {@see $layers master list}.
|
||||
//
|
||||
// @link on http://css-tricks.com/handling-z-index/
|
||||
//
|
||||
// @param {string} $layer The name of the z-index.
|
||||
// @param {number} $modifier A positive or negative modifier to apply
|
||||
// to the returned z-index value.
|
||||
// @throw Error if the $layer does not exist.
|
||||
// @throw Warning if the $modifier might overlap another master z-index.
|
||||
// @return {number} The computed z-index of $layer and $modifier.
|
||||
|
||||
@function z($layer: $z-index-default, $modifier: 0) {
|
||||
@if not map-has-key($z-indexes, $layer) {
|
||||
@error "Unknown master z-index layer: #{$layer}";
|
||||
}
|
||||
|
||||
@if ($modifier >= 50 or $modifier <= -50) {
|
||||
@warn "Modifier may overlap the another master z-index layer: #{$modifier}";
|
||||
}
|
||||
|
||||
$index: map-get($z-indexes, $layer);
|
||||
|
||||
@return $index + $modifier;
|
||||
}
|
||||
@@ -147,7 +147,7 @@
|
||||
// @param {number} $num - id of the child
|
||||
|
||||
@mixin middle($num) {
|
||||
&:nth-child(#{round($num / 2)}) {
|
||||
&:nth-child(#{round(math.div($num, 2))}) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,42 +48,6 @@
|
||||
@return math.div($size, $base) * 1rem;
|
||||
}
|
||||
|
||||
// Retrieves the z-index from the {@see $layers master list}.
|
||||
//
|
||||
// @link on http://css-tricks.com/handling-z-index/
|
||||
//
|
||||
// @param {string} $layer The name of the z-index.
|
||||
// @param {number} $modifier A positive or negative modifier to apply
|
||||
// to the returned z-index value.
|
||||
// @throw Error if the $layer does not exist.
|
||||
// @throw Warning if the $modifier might overlap another master z-index.
|
||||
// @return {number} The computed z-index of $layer and $modifier.
|
||||
|
||||
@function z($layer, $modifier: 0) {
|
||||
@if not map-has-key($z-indexes, $layer) {
|
||||
@error "Unknown master z-index layer: #{$layer}";
|
||||
}
|
||||
|
||||
@if ($modifier >= 50 or $modifier <= -50) {
|
||||
@warn "Modifier may overlap the another master z-index layer: #{$modifier}";
|
||||
}
|
||||
|
||||
$index: map-get($z-indexes, $layer);
|
||||
|
||||
@return $index + $modifier;
|
||||
}
|
||||
|
||||
// Converts a number to a percentage.
|
||||
//
|
||||
// @alias percentage()
|
||||
// @link http://sassdoc.com/annotations/#alias
|
||||
// @param {Number} $number - The value to convert.
|
||||
// @return {Number} A percentage.
|
||||
|
||||
@function span($number) {
|
||||
@return percentage($number);
|
||||
}
|
||||
|
||||
// Checks if a list contains a value(s).
|
||||
//
|
||||
// @link https://github.com/thoughtbot/bourbon/blob/master/core/bourbon/validators/_contains.scss
|
||||
@@ -139,3 +103,112 @@
|
||||
}
|
||||
|
||||
$context: 'frontend' !default;
|
||||
|
||||
// Returns calculation of a percentage of the grid cell width
|
||||
// with optional inset of grid gutter.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// width: grid-space(6/12);
|
||||
// margin-left: grid-space(1/12, 1);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $percentage - The percentage spacer
|
||||
// @param {number} $inset - The grid gutter inset
|
||||
// @return {function<number>}
|
||||
@function grid-space($percentage, $inset: 0) {
|
||||
@return calc(#{$percentage} * (#{vw(100)} - 2 * var(--grid-margin, 0px)) - (1 - #{$percentage}) * var(--grid-gutter, 0px) + #{$inset} * var(--grid-gutter, 0px));
|
||||
}
|
||||
|
||||
// Returns calculation of a percentage of the viewport small height.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// height: svh(100);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $number - The percentage number
|
||||
// @return {function<number>} in svh
|
||||
@function svh($number) {
|
||||
@return calc(#{$number} * var(--svh, 1svh));
|
||||
}
|
||||
|
||||
// Returns calculation of a percentage of the viewport large height.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// height: lvh(100);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $number - The percentage number
|
||||
// @return {function<number>} in lvh
|
||||
@function lvh($number) {
|
||||
@return calc(#{$number} * var(--lvh, 1lvh));
|
||||
}
|
||||
|
||||
// Returns calculation of a percentage of the viewport dynamic height.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// height: dvh(100);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $number - The percentage number
|
||||
// @return {function<number>} in dvh
|
||||
@function dvh($number) {
|
||||
@return calc(#{$number} * var(--dvh, 1dvh));
|
||||
}
|
||||
|
||||
// Returns calculation of a percentage of the viewport width.
|
||||
//
|
||||
// ```scss
|
||||
// .c-box {
|
||||
// width: vw(100);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $number - The percentage number
|
||||
// @return {function<number>} in vw
|
||||
|
||||
@function vw($number) {
|
||||
@return calc(#{$number} * var(--vw, 1vw));
|
||||
}
|
||||
|
||||
@function clamp-with-max($min, $size, $max) {
|
||||
$vw-context: $vw-viewport * 0.01;
|
||||
@return clamp(#{$min}, calc(#{$size} / #{$vw-context} * 1vw), #{$max});
|
||||
}
|
||||
|
||||
@function size-clamp($size) {
|
||||
@return clamp-with-max(
|
||||
calc(#{rem(1px)} * var(--spacing-#{$size}-mobile)),
|
||||
var(--spacing-#{$size}-desktop),
|
||||
calc(#{rem(1px)} * var(--spacing-#{$size}-desktop))
|
||||
);
|
||||
}
|
||||
|
||||
// Returns clamp of calculated preferred responsive font size
|
||||
// within a font size and breakpoint range.
|
||||
//
|
||||
// ```scss
|
||||
// .c-heading.-h1 {
|
||||
// font-size: responsive-value(30px, 60px, 1800);
|
||||
// }
|
||||
//
|
||||
// .c-heading.-h2 {
|
||||
// font-size: responsive-value(20px, 40px, $from-xl);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// @param {number} $min-size - Minimum font size in pixels.
|
||||
// @param {number} $max-size - Maximum font size in pixels.
|
||||
// @param {number} $breakpoint - Maximum breakpoint.
|
||||
// @return {function<number, function<number>, number>}
|
||||
@function responsive-value($min-size, $max-size, $breakpoint) {
|
||||
$delta: math.div($max-size, $breakpoint);
|
||||
@return clamp($min-size, calc(#{strip-unit($delta)} * #{vw(100)}), $max-size);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
// Tools / Maths
|
||||
// ==========================================================================
|
||||
|
||||
// Removes the unit from the given number.
|
||||
// Remove the unit of a length
|
||||
//
|
||||
// @param {number} $number The number to strip.
|
||||
// @return {number}
|
||||
// @param {Number} $number Number to remove unit from
|
||||
// @return {function<number>}
|
||||
@function strip-unit($value) {
|
||||
@if type-of($value) != "number" {
|
||||
@error "Invalid `#{type-of($value)}` type. Choose a number type instead.";
|
||||
} @else if type-of($value) == "number" and not is-unitless($value) {
|
||||
@return math.div($value, $value * 0 + 1);
|
||||
}
|
||||
|
||||
@function strip-units($number) {
|
||||
@return $number / ($number * 0 + 1);
|
||||
@return $value;
|
||||
}
|
||||
|
||||
// Returns the square root of the given number.
|
||||
@@ -21,7 +26,7 @@
|
||||
$value: $x;
|
||||
|
||||
@for $i from 1 through 10 {
|
||||
$value: $x - ($x * $x - abs($number)) / (2 * $x);
|
||||
$value: $x - math.div(($x * $x - abs($number)), (2 * $x));
|
||||
$x: $value;
|
||||
}
|
||||
|
||||
@@ -43,7 +48,7 @@
|
||||
}
|
||||
} @else if $exp < 0 {
|
||||
@for $i from 1 through -$exp {
|
||||
$value: $value / $number;
|
||||
$value: math.div($value, $number);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +93,7 @@
|
||||
|
||||
// If the angle has `deg` as unit, convert to radians.
|
||||
@if ($unit == deg) {
|
||||
@return $angle / 180 * pi();
|
||||
@return math.div($angle, 180) * pi();
|
||||
}
|
||||
|
||||
@return $angle;
|
||||
@@ -104,7 +109,7 @@
|
||||
$angle: rad($angle);
|
||||
|
||||
@for $i from 0 through 10 {
|
||||
$sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
|
||||
$sin: $sin + pow(-1, $i) * math.div(pow($angle, (2 * $i + 1)), fact(2 * $i + 1));
|
||||
}
|
||||
|
||||
@return $sin;
|
||||
@@ -120,7 +125,7 @@
|
||||
$angle: rad($angle);
|
||||
|
||||
@for $i from 0 through 10 {
|
||||
$cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
|
||||
$cos: $cos + pow(-1, $i) * math.div(pow($angle, 2 * $i), fact(2 * $i));
|
||||
}
|
||||
|
||||
@return $cos;
|
||||
@@ -132,5 +137,5 @@
|
||||
// @return {number}
|
||||
|
||||
@function tan($angle) {
|
||||
@return sin($angle) / cos($angle);
|
||||
@return math.div(sin($angle), cos($angle));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
font-size: rem($font-size) $important;
|
||||
|
||||
@if ($line-height == "auto") {
|
||||
line-height: ceil($font-size / $line-height) * ($line-height / $font-size) $important;
|
||||
line-height: ceil(math.div($font-size, $line-height)) * math.div($line-height, $font-size) $important;
|
||||
}
|
||||
@else {
|
||||
@if (type-of($line-height) == number or $line-height == "inherit" or $line-height == "normal") {
|
||||
@@ -193,3 +193,32 @@
|
||||
display: $display $important;
|
||||
visibility: visible $important;
|
||||
}
|
||||
|
||||
// Aspect-ratio polyfill
|
||||
//
|
||||
// @param {Number} $ratio [19/6] - The ratio of the element.
|
||||
// @param {Number} $width [100%] - The fallback width of element.
|
||||
// @param {Boolean} $children [false] - Whether the element contains children for the fallback properties.
|
||||
// @output Properties for maintaining aspect-ratio
|
||||
|
||||
@mixin aspect-ratio($ratio: math.div(16, 9), $width: 100%, $children: false) {
|
||||
|
||||
@supports (aspect-ratio: 1) {
|
||||
aspect-ratio: $ratio;
|
||||
}
|
||||
|
||||
@supports not (aspect-ratio: 1) {
|
||||
height: 0;
|
||||
padding-top: calc(#{$width} * #{math.div(1, $ratio)});
|
||||
|
||||
@if ($children == true) {
|
||||
position: relative;
|
||||
|
||||
> * {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ $breakpoint-delimiter: \@ !default;
|
||||
@for $numerator from 1 through $denominator {
|
||||
// Build a class in the format `.u-3/4[@<breakpoint>]`.
|
||||
.u-#{$numerator}#{$fractions-delimiter}#{$denominator}#{$breakpoint} {
|
||||
width: ($numerator / $denominator) * 100% $important;
|
||||
width: math.div($numerator, $denominator) * 100% $important;
|
||||
}
|
||||
|
||||
@if ($widths-offsets == true) {
|
||||
@@ -66,13 +66,13 @@ $breakpoint-delimiter: \@ !default;
|
||||
.u-push-#{$numerator}#{$fractions-delimiter}#{$denominator}#{$breakpoint} {
|
||||
position: relative $important;
|
||||
right: auto $important;
|
||||
left: ($numerator / $denominator) * 100% $important;
|
||||
left: math.div($numerator, $denominator) * 100% $important;
|
||||
}
|
||||
|
||||
// Build a class in the format `.u-pull-5/6[@<breakpoint>]`.
|
||||
.u-pull-#{$numerator}#{$fractions-delimiter}#{$denominator}#{$breakpoint} {
|
||||
position: relative $important;
|
||||
right: ($numerator / $denominator) * 100% $important;
|
||||
right: math.div($numerator, $denominator) * 100% $important;
|
||||
left: auto $important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,29 +11,31 @@
|
||||
|
||||
$colsMax: $base-column-nb + 1;
|
||||
|
||||
$breakpoints: (
|
||||
"null" null,
|
||||
"from-tiny" $from-tiny,
|
||||
"from-small" $from-small,
|
||||
"from-medium" $from-medium,
|
||||
"from-large" $from-large,
|
||||
"from-big" $from-big
|
||||
) !default;
|
||||
|
||||
@each $breakpoint, $mediaquery in $breakpoints {
|
||||
@for $fromIndex from 1 through $colsMax {
|
||||
@for $toIndex from 1 through $colsMax {
|
||||
@if $mediaquery == null {
|
||||
|
||||
// Columns without media query
|
||||
@if $breakpoint == "tiny" {
|
||||
.u-gc-#{$fromIndex}\/#{$toIndex} {
|
||||
--gc-start: #{$fromIndex};
|
||||
--gc-end: #{$toIndex};
|
||||
}
|
||||
} @else {
|
||||
.u-gc-#{$fromIndex}\/#{$toIndex}\@#{$breakpoint} {
|
||||
@media (min-width: #{$mediaquery}) {
|
||||
--gc-start: #{$fromIndex};
|
||||
--gc-end: #{$toIndex};
|
||||
}
|
||||
}
|
||||
|
||||
// Columns min-width breakpoints `@from-*`
|
||||
.u-gc-#{$fromIndex}\/#{$toIndex}\@from-#{$breakpoint} {
|
||||
@media #{mq-min($breakpoint)} {
|
||||
--gc-start: #{$fromIndex};
|
||||
--gc-end: #{$toIndex};
|
||||
}
|
||||
}
|
||||
|
||||
// Columns max-width breakpoints @to-*`
|
||||
.u-gc-#{$fromIndex}\/#{$toIndex}\@to-#{$breakpoint} {
|
||||
@media #{mq-max($breakpoint)} {
|
||||
--gc-start: #{$fromIndex};
|
||||
--gc-end: #{$toIndex};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
///
|
||||
/// @example
|
||||
/// .u-margin-top {}
|
||||
/// .u-padding-left-large {}
|
||||
/// .u-margin-right-small {}
|
||||
/// .u-margin-top-xs {}
|
||||
/// .u-padding-left-lg {}
|
||||
/// .u-margin-right-sm {}
|
||||
/// .u-padding {}
|
||||
/// .u-padding-right-none {}
|
||||
/// .u-padding-horizontal {}
|
||||
/// .u-padding-vertical-small {}
|
||||
///
|
||||
/// @link https://github.com/inuitcss/inuitcss/blob/512977a/utilities/_utilities.spacing.scss
|
||||
////
|
||||
@@ -26,8 +25,8 @@ $spacing-directions: (
|
||||
'-right': '-right',
|
||||
'-bottom': '-bottom',
|
||||
'-left': '-left',
|
||||
'-horizontal': '-left' '-right',
|
||||
'-vertical': '-top' '-bottom',
|
||||
'-x': '-left' '-right',
|
||||
'-y': '-top' '-bottom',
|
||||
) !default;
|
||||
|
||||
$spacing-properties: (
|
||||
@@ -35,19 +34,47 @@ $spacing-properties: (
|
||||
'margin': 'margin',
|
||||
) !default;
|
||||
|
||||
$spacing-sizes: (
|
||||
null: $unit,
|
||||
'-double': $unit * 2,
|
||||
'-small': $unit-small,
|
||||
'-none': 0px
|
||||
) !default;
|
||||
$spacing-sizes: join($spacings, (
|
||||
null: var(--grid-gutter),
|
||||
'none': 0
|
||||
));
|
||||
|
||||
@each $property-namespace, $property in $spacing-properties {
|
||||
@each $direction-namespace, $direction-rules in $spacing-directions {
|
||||
@each $size-namespace, $size in $spacing-sizes {
|
||||
.u-#{$property-namespace}#{$direction-namespace}#{$size-namespace} {
|
||||
@each $direction in $direction-rules {
|
||||
#{$property}#{$direction}: rem($size) !important;
|
||||
@each $breakpoint, $mediaquery in $breakpoints {
|
||||
@each $property-namespace, $property in $spacing-properties {
|
||||
@each $direction-namespace, $directions in $spacing-directions {
|
||||
@each $size-namespace, $size in $spacing-sizes {
|
||||
|
||||
// Prepend "-" to spacing sizes if not null
|
||||
$size-namespace: if($size-namespace != null, "-" + $size-namespace, $size-namespace);
|
||||
|
||||
// Base class
|
||||
$base-class: ".u-" + #{$property-namespace}#{$direction-namespace}#{$size-namespace};
|
||||
|
||||
// Spacing without media query
|
||||
@if $breakpoint == "xs" {
|
||||
#{$base-class} {
|
||||
@each $direction in $directions {
|
||||
#{$property}#{$direction}: $size !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spacing min-width breakpoints `@from-*`
|
||||
#{$base-class}\@from-#{$breakpoint} {
|
||||
@media #{mq-min($breakpoint)} {
|
||||
@each $direction in $directions {
|
||||
#{$property}#{$direction}: $size !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spacing max-width breakpoints @to-*`
|
||||
#{$base-class}\@to-#{$breakpoint} {
|
||||
@media #{mq-max($breakpoint)} {
|
||||
@each $direction in $directions {
|
||||
#{$property}#{$direction}: $size !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
// .is-hidden\@to-large {
|
||||
// @media (max-width: $to-large) {
|
||||
// .is-hidden\@to-lg {
|
||||
// @media (max-width: $to-lg) {
|
||||
// display: none;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// .is-hidden\@from-large {
|
||||
// @media (min-width: $from-large) {
|
||||
// .is-hidden\@from-lg {
|
||||
// @media (min-width: $from-lg) {
|
||||
// display: none;
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -21,8 +21,8 @@ $widths-fractions: 1 2 3 4 5 !default;
|
||||
|
||||
@include widths($widths-fractions);
|
||||
|
||||
.u-1\/2\@from-small {
|
||||
@media (min-width: $from-small) {
|
||||
width: span(1/2);
|
||||
.u-1\/2\@from-sm {
|
||||
@media (min-width: $from-sm) {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* @file Provides simple user configuration options.
|
||||
*/
|
||||
|
||||
import loconfig from '../../loconfig.json' assert { type: 'json' };
|
||||
import loconfig from '../../loconfig.json' with { type: 'json' };
|
||||
import { merge } from '../utils/index.js';
|
||||
|
||||
let usrconfig;
|
||||
|
||||
try {
|
||||
usrconfig = await import('../../loconfig.local.json', {
|
||||
assert: { type: 'json' },
|
||||
with: { type: 'json' },
|
||||
});
|
||||
usrconfig = usrconfig.default;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ export default async function concatFiles(globOptions = null, concatOptions = nu
|
||||
* Defaults to the outfile name.
|
||||
* @return {Promise}
|
||||
*/
|
||||
loconfig.tasks.concats.forEach(async ({
|
||||
loconfig.tasks.concats?.forEach(async ({
|
||||
includes,
|
||||
outfile,
|
||||
label = null
|
||||
|
||||
@@ -65,7 +65,7 @@ export default async function compileScripts(esBuildOptions = null) {
|
||||
* @throws {TypeError} If outdir and outfile are missing.
|
||||
* @return {Promise}
|
||||
*/
|
||||
loconfig.tasks.scripts.forEach(async ({
|
||||
loconfig.tasks.scripts?.forEach(async ({
|
||||
includes,
|
||||
outdir = '',
|
||||
outfile = '',
|
||||
|
||||
@@ -11,7 +11,7 @@ import { merge } from '../utils/index.js';
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { basename } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
import sass from 'sass';
|
||||
import * as sass from 'sass';
|
||||
import { PurgeCSS } from 'purgecss';
|
||||
|
||||
const sassRender = promisify(sass.render);
|
||||
@@ -60,10 +60,12 @@ export const productionPostCSSOptions = Object.assign({}, defaultPostCSSOptions
|
||||
export const developmentStylesArgs = [
|
||||
developmentSassOptions,
|
||||
developmentPostCSSOptions,
|
||||
false
|
||||
];
|
||||
export const productionStylesArgs = [
|
||||
productionSassOptions,
|
||||
productionPostCSSOptions,
|
||||
true
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -80,7 +82,7 @@ export const productionStylesArgs = [
|
||||
* If `false`, PostCSS processing will be ignored.
|
||||
* @return {Promise}
|
||||
*/
|
||||
export default async function compileStyles(sassOptions = null, postcssOptions = null) {
|
||||
export default async function compileStyles(sassOptions = null, postcssOptions = null, purge = true) {
|
||||
if (sassOptions == null) {
|
||||
sassOptions = productionSassOptions;
|
||||
} else if (
|
||||
@@ -111,7 +113,7 @@ export default async function compileStyles(sassOptions = null, postcssOptions =
|
||||
* Defaults to the outfile name.
|
||||
* @return {Promise}
|
||||
*/
|
||||
loconfig.tasks.styles.forEach(async ({
|
||||
loconfig.tasks.styles?.forEach(async ({
|
||||
infile,
|
||||
outfile,
|
||||
label = null
|
||||
@@ -160,7 +162,7 @@ export default async function compileStyles(sassOptions = null, postcssOptions =
|
||||
try {
|
||||
await writeFile(outfile, result.css).then(() => {
|
||||
// Purge CSS once file exists.
|
||||
if (outfile) {
|
||||
if (outfile && purge) {
|
||||
purgeUnusedCSS(outfile, `${label || `${filestem}.css`}`);
|
||||
}
|
||||
});
|
||||
@@ -216,21 +218,27 @@ export default async function compileStyles(sassOptions = null, postcssOptions =
|
||||
* @return {Promise}
|
||||
*/
|
||||
async function purgeUnusedCSS(outfile, label) {
|
||||
const contentFiles = loconfig.tasks.purgeCSS?.content;
|
||||
if (!Array.isArray(contentFiles) || !contentFiles.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
label = label ?? basename(outfile);
|
||||
|
||||
const timeLabel = `${label} purged in`;
|
||||
console.time(timeLabel);
|
||||
|
||||
const purgeCSSContentFiles = Array.from(loconfig.tasks.purgeCSS.content);
|
||||
|
||||
const purgeCSSResults = await (new PurgeCSS()).purge({
|
||||
content: purgeCSSContentFiles,
|
||||
content: contentFiles,
|
||||
css: [ outfile ],
|
||||
rejected: true,
|
||||
defaultExtractor: (content) => content.match(/[a-z0-9_\-\\\/\@]+/gi) || [],
|
||||
defaultExtractor: content => content.match(/[a-z0-9_\-\\\/\@]+/gi) || [],
|
||||
fontFaces: true,
|
||||
keyframes: true,
|
||||
safelist: {
|
||||
standard: [ /^((?!\bu-gc-).)*$/ ]
|
||||
}
|
||||
// Keep all except .u-gc-* | .u-margin-* | .u-padding-*
|
||||
standard: [ /^(?!.*\b(u-gc-|u-margin|u-padding)).*$/ ]
|
||||
},
|
||||
variables: true,
|
||||
})
|
||||
|
||||
for (let result of purgeCSSResults) {
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
import loconfig from '../helpers/config.js';
|
||||
import glob, { supportsGlob } from '../helpers/glob.js';
|
||||
import message from '../helpers/message.js';
|
||||
import notification from '../helpers/notification.js';
|
||||
import resolve from '../helpers/template.js';
|
||||
import { resolve as resolveTemplate } from '../helpers/template.js';
|
||||
import { merge } from '../utils/index.js';
|
||||
import { basename } from 'node:path';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
resolve,
|
||||
} from 'node:path';
|
||||
import commonPath from 'common-path';
|
||||
import mixer from 'svg-mixer';
|
||||
import slugify from 'url-slug';
|
||||
|
||||
const basePath = loconfig?.paths?.svgs?.src
|
||||
? resolve(loconfig.paths.svgs.src)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @const {object} defaultMixerOptions - The default shared Mixer options.
|
||||
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
|
||||
* @const {object} productionMixerOptions - The predefined Mixer options for production.
|
||||
* @const {object} defaultMixerOptions - The default shared Mixer options.
|
||||
*/
|
||||
export const defaultMixerOptions = {
|
||||
spriteConfig: {
|
||||
usages: false,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
|
||||
* @const {object} productionMixerOptions - The predefined Mixer options for production.
|
||||
*/
|
||||
export const developmentMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||
export const productionMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||
|
||||
@@ -57,7 +72,7 @@ export default async function compileSVGs(mixerOptions = null) {
|
||||
* Defaults to the outfile name.
|
||||
* @return {Promise}
|
||||
*/
|
||||
loconfig.tasks.svgs.forEach(async ({
|
||||
loconfig.tasks.svgs?.forEach(async ({
|
||||
includes,
|
||||
outfile,
|
||||
label = null
|
||||
@@ -74,10 +89,52 @@ export default async function compileSVGs(mixerOptions = null) {
|
||||
includes = [ includes ];
|
||||
}
|
||||
|
||||
includes = resolve(includes);
|
||||
outfile = resolve(outfile);
|
||||
includes = resolveTemplate(includes);
|
||||
outfile = resolveTemplate(outfile);
|
||||
|
||||
const result = await mixer(includes, mixerOptions);
|
||||
if (supportsGlob && basePath) {
|
||||
includes = await glob(includes);
|
||||
includes = [ ...new Set(includes) ];
|
||||
|
||||
const common = commonPath(includes);
|
||||
if (common.commonDir) {
|
||||
common.commonDir = resolve(common.commonDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the `<symbol id>` attribute and prefix any
|
||||
* SVG files in subdirectories according to the paths
|
||||
* common base path.
|
||||
*
|
||||
* Example for SVG source path `./assets/images/sprite`:
|
||||
*
|
||||
* | Path | ID |
|
||||
* | ------------------------------------ | --------- |
|
||||
* | `./assets/images/sprite/foo.svg` | `foo` |
|
||||
* | `./assets/images/sprite/baz/qux.svg` | `baz-qux` |
|
||||
*
|
||||
* @param {string} path - The absolute path to the file.
|
||||
* @param {string} [query=''] - A query string.
|
||||
* @return {string} The symbol ID.
|
||||
*/
|
||||
mixerOptions.generateSymbolId = (path, query = '') => {
|
||||
let dirName = dirname(path)
|
||||
.replace(common.commonDir ?? basePath, '')
|
||||
.replace(/^\/|\/$/, '')
|
||||
.replace('/', '-');
|
||||
if (dirName) {
|
||||
dirName += '-';
|
||||
}
|
||||
|
||||
const fileName = basename(path, extname(path));
|
||||
const decodedQuery = decodeURIComponent(decodeURIComponent(query));
|
||||
return `${dirName}${fileName}${slugify(decodedQuery)}`;
|
||||
};
|
||||
}
|
||||
|
||||
const result = await mixer(includes, {
|
||||
...mixerOptions,
|
||||
});
|
||||
|
||||
await result.write(outfile);
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
} from 'node:path';
|
||||
import readline from 'node:readline';
|
||||
|
||||
export const REGEXP_SEMVER = /^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
||||
|
||||
/**
|
||||
* @typedef {object} VersionOptions
|
||||
* @property {string|number|null} prettyPrint - A string or number to insert
|
||||
@@ -111,7 +113,7 @@ export default async function bumpVersions(versionOptions = null) {
|
||||
* @param {?string|number} [entry.pretty] - The white space to use to format the JSON file.
|
||||
* @return {Promise}
|
||||
*/
|
||||
loconfig.tasks.versions.forEach(({
|
||||
loconfig.tasks.versions?.forEach(({
|
||||
outfile,
|
||||
label = null,
|
||||
...options
|
||||
@@ -135,32 +137,64 @@ export default async function bumpVersions(versionOptions = null) {
|
||||
/**
|
||||
* Creates a formatted version number or string.
|
||||
*
|
||||
* @param {string} format - The version format.
|
||||
* @param {string} format - The version format.
|
||||
* @param {?string} [oldValue] - The old version value.
|
||||
* @return {string|number}
|
||||
* @throws TypeError If the format or value are invalid.
|
||||
*/
|
||||
function createVersionNumber(format) {
|
||||
function createVersionNumber(format, oldValue = null) {
|
||||
let [ type, modifier ] = format.split(':', 2);
|
||||
|
||||
switch (type) {
|
||||
case 'hex':
|
||||
case 'hexadecimal':
|
||||
modifier = Number.parseInt(modifier);
|
||||
try {
|
||||
modifier = Number.parseInt(modifier);
|
||||
|
||||
if (Number.isNaN(modifier)) {
|
||||
modifier = 6;
|
||||
if (Number.isNaN(modifier)) {
|
||||
modifier = 6;
|
||||
}
|
||||
|
||||
return randomBytes(modifier).toString('hex');
|
||||
} catch (err) {
|
||||
throw new TypeError(
|
||||
`${err.message} for \'format\' type "hexadecimal"`,
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
|
||||
return randomBytes(modifier).toString('hex');
|
||||
case 'inc':
|
||||
case 'increment':
|
||||
try {
|
||||
if (modifier === 'semver') {
|
||||
return incrementSemVer(oldValue, [ 'buildmetadata', 'patch' ]);
|
||||
}
|
||||
|
||||
return incrementNumber(oldValue, modifier);
|
||||
} catch (err) {
|
||||
throw new TypeError(
|
||||
`${err.message} for \'format\' type "increment"`,
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
|
||||
case 'regex':
|
||||
return new RegExp(modifier);
|
||||
case 'regexp':
|
||||
try {
|
||||
return new RegExp(modifier);
|
||||
} catch (err) {
|
||||
throw new TypeError(
|
||||
`${err.message} for \'format\' type "regexp"`,
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
|
||||
case 'timestamp':
|
||||
return Date.now().valueOf();
|
||||
}
|
||||
|
||||
throw new TypeError(
|
||||
'Expected \'format\' to be either "timestamp" or "hexadecimal"'
|
||||
'Expected \'format\' to be either "timestamp", "increment", or "hexadecimal"'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -221,9 +255,7 @@ async function handleBumpVersionInJson(outfile, label, options) {
|
||||
await mkdir(dirname(outfile), { recursive: true });
|
||||
}
|
||||
|
||||
const version = createVersionNumber(options.format);
|
||||
|
||||
json[options.key] = version;
|
||||
json[options.key] = createVersionNumber(options.format, json?.[options.key]);
|
||||
|
||||
return await writeFile(
|
||||
outfile,
|
||||
@@ -254,7 +286,7 @@ async function handleBumpVersionWithRegExp(outfile, label, options) {
|
||||
input: createReadStream(bckfile),
|
||||
});
|
||||
|
||||
const version = createVersionNumber(options.format);
|
||||
let newVersion = null;
|
||||
|
||||
const writeStream = createWriteStream(outfile, { encoding: 'utf8' });
|
||||
|
||||
@@ -262,12 +294,12 @@ async function handleBumpVersionWithRegExp(outfile, label, options) {
|
||||
const found = line.match(options.key);
|
||||
|
||||
if (found) {
|
||||
const groups = (found.groups ?? {});
|
||||
const replace = found[0].replace(
|
||||
(groups.build ?? groups.version ?? found[1] ?? found[0]),
|
||||
version
|
||||
);
|
||||
line = line.replace(found[0], replace);
|
||||
const groups = (found.groups ?? {});
|
||||
const oldVersion = (groups.build ?? groups.version ?? found[1] ?? found[0]);
|
||||
const newVersion = createVersionNumber(options.format, oldVersion);
|
||||
const replacement = found[0].replace(oldVersion, newVersion);
|
||||
|
||||
line = line.replace(found[0], replacement);
|
||||
}
|
||||
|
||||
writeStream.write(line + "\n");
|
||||
@@ -285,6 +317,88 @@ async function handleBumpVersionWithRegExp(outfile, label, options) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the given integer.
|
||||
*
|
||||
* @param {string|int} value - The number to increment.
|
||||
* @param {string|int} [increment=1] - The amount to increment by.
|
||||
* @return {int}
|
||||
* @throws TypeError If the version number is invalid.
|
||||
*/
|
||||
function incrementNumber(value, increment = 1) {
|
||||
const version = Number.parseInt(value);
|
||||
if (Number.isNaN(version)) {
|
||||
throw new TypeError(
|
||||
`Expected an integer version number, received [${value}]`
|
||||
);
|
||||
}
|
||||
|
||||
increment = Number.parseInt(increment);
|
||||
if (Number.isNaN(increment)) {
|
||||
throw new TypeError(
|
||||
'Expected an integer increment number'
|
||||
);
|
||||
}
|
||||
|
||||
return (version + increment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the given SemVer version number.
|
||||
*
|
||||
* @param {string} value - The version to mutate.
|
||||
* @param {string|string[]} [target] - The segment to increment, one of:
|
||||
* 'major', 'minor', 'patch', ~~'prerelease'~~, 'buildmetadata'.
|
||||
* @param {string|int} [increment=1] - The amount to increment by.
|
||||
* @return {string}
|
||||
* @throws TypeError If the version or target are invalid.
|
||||
*/
|
||||
function incrementSemVer(value, target = 'patch', increment = 1) {
|
||||
const found = value.match(REGEXP_SEMVER);
|
||||
if (!found) {
|
||||
throw new TypeError(
|
||||
`Expected a SemVer version number, received [${value}]`
|
||||
);
|
||||
}
|
||||
|
||||
if (Array.isArray(target)) {
|
||||
for (const group of target) {
|
||||
if (found.groups[group] != null) {
|
||||
target = group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!target || !found.groups[target]) {
|
||||
throw new TypeError(
|
||||
`Expected a supported SemVer segment, received [${target}]`
|
||||
);
|
||||
}
|
||||
|
||||
const segments = {
|
||||
'major': '',
|
||||
'minor': '.',
|
||||
'patch': '.',
|
||||
'prerelease': '-',
|
||||
'buildmetadata': '+',
|
||||
};
|
||||
|
||||
let replacement = '';
|
||||
|
||||
for (const [ segment, delimiter ] of Object.entries(segments)) {
|
||||
if (found.groups?.[segment] != null) {
|
||||
const newVersion = (segment === target)
|
||||
? incrementNumber(found.groups[segment], increment)
|
||||
: found.groups[segment];
|
||||
|
||||
replacement += `${delimiter}${newVersion}`;
|
||||
}
|
||||
}
|
||||
|
||||
return value.replace(found[0], replacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the version key.
|
||||
*
|
||||
|
||||
@@ -70,16 +70,18 @@ function configureServer(server, { paths, tasks }) {
|
||||
});
|
||||
|
||||
// Watch source concats
|
||||
server.watch(
|
||||
resolve(
|
||||
tasks.concats.reduce(
|
||||
(patterns, { includes }) => patterns.concat(includes),
|
||||
[]
|
||||
if (tasks.concats?.length) {
|
||||
server.watch(
|
||||
resolve(
|
||||
tasks.concats.reduce(
|
||||
(patterns, { includes }) => patterns.concat(includes),
|
||||
[]
|
||||
)
|
||||
)
|
||||
)
|
||||
).on('change', () => {
|
||||
concatFiles(...developmentConcatFilesArgs);
|
||||
});
|
||||
).on('change', () => {
|
||||
concatFiles(...developmentConcatFilesArgs);
|
||||
});
|
||||
}
|
||||
|
||||
// Watch source styles
|
||||
server.watch(
|
||||
|
||||
@@ -338,8 +338,8 @@ See [`svgs.js`](../build/tasks/svgs.js) for details.
|
||||
|
||||
A task to create and update values for use in versioning assets.
|
||||
|
||||
Can generate a hexadecimal value (using random bytes) or
|
||||
use the current timestamp.
|
||||
Can generate a hexadecimal value (using random bytes), use the current timestamp,
|
||||
or increment a number.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -355,6 +355,11 @@ Example:
|
||||
"format": "hex:8",
|
||||
"key": "hex",
|
||||
"outfile": "./assets.json"
|
||||
},
|
||||
{
|
||||
"format": "inc:semver",
|
||||
"key": "inc",
|
||||
"outfile": "./assets.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -363,7 +368,8 @@ Example:
|
||||
```json
|
||||
{
|
||||
"now": 1665071717350,
|
||||
"hex": "6ef54181c4ba"
|
||||
"hex": "6ef54181c4ba",
|
||||
"hex": "1.0.2"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ The first step is to set intial SCSS values in the following files :
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
&.-col-#{$base-column-nb}\@from-medium {
|
||||
@media (min-width: $from-medium) {
|
||||
&.-col-#{$base-column-nb}\@from-md {
|
||||
@media (min-width: $from-md) {
|
||||
grid-template-columns: repeat(#{$base-column-nb}, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ Learn about [namespacing](https://csswizardry.com/2015/03/more-transparent-ui-co
|
||||
}
|
||||
|
||||
.c-block_heading {
|
||||
@media (max-width: $to-medium) {
|
||||
@media (max-width: $to-md) {
|
||||
.c-block.-large & {
|
||||
margin-bottom: rem(40px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -181,10 +181,7 @@ detection and smooth scrolling with parallax.
|
||||
```js
|
||||
import LocomotiveScroll from 'locomotive-scroll';
|
||||
|
||||
this.scroll = new LocomotiveScroll({
|
||||
el: this.el,
|
||||
smooth: true
|
||||
});
|
||||
this.scroll = new LocomotiveScroll({})
|
||||
````
|
||||
|
||||
Learn more about [Locomotive Scroll][locomotive-scroll].
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"dest": "./www/assets/scripts"
|
||||
},
|
||||
"svgs": {
|
||||
"src": "./assets/images/sprite",
|
||||
"src": "./assets/svgs",
|
||||
"dest": "./www/assets/images"
|
||||
},
|
||||
"views": {
|
||||
|
||||
5174
package-lock.json
generated
5174
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
@@ -6,39 +6,44 @@
|
||||
"author": "Locomotive <info@locomotive.ca>",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=17.9",
|
||||
"npm": ">=8.0"
|
||||
"node": ">=20",
|
||||
"npm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --experimental-json-modules --no-warnings build/watch.js",
|
||||
"build": "node --experimental-json-modules --no-warnings build/build.js"
|
||||
"start": "node --no-warnings build/watch.js",
|
||||
"build": "node --no-warnings build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"locomotive-scroll": "^4.1.4",
|
||||
"focus-trap": "^7.5.4",
|
||||
"locomotive-scroll": "^5.0.0-beta.13",
|
||||
"modujs": "^1.4.2",
|
||||
"modularload": "^1.2.6",
|
||||
"normalize.css": "^8.0.1",
|
||||
"svg4everybody": "^2.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.13",
|
||||
"browser-sync": "^2.27.11",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"browser-sync": "^3.0.2",
|
||||
"common-path": "^1.0.1",
|
||||
"concat": "^1.0.3",
|
||||
"esbuild": "^0.17.6",
|
||||
"esbuild": "^0.21.5",
|
||||
"kleur": "^4.1.5",
|
||||
"node-notifier": "^10.0.1",
|
||||
"postcss": "^8.4.21",
|
||||
"purgecss": "^5.0.0",
|
||||
"sass": "^1.57.1",
|
||||
"svg-mixer": "~2.3.14",
|
||||
"postcss": "^8.4.38",
|
||||
"purgecss": "^6.0.0",
|
||||
"sass": "^1.77.6",
|
||||
"svg-mixer": "^2.3.14",
|
||||
"tiny-glob": "^0.2.9"
|
||||
},
|
||||
"overrides": {
|
||||
"browser-sync": {
|
||||
"ua-parser-js": "~1.0.33"
|
||||
"ua-parser-js": "^1.0.33"
|
||||
},
|
||||
"svg-mixer": {
|
||||
"postcss": "^8.4.20"
|
||||
"micromatch": "^4.0.4",
|
||||
"postcss": "^8.4.38"
|
||||
},
|
||||
"svg-mixer-utils": {
|
||||
"anymatch": "^3.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"critical.css"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18,8 +18,8 @@
|
||||
</head>
|
||||
<body data-module-load>
|
||||
<div data-load-container>
|
||||
<div class="o-scroll" data-module-scroll="main">
|
||||
<header data-scroll-section>
|
||||
<div data-module-scroll="main">
|
||||
<header>
|
||||
<a href="/"><h1>Locomotive Boilerplate</h1></a>
|
||||
<nav>
|
||||
<ul>
|
||||
@@ -30,7 +30,7 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main data-scroll-section>
|
||||
<main>
|
||||
<div class="o-container">
|
||||
<h1 class="c-heading -h1">Page</h1>
|
||||
|
||||
@@ -90,15 +90,12 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer data-scroll-section>
|
||||
<footer>
|
||||
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
|
||||
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="assets/scripts/vendors.js" defer></script>
|
||||
<script src="assets/scripts/app.js" defer></script>
|
||||
</body>
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
|
||||
<body data-module-load>
|
||||
<div data-load-container>
|
||||
<div class="o-scroll" data-module-scroll="main">
|
||||
<header data-scroll-section>
|
||||
<div data-module-scroll="main">
|
||||
<header>
|
||||
<a href="/">
|
||||
<h1>Locomotive Boilerplate</h1>
|
||||
</a>
|
||||
@@ -48,7 +48,7 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main data-scroll-section>
|
||||
<main>
|
||||
<div class="o-container">
|
||||
<h1 class="c-heading -h1">Hello</h1>
|
||||
|
||||
@@ -76,19 +76,13 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer data-scroll-section>
|
||||
<footer>
|
||||
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
|
||||
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"
|
||||
crossorigin="anonymous"></script>
|
||||
<script nomodule
|
||||
src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="assets/scripts/vendors.js" defer></script>
|
||||
<script src="assets/scripts/app.js" defer></script>
|
||||
</body>
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
</head>
|
||||
<body data-module-load>
|
||||
<div data-load-container>
|
||||
<div class="o-scroll" data-module-scroll="main">
|
||||
<header data-scroll-section>
|
||||
<div data-module-scroll="main">
|
||||
<header>
|
||||
<a href="/"><h1>Locomotive Boilerplate</h1></a>
|
||||
<nav>
|
||||
<ul>
|
||||
@@ -30,7 +30,7 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main data-scroll-section>
|
||||
<main>
|
||||
<div class="o-container">
|
||||
<h1 class="c-heading -h1">Images</h1>
|
||||
|
||||
@@ -116,15 +116,12 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer data-scroll-section>
|
||||
<footer>
|
||||
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
|
||||
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="assets/scripts/vendors.js" defer></script>
|
||||
<script src="assets/scripts/app.js" defer></script>
|
||||
</body>
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
<body data-module-load>
|
||||
|
||||
<div data-load-container>
|
||||
<div class="o-scroll" data-module-scroll="main">
|
||||
<header data-scroll-section>
|
||||
<div data-module-scroll="main">
|
||||
<header>
|
||||
<a href="/">
|
||||
<h1>Locomotive Boilerplate</h1>
|
||||
</a>
|
||||
@@ -56,25 +56,32 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main data-module-example data-scroll-section>
|
||||
<main data-module-example>
|
||||
<div class="o-container">
|
||||
<h1 class="c-heading -h1">Hello</h1>
|
||||
<button data-modal-toggler>Open modal</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer data-scroll-section>
|
||||
<footer>
|
||||
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
|
||||
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
|
||||
</footer>
|
||||
|
||||
<div class="c-modal" data-module-modal>
|
||||
<div class="c-modal_inner" data-modal-target>
|
||||
<button data-modal-toggler>Close</button>
|
||||
<h2>Modal</h2>
|
||||
<p>Content</p>
|
||||
<form action="">
|
||||
<input type="text">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"
|
||||
crossorigin="anonymous"></script>
|
||||
<script nomodule
|
||||
src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="assets/scripts/vendors.js" defer></script>
|
||||
<script src="assets/scripts/app.js" defer></script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user