1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00

87 Commits

Author SHA1 Message Date
Deven Caron
1a8c502ac2 Merge branch 'master' into mcaskill/node-20-npm-10 2024-07-04 12:12:29 -05:00
Chauncey McAskill
f8a46043a6 Remove babel-polyfill (#178)
All features are suported by modern browsers.

Can be restored if ever needed to support older browsers.
2024-07-04 13:12:18 -04:00
Chauncey McAskill
3a9038c832 Update gitignore of assets to use wildcards 2024-06-27 15:01:00 -04:00
Chauncey McAskill
9e003ae89c Update NPM constraint and dependencies
Requied:
- NPM v8 → v10

Changed:
- Fixed Node/NPM requirements in README.
- Fixed dependency vulenerabilities.
- Updated dependencies.
- Removed obsolete Node flag `--experimental-json-modules`.
- Replaced obsolete import `assert` keyword with `with`.
2024-06-27 15:00:40 -04:00
Chauncey McAskill
25823286d5 Remove polyfill.io
See: https://sansec.io/research/polyfill-supply-chain-attack
2024-06-25 18:19:00 -04:00
Chauncey McAskill
605f30c948 Fix svg-mixer support for sub-directories
By default, svg-mixer only uses the SVG's file name as its ID. If any SVG files are stored in sub-directories, that information is ignored in the assembled spritesheet. This is problematic since context is lost (the sub-directory's name) and risks duplicate symbol IDs.

This commit introduces a new NPM dependency, `common-path` to resolve the longest common base path, and uses a dependency of `svg-mixer` named `url-slug` in order to prefix the directory name.
2024-04-03 09:29:52 -04:00
Lucas Bigot
27a41aba66 Add default text dedicated file (#173) 2024-04-03 08:29:24 -04:00
Lucas Bigot
353a38915d Update default headings (#172)
* Move font-size css var into dedicated heading file + Add default mixins

* Rename responsive-type for a more generic name
2024-04-03 08:28:57 -04:00
Lucas Bigot
6d37049989 Fix resize event debounce method + Clean up and re-organize app file 2024-03-26 18:30:36 -04:00
Lucas Bigot
bc3fd3a492 Fix grid-space sass function using calculated vw value 2024-03-26 18:29:48 -04:00
Lucas Bigot
45d8be5525 Rename breakpoints by shortnames (#171)
* Rename breakpoints by shortnames

* Replace `tiny` breakpoint for `xs` in spacing loop

* Add 2xs, 4xl and 5xl breakpoints
2024-03-26 16:50:16 -04:00
Deven Caron
ea8f98a52d Add assets.json and empty directories for scripts and styles 2024-03-26 16:29:33 -04:00
Deven Caron
56bbd9e3c5 Delete assets.json file 2024-03-26 16:29:12 -04:00
Deven Caron
dcb7e91b91 Update node version for vercel 2024-03-26 16:20:50 -04:00
Deven Caron
2b1eb8e0dd Add new files and update .gitignore 2024-03-26 15:44:21 -04:00
Deven Caron
f4afd9c6b2 Delete compiled assets 2024-03-26 15:42:20 -04:00
Lucas Bigot
7578397a8e Merge pull request #170 from locomotivemtl/feature/config-speed
Rename `timing` by `speed`
2024-03-26 15:10:10 -04:00
Lucas Bigot
27effb470d Merge branch 'master' into feature/config-speed 2024-03-26 15:06:16 -04:00
Lucas Bigot
7a91cbce61 Merge pull request #165 from locomotivemtl/feature/css-reset
Modernize css normalize
2024-03-26 15:03:15 -04:00
Lucas Bigot
65a265c0ea Merge branch 'master' into feature/css-reset 2024-03-26 15:02:21 -04:00
Lucas Bigot
afb3a4aa6a Merge pull request #161 from locomotivemtl/feature/svgs-folder
Add dedicated SVG sprite folder
2024-03-26 14:56:03 -04:00
Lucas Bigot
40521c3f2b Merge pull request #169 from locomotivemtl/feature/config-spacing
Rework spacing css config
2024-03-26 14:47:00 -04:00
Lucas Bigot
2d395cf73a Rename timing file and sass function for speed 2024-03-26 14:37:11 -04:00
Lucas Bigot
81d47b88b8 Rename spacer by spacings 2024-03-26 14:06:25 -04:00
Lucas Bigot
c16407c8c1 Add clamp-with-max & size-clamp sass functions 2024-03-26 11:41:23 -04:00
Lucas Bigot
522c9c0bcb Replace vh based spacing values 2024-03-26 11:16:54 -04:00
Chauncey McAskill
ddd12ffc38 Fix inconsistent argument name in grid-space() function in Sass 2024-01-29 15:19:09 -05:00
Chauncey McAskill
9e6d7ae182 Replace deprecated divisions in Sass 2024-01-29 15:17:50 -05:00
Chauncey McAskill
d5bff3ab50 Remove obsolete span() function in Sass 2024-01-29 15:06:58 -05:00
Chauncey McAskill
962ba66b96 Update NPM dependencies
Updated:
- autoprefixer v10.4.13 → v10.4.17
- esbuild v0.17.6 → →0.20.0
- locomotive-scroll v5.0.0-beta.9 → v5.0.0-beta.11
- sass v1.69.5 → v1.70.0
2024-01-29 12:30:58 -05:00
Chauncey McAskill
5b6bca6ce3 Replace deprecated division in '_widths.scss' 2024-01-29 11:37:39 -05:00
Chauncey McAskill
4ae90a5821 Annotate Sass modules section of 'main.scss' 2024-01-29 11:37:18 -05:00
Lucas
31061daf60 Merge pull request #166 from locomotivemtl/feature/viewport-units
Viewport sizes fallbacks
2024-01-22 16:31:21 +01:00
Lucas
ceefeb554e Merge branch 'master' into feature/viewport-units 2024-01-22 16:31:12 +01:00
Lucas Vallenet
276b5eebc0 Update asset version 2024-01-22 16:30:40 +01:00
Jérémy Minié
a37c5b047a Fix PurgeCSS safelist regex 2024-01-16 15:07:09 -05:00
Lucas Vallenet
0af2be4599 Update reset 2024-01-12 12:07:38 +01:00
Lucas Vallenet
98ba8c4972 Update normalize comment 2024-01-12 11:28:42 +01:00
Lucas Vallenet
3f7077b488 Add vh/svh/dvh/lvh fallbacks 2024-01-11 11:45:46 +01:00
Lucas Vallenet
a674a16c4b Remove body margins 2024-01-11 11:27:44 +01:00
Lucas Vallenet
dd2c783938 Modernize css normalize 2024-01-11 11:10:38 +01:00
Deven Caron
61b6222525 Merge pull request #163 from locomotivemtl/chore/update-node-version
Update node version & bump npm packages version
2024-01-05 15:24:22 -05:00
Deven Caron
5acd27d1b0 Compile assets 2024-01-05 09:06:33 -05:00
Deven Caron
9a5a91b221 Update Node version and npm dependencies 2024-01-05 09:06:24 -05:00
Lucas Vallenet
7021666c46 Add dedicated svg folder 2023-12-11 11:43:16 +01:00
Lucas
43c86c3b50 Merge pull request #160 from butterfail/greg/invlerp
Fix invlerp method
2023-12-11 11:10:26 +01:00
Lucas Vallenet
0b4c82ceda Add scss-config dedicated files 2023-12-11 11:02:54 +01:00
Lucas Vallenet
b72fdabe23 Add default z-index value 2023-12-11 11:00:21 +01:00
Lucas Vallenet
f1ebc27a69 Add aspect-ratio scss mixin 2023-12-11 10:58:24 +01:00
Grégoire Ciles
f2898c8c8e Fix invlerp method 2023-11-29 12:27:01 +01:00
Lucas Vallenet
12d65db09f Reverse aspect-ratio condition 2023-11-29 11:10:32 +01:00
Lucas Vallenet
657fd41f70 Update config functions: alpha parameter for colors, multiplier parameter for spacers 2023-11-21 10:03:17 +01:00
Deven Caron
65c486b910 Update locomotive-scroll to v5.0.0-beta.9 2023-11-15 13:55:25 -05:00
Deven Caron
3d0e4d26a2 Update sass version to 1.69.5 2023-11-15 13:53:04 -05:00
Chauncey McAskill
df1a3a6f3c Update sass import in styles.js 2023-09-08 17:11:27 -04:00
Lucas Vallenet
7f1b6dad2e Fix device detection on config.js 2023-09-05 09:40:19 +02:00
Lucas Vallenet
63e46cde26 Comment updates 2023-09-05 09:34:24 +02:00
Lucas Vallenet
6564fb330a Update eases names to match gsap / Add default vars for z-indexes, timings and eases 2023-09-05 09:31:56 +02:00
Chauncey McAskill
b5753148f1 Improve asset versioning task
Add support for "increment" format to increment an integer version number with support for "increment:semver" to increment the build or patch of a SemVer version number.

Usage:

```json
"versions": [
    {
        "format": "increment",
        "key": "version",
        "outfile": "assets.json"
    }
]
```

```jsonc
{
    "version": 16 // → 17
}
```

```json
"versions": [
    {
        "format": "increment:semver",
        "key": "version",
        "outfile": "assets.json"
    }
]
```

```jsonc
{
    "version": "1.0.0" // → 1.0.1
}
```

```jsonc
{
    "version": "1.0.0+1" // → 1.0.0+2
}
```
2023-08-14 16:56:01 -04:00
Lucas Vallenet
7b415af8c2 Fix comments 2023-08-14 10:56:14 +02:00
Lucas Vallenet
dc0bc2042c Create aspect-ratio SCSS mixin polyfill 2023-08-14 10:40:24 +02:00
Chauncey McAskill
e9dbb03207 Fix support for undefined tasks in watch.js
Amends 596ff7a8ee
2023-08-10 11:01:50 -04:00
Chauncey McAskill
95caf9ebb5 Replace window.onload with window.addEventListener()
Since the `window` can only ever have one `onload` value, if ever a third-party script overwrites this property, the application risks never initializing.

By using `addEventListener('load',…)`, the application's bootstrapping logic is queued and is more likely to be initialized.
2023-08-08 15:34:01 -04:00
Chauncey McAskill
596ff7a8ee Fix support for undefined tasks
For example, if there are no `concats` tasks defined in 'loconfig.json', avoid throwing an error.
2023-08-08 14:49:47 -04:00
Deven Caron
70b36052e6 Merge pull request #154 from locomotivemtl/dependabot/npm_and_yarn/socket.io-parser-4.2.4
Bump socket.io-parser from 4.2.2 to 4.2.4
2023-07-31 10:56:07 -04:00
dependabot[bot]
f1e2e2270f Bump socket.io-parser from 4.2.2 to 4.2.4
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.2...4.2.4)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-31 14:30:51 +00:00
Deven Caron
13735c64f9 Merge pull request #153 from locomotivemtl/feature/update-scroll
Update locomotive scroll v5
2023-07-31 10:30:17 -04:00
Deven Caron
659ef3767b Fix img scroll lazyload $el 2023-07-31 10:29:02 -04:00
Deven Caron
e162af17dd Update LS styles vendor import 2023-07-31 10:28:35 -04:00
Lucas Vallenet
93559a0c84 Add purgeCSS for .u-padding and .u-margin classes | Disable purge on development 2023-07-10 15:40:56 +02:00
Lucas Vallenet
c1bcf7fb0d Fix spacing loop 2023-06-16 10:13:10 +02:00
Lucas Vallenet
d0fcfaac86 Add config.spacers and modify spacing function to add breakpoint based spacers. 2023-06-15 17:28:29 +02:00
Lucas Vallenet
4a958c5fb5 Update grid-column loop with config.breakpoints list and media query functions. Add @to-* modifier 2023-06-15 17:28:06 +02:00
Lucas Vallenet
5e7e92c7f5 Rename z-indexes config / Update easing comment / Move font-face include to document.scss 2023-06-12 16:50:40 +02:00
Lucas Vallenet
380fbd40c3 Update comments 2023-06-12 16:21:57 +02:00
Lucas Vallenet
e16ba2ca16 Import locomotive scroll CSS / Removed unused styles (scroll, scorllbar) / Update DOM Markup / Update doc 2023-06-12 09:36:14 +02:00
Lucas Vallenet
43a5eb1ad3 Update locomotive scroll v5 2023-06-08 15:44:35 +02:00
Lucas Vallenet
99801a2d8b Add dedicated scss config files 2023-06-08 11:48:00 +02:00
Lucas Vallenet
217a1adba7 Merge scss functions / Fix strip-unit 2023-06-08 10:57:59 +02:00
Lucas Vallenet
a11e98e31e Fix js FONT var error 2023-05-22 09:48:34 +02:00
Deven Caron
6ef90dbe11 Merge pull request #149 from locomotivemtl/dependabot/npm_and_yarn/engine.io-6.4.2
Bump engine.io from 6.4.0 to 6.4.2
2023-05-12 10:41:24 -04:00
Deven Caron
6726d665f2 Merge pull request #148 from locomotivemtl/feature/scss-colors
Color as list
2023-05-12 10:39:38 -04:00
dependabot[bot]
dcec21adf4 Bump engine.io from 6.4.0 to 6.4.2
Bumps [engine.io](https://github.com/socketio/engine.io) from 6.4.0 to 6.4.2.
- [Release notes](https://github.com/socketio/engine.io/releases)
- [Changelog](https://github.com/socketio/engine.io/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/engine.io/compare/6.4.0...6.4.2)

---
updated-dependencies:
- dependency-name: engine.io
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-04 01:31:42 +00:00
Lucas Vallenet
be71474633 Remove duplicate / Update functions descriptions 2023-01-05 09:58:01 +01:00
Lucas Vallenet
810df92a61 Fix functions.scss error 2023-01-04 14:41:25 +01:00
Lucas Vallenet
bf28fe21a3 Strip breakpoint unit from responsive-type 2023-01-04 11:02:32 +01:00
Lucas Vallenet
7b3cefd8df Add usefull scss functions 2023-01-04 10:50:36 +01:00
62 changed files with 2585 additions and 4585 deletions

9
.gitignore vendored
View File

@@ -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

2
.nvmrc
View File

@@ -1 +1 @@
v17.9
v20

View File

@@ -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.

View File

@@ -1,3 +0,0 @@
{
"version": 1683902331941
}

View File

@@ -1,65 +1,137 @@
import modular from 'modujs';
import * as modules from './modules';
import globals from './globals';
import { debounce } from './utils/tickers'
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');
}
};
function init() {
globals();
app.init(app);
$html.classList.add(CSS_CLASS.LOADED);
$html.classList.add(CSS_CLASS.READY);
$html.classList.remove(CSS_CLASS.LOADING);
// Bind window resize event with default vars
const resizeEndEvent = new CustomEvent(CUSTOM_EVENT.RESIZE_END)
window.addEventListener('resize', () => {
$html.style.setProperty('--vw', `${document.documentElement.clientWidth * 0.01}px`)
debounce(() => {
window.dispatchEvent(resizeEndEvent)
}, 200, false)
})
/**
* Eagerly load the following fonts.
*/
if (isFontLoadingAPIAvailable) {
loadFonts(FONT.EAGER_FONTS, ENV.IS_DEV).then((eagerFonts) => {
$html.classList.add(CSS_CLASS.FONTS_LOADED);
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/*, 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()
}
});
}
}
});

View File

@@ -9,7 +9,7 @@
*/
const NODE_ENV = process.env.NODE_ENV
const IS_DESKTOP = typeof window.orientation === 'undefined'
const IS_MOBILE = window.matchMedia('(any-pointer:coarse)').matches
// Main environment variables
const ENV = Object.freeze({
@@ -19,8 +19,17 @@ const ENV = Object.freeze({
IS_DEV: NODE_ENV === 'development',
// Device
IS_DESKTOP,
IS_MOBILE: !IS_DESKTOP,
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

View File

@@ -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();
}

View File

@@ -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))
/**

View File

@@ -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;
}
}

View File

@@ -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 {

View 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;
}
}

View File

@@ -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,56 +20,32 @@ 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 {

View 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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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,
// lets 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]
}

View File

@@ -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,15 +50,11 @@
// @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";
@@ -69,5 +67,5 @@
// @import "utilities/align";
// @import "utilities/helpers";
// @import "utilities/states";
// @import "utilities/spacing";
@import "utilities/spacing";
// @import "utilities/print";

View File

@@ -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);
}
}

View File

@@ -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 & {

View File

@@ -1,7 +0,0 @@
// ==========================================================================
// Objects / Scroll
// ==========================================================================
.o-scroll {
min-height: 100vh;
}

View 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;

View File

@@ -3,7 +3,7 @@
// ==========================================================================
// Palette
// =============================================================================
// ==========================================================================
$colors: (
primary: #3297FD,
@@ -11,9 +11,37 @@ $colors: (
darkest: #000000,
);
// 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: color(primary);

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -11,43 +11,11 @@ $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);
@@ -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
);

View 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});
}

View 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);
}

View File

@@ -7,26 +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)};
// // Colors
// @each $color, $value in $colors {
// --color-#{"" + $color}: #{$value};
// }
@media (min-width: $from-small) {
@media (min-width: $from-sm) {
--grid-columns: #{$base-column-nb};
--grid-gutter: #{rem(16px)};
--grid-margin: #{rem(20px)};

View 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;
}

View File

@@ -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
@@ -140,21 +104,111 @@
$context: 'frontend' !default;
// Returns color code.
// Returns calculation of a percentage of the grid cell width
// with optional inset of grid gutter.
//
// ```scss
// .c-box {
// width: color(primary);
// width: grid-space(6/12);
// margin-left: grid-space(1/12, 1);
// }
// ```
//
// @param {string} $key - The color key in $colors.
// @return {color}
@function color($key) {
@if not map-has-key($colors, $key) {
@error "Unknown '#{$key}' in $colors.";
}
@return map-get($colors, $key);
// @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);
}

View File

@@ -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 math.div($number, ($number * 0 + 1));
@return $value;
}
// Returns the square root of the given number.

View File

@@ -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;
}
}
}
}

View File

@@ -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};
}
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -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;
// }
// }

View File

@@ -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%;
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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 = '',

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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.
*

View File

@@ -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(

View File

@@ -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"
}
```

View File

@@ -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);
}
}

View File

@@ -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].

View File

@@ -15,7 +15,7 @@
"dest": "./www/assets/scripts"
},
"svgs": {
"src": "./assets/images/sprite",
"src": "./assets/svgs",
"dest": "./www/assets/images"
},
"views": {

5144
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,39 +6,43 @@
"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",
"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

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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,19 @@
</nav>
</header>
<main data-module-example data-scroll-section>
<main data-module-example>
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
</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>