diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 4713612..0c79b6f 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 828feec..89c5fd9 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,54 +2,43 @@ - - - - - - - - - - - - + + + + + + + - - - - - + + - - - - - + + + - - - - + + - - - - + + + + + @@ -82,7 +71,7 @@ - + @@ -156,7 +145,10 @@ - + + + + diff --git a/README.md b/README.md index 6228e35..f74053b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # Timeline -[Click for live version](https://schmelczer.dev) - An easily configurable portfolio. +> [Click for live version](https://schmelczer.dev) + +## Configuration +- The actual content is in [portfolio.ts](src/portfolio.ts). +- The assets referenced by this file should be located in [src/static](src/static). + + + diff --git a/package.json b/package.json index e876267..a94840e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "html-webpack-plugin": "^3.2.0", "image-webpack-loader": "^6.0.0", "mini-css-extract-plugin": "^0.9.0", - "node-sass": "^4.13.0", + "sass": "^1.24.2", "optimize-css-assets-webpack-plugin": "^5.0.3", "postcss-loader": "^3.0.0", "prettier": "^1.19.1", @@ -56,5 +56,8 @@ "webpack": "^4.41.4", "webpack-cli": "^3.3.10", "webpack-dev-server": "^3.10.1" + }, + "dependencies": { + "sass": "latest" } } diff --git a/src/framework/container-page.ts b/src/framework/container-page.ts index fb1e1d5..7521a04 100644 --- a/src/framework/container-page.ts +++ b/src/framework/container-page.ts @@ -3,16 +3,18 @@ import { PageEventType } from './page-event'; export class ContainerPage extends PageElement { public constructor(rootElement: HTMLElement, children: Array) { - children.forEach(e => rootElement.appendChild(e.element)); + children + .filter(e => e.element) + .forEach(e => rootElement.appendChild(e.element)); super(rootElement, children); } public setAsMain() { - this.broadcastEvent({ type: PageEventType.onLoad }, this); - this.broadcastEvent( { type: PageEventType.eventBroadcasterChanged, data: this }, this ); + + this.broadcastEvent({ type: PageEventType.onLoad }, this); } } diff --git a/src/framework/helper/dark-mode.ts b/src/framework/helper/dark-mode.ts new file mode 100644 index 0000000..5750422 --- /dev/null +++ b/src/framework/helper/dark-mode.ts @@ -0,0 +1,9 @@ +export const isSystemLevelDarkModeEnabled = (): boolean => + window.matchMedia && + window.matchMedia('(prefers-color-scheme: dark)').matches; + +export const turnOnDarkMode = () => + document.body.parentElement.setAttribute('theme', 'dark'); + +export const turnOnLightMode = () => + document.body.parentElement.setAttribute('theme', 'light'); diff --git a/src/framework/helper/mix-colors.ts b/src/framework/helper/mix-colors.ts index 81ceb6d..2f89fd1 100644 --- a/src/framework/helper/mix-colors.ts +++ b/src/framework/helper/mix-colors.ts @@ -20,16 +20,12 @@ export const mixColors = ( const hexToRGB = (hex: hex): rgb => { const [r1, r2, g1, g2, b1, b2] = normalizeHex(hex); - return [ - Number.parseInt(r1 + r2, 16), - Number.parseInt(g1 + g2, 16), - Number.parseInt(b1 + b2, 16), - ]; + return [parseInt(r1 + r2, 16), parseInt(g1 + g2, 16), parseInt(b1 + b2, 16)]; }; const normalizeHex = (hex: hex): hex => { hex = hex.trim(); - if (hex.startsWith('#')) { + if (hex[0] === '#') { hex = hex.substr(1); } return hex; @@ -38,4 +34,4 @@ const normalizeHex = (hex: hex): hex => { const mix = (a: number, b: number, q: number): number => a * q + b * (1 - q); const rgbToHex = (rgb: rgb): hex => - '#' + rgb.map(n => Math.round(n).toString(16)).join(''); + '#' + rgb.map(n => (n < 16 ? '0' : '') + Math.round(n).toString(16)).join(''); diff --git a/src/framework/helper/random.ts b/src/framework/helper/random.ts index 68a2c05..aad6370 100644 --- a/src/framework/helper/random.ts +++ b/src/framework/helper/random.ts @@ -1,5 +1,9 @@ +import { addImul } from '../polyfills'; + export class Random { - public constructor(private seed: number) {} + public constructor(private seed: number) { + addImul(); + } public get next(): number { // result is in [0, 1) diff --git a/src/framework/page-element.ts b/src/framework/page-element.ts index d06e3fa..e18c9d9 100644 --- a/src/framework/page-element.ts +++ b/src/framework/page-element.ts @@ -5,7 +5,7 @@ export abstract class PageElement implements EventBroadcaster { protected eventBroadcaster: EventBroadcaster; protected constructor( - private readonly rootElement: HTMLElement, + private readonly rootElement?: HTMLElement, private readonly children: Array = [] ) {} diff --git a/src/framework/page-event.ts b/src/framework/page-event.ts index 0a682eb..71447b0 100644 --- a/src/framework/page-event.ts +++ b/src/framework/page-event.ts @@ -6,5 +6,6 @@ export class PageEvent { export enum PageEventType { onLoad, onBodyDimensionsChanged, - eventBroadcasterChanged + eventBroadcasterChanged, + pageThemeChanged, } diff --git a/src/framework/polyfills.ts b/src/framework/polyfills.ts new file mode 100644 index 0000000..bc31a07 --- /dev/null +++ b/src/framework/polyfills.ts @@ -0,0 +1,17 @@ +export const addImul = () => { + if (!Math.imul) + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + Math.imul = function(opA, opB) { + opB |= 0; // ensure that opB is an integer. opA will automatically be coerced. + // floating points give us 53 bits of precision to work with plus 1 sign bit + // automatically handled for our convenience: + // 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001 + // 0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ + let result = (opA & 0x003fffff) * opB; + // 2. We can remove an integer coercion from the statement above because: + // 0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001 + // 0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ + if (opA & 0xffc00000 /*!== 0*/) result += ((opA & 0xffc00000) * opB) | 0; + return result | 0; + }; +}; diff --git a/src/framework/primitives/primitives.scss b/src/framework/primitives/primitives.scss index 705bd52..38194c6 100644 --- a/src/framework/primitives/primitives.scss +++ b/src/framework/primitives/primitives.scss @@ -1,25 +1,27 @@ @import '../../style/vars'; @import '../../style/mixins'; -.figure-container { - font-size: 0; - box-shadow: inset $shadow1, inset $shadow2; - pointer-events: none; - cursor: pointer; +@include responsive() using ($vars) { + .figure-container { + font-size: 0; + box-shadow: inset map_get($vars, $shadow1), inset map_get($vars, $shadow2); + pointer-events: none; + cursor: pointer; - * { - pointer-events: all; - position: relative; - z-index: -2; + * { + pointer-events: all; + position: relative; + z-index: -2; + } + } + + .primitive-text, + .primitive-anchor, + .figure-container { + margin-top: map_get($vars, $line-height); + } + + .primitive-text { + text-align: left; } } - -.primitive-text, -.primitive-anchor, -.figure-container { - margin-top: $line-height; -} - -.primitive-text { - text-align: left; -} diff --git a/src/index.html b/src/index.html index d8367a6..2e1f704 100644 --- a/src/index.html +++ b/src/index.html @@ -17,8 +17,8 @@ Portfolio - AndrĂ¡s Schmelczer - + Javascript is required for this website. - +