diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/autoComplete.ts | 115 | ||||
-rw-r--r-- | src/lib/base.ts | 32 | ||||
-rw-r--r-- | src/lib/button.ts | 29 | ||||
-rw-r--r-- | src/lib/color.ts | 36 | ||||
-rw-r--r-- | src/lib/contextMenu.ts | 35 | ||||
-rw-r--r-- | src/lib/dom.ts | 6 | ||||
-rw-r--r-- | src/lib/form.ts | 54 | ||||
-rw-r--r-- | src/lib/h.ts | 31 | ||||
-rw-r--r-- | src/lib/icons.ts | 66 | ||||
-rw-r--r-- | src/lib/layout.ts | 15 | ||||
-rw-r--r-- | src/lib/modal.ts | 28 |
11 files changed, 0 insertions, 447 deletions
diff --git a/src/lib/autoComplete.ts b/src/lib/autoComplete.ts deleted file mode 100644 index b0a79eb..0000000 --- a/src/lib/autoComplete.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { h, Children, concatClassName } from 'lib/h' -import * as Button from 'lib/button' - -export function create( - attrs: object, - id: string, - keys: string[], - renderEntry: (entry: string) => Element, - onInput: (value: string) => void -): Element { - const completion = h('div', {}) - - const updateCompletion = (target: EventTarget, value: string) => { - const entries = search(value, keys) - mountOn( - completion, - renderCompletion( - renderEntry, - selected => { - (target as HTMLInputElement).value = selected - completion.remove - removeChildren(completion) - onInput(selected) - }, - entries - ) - ) - } - - const input = h('input', - concatClassName( - { ...attrs, - id, - autocomplete: 'off', - onfocus: (e: Event) => { - if (e.target !== null) { - const target = e.target as HTMLInputElement - updateCompletion(target, target.value) - } - }, - oninput: (e: Event) => { - if (e.target !== null) { - const target = e.target as HTMLInputElement - updateCompletion(target, target.value) - onInput(target.value) - } - } - }, - 'g-AutoComplete__Input' - ) - ) as HTMLInputElement - - input.addEventListener('blur', (e: MouseEvent) => { - if (e.relatedTarget === null) { - removeChildren(completion) - } - }) - - return h('div', - { className: 'g-AutoComplete' }, - input, - completion, - Button.raw( - { className: 'g-AutoComplete__Clear', - type: 'button', - onclick: () => { - onInput('') - input.value = '' - input.focus() - } - }, - 'x' - ) - ) -} - -function renderCompletion( - renderEntry: (entry: string) => Element, - onSelect: (entry: string) => void, - entries: string[] -): Element { - return h('div', - { className: 'g-AutoComplete__Completion' }, - ...entries.map(c => - Button.raw( - { className: 'g-AutoComplete__Entry', - type: 'button', - onclick: (e: Event) => { - e.stopPropagation() - e.preventDefault() - onSelect(c) - } - }, - renderEntry(c) - ) - ) - ) -} - -function search(s: string, xs: string[]): string[] { - return xs.filter(x => x.includes(s)) -} - -function mountOn(base: Element, ...children: Element[]) { - removeChildren(base) - children.forEach(child => base.appendChild(child)) -} - -function removeChildren(base: Element) { - const firstChild = base.firstChild - if (firstChild !== null) { - base.removeChild(firstChild) - removeChildren(base) - } -} diff --git a/src/lib/base.ts b/src/lib/base.ts deleted file mode 100644 index 59c91cc..0000000 --- a/src/lib/base.ts +++ /dev/null @@ -1,32 +0,0 @@ -export const b2: string[] = - '01'.split('') - -export const b16: string[] = - '0123456789abcdef'.split('') - -export const b62: string[] = - '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('') - -export function encode(n: bigint, charset: string[]): string { - const base = BigInt(charset.length) - - if (n == BigInt(0)) { - return '0' - } else { - var xs = [] - while (n > BigInt(0)) { - xs.push(charset[Number(n % base)]) - n = n / base - } - return xs.reverse().join('') - } -} - -export function decode(xs: string, charset: string[]): bigint { - const base = BigInt(charset.length) - - return xs - .split('') - .reverse() - .reduce((acc, x, i) => acc + (BigInt(charset.indexOf(x)) * (base ** BigInt(i))), BigInt(0)) -} diff --git a/src/lib/button.ts b/src/lib/button.ts deleted file mode 100644 index 794df35..0000000 --- a/src/lib/button.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { h, Children, concatClassName } from 'lib/h' - -export function raw(attrs: object, ...children: Children): Element { - return h('button', - concatClassName(attrs, 'g-Button__Raw'), - ...children - ) -} - -export function text(attrs: object, ...children: Children): Element { - return h('button', - concatClassName(attrs, 'g-Button__Text'), - ...children - ) -} - -export function action(attrs: object, ...children: Children): Element { - return h('button', - concatClassName(attrs, 'g-Button__Action'), - ...children - ) -} - -export function cancel(attrs: object, ...children: Children): Element { - return h('button', - concatClassName(attrs, 'g-Button__Cancel'), - ...children - ) -} diff --git a/src/lib/color.ts b/src/lib/color.ts deleted file mode 100644 index 59b320d..0000000 --- a/src/lib/color.ts +++ /dev/null @@ -1,36 +0,0 @@ -interface Color { - red: number, - green: number, - blue: number, -} - -export function parse(str: string): Color { - return { - red: parseInt(str.slice(1,3), 16), - green: parseInt(str.slice(3,5), 16), - blue: parseInt(str.slice(5,7), 16), - } -} - -// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrastratio -export function contrastRatio(c1: Color, c2: Color): number { - const r1 = relativeLuminance(c1) - const r2 = relativeLuminance(c2) - - return r1 > r2 - ? (r1 + 0.05) / (r2 + 0.05) - : (r2 + 0.05) / (r1 + 0.05) -} - -function relativeLuminance(c: Color): number { - return ( - 0.2126 * fromSRGB(c.red / 255) - + 0.7152 * fromSRGB(c.green / 255) - + 0.0722 * fromSRGB(c.blue / 255)) -} - -function fromSRGB(sRGB: number): number { - return sRGB <= 0.03928 - ? sRGB / 12.92 - : Math.pow(((sRGB + 0.055) / 1.055), 2.4) -} diff --git a/src/lib/contextMenu.ts b/src/lib/contextMenu.ts deleted file mode 100644 index 6edd567..0000000 --- a/src/lib/contextMenu.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { h } from 'lib/h' - -interface Action { - label: string, - action: () => void -} - -export function show(event: MouseEvent, actions: Action[]) { - const menu = h('div', - { id: 'g-ContextMenu', - style: `left: ${event.pageX.toString()}px; top: ${event.pageY.toString()}px` - }, - ...actions.map(({ label, action }) => - h('div', - { className: 'g-ContextMenu__Entry', - onclick: () => action() - }, - label - ) - ) - ) - - document.body.appendChild(menu) - - // Remove on click or context menu - setTimeout(() => { - const f = () => { - document.body.removeChild(menu) - document.body.removeEventListener('click', f) - document.body.removeEventListener('contextmenu', f) - } - document.body.addEventListener('click', f) - document.body.addEventListener('contextmenu', f) - }, 0) -} diff --git a/src/lib/dom.ts b/src/lib/dom.ts deleted file mode 100644 index 2ab4de5..0000000 --- a/src/lib/dom.ts +++ /dev/null @@ -1,6 +0,0 @@ -export function replaceChildren(parent: Element, ...newChildren: Element[]) { - while (parent.lastChild) { - parent.removeChild(parent.lastChild) - } - newChildren.forEach(c => parent.appendChild(c)) -} diff --git a/src/lib/form.ts b/src/lib/form.ts deleted file mode 100644 index 04a2654..0000000 --- a/src/lib/form.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { h } from 'lib/h' -import * as Layout from 'lib/layout' -import * as Button from 'lib/button' - -interface InputParams { - label: string, - attrs: object, -} - -export function input({ label, attrs }: InputParams): Element { - return h('label', - { className: 'g-Form__Field' }, - label, - h('input', attrs), - ) -} - -interface ColorInputParams { - colors: string[], - label: string, - initValue: string, - onInput: (value: string) => void, -} - -export function colorInput({ colors, label, initValue, onInput }: ColorInputParams): Element { - const input = h('input', - { value: initValue, - type: 'color', - oninput: (e: Event) => { - if (e.target !== null) { - onInput((e.target as HTMLInputElement).value) - } - } - } - ) as HTMLInputElement - return h('label', - { className: 'g-Form__Field' }, - label, - Layout.line( - {}, - input, - ...colors.map(color => - Button.raw({ className: 'g-Form__Color', - style: `background-color: ${color}`, - type: 'button', - onclick: () => { - input.value = color - onInput(color) - } - }) - ) - ) - ) -} diff --git a/src/lib/h.ts b/src/lib/h.ts deleted file mode 100644 index 7e93311..0000000 --- a/src/lib/h.ts +++ /dev/null @@ -1,31 +0,0 @@ -type Child = Element | Text | string | number - -export type Children = Child[] - -export function h(tagName: string, attrs: object, ...children: Children): Element { - let elem = document.createElement(tagName) - elem = Object.assign(elem, attrs) - appendChildren(elem, ...children) - return elem -} - -export function s(tagName: string, attrs: object, ...children: Children): Element { - let elem = document.createElementNS('http://www.w3.org/2000/svg', tagName) - Object.entries(attrs).forEach(([key, value]) => elem.setAttribute(key, value)) - appendChildren(elem, ...children) - return elem -} - -function appendChildren(elem: Element, ...children: Children) { - for (const child of children) { - if (typeof child === 'number') - elem.append(child.toString()) - else - elem.append(child) - } -} - -export function concatClassName(attrs: any, className: string): object { - const existingClassName = 'className' in attrs ? attrs['className'] : undefined - return { ...attrs, className: `${className} ${existingClassName}` } -} diff --git a/src/lib/icons.ts b/src/lib/icons.ts deleted file mode 100644 index 8db4e17..0000000 --- a/src/lib/icons.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { h, s } from 'lib/h' - -export function get(key: string, attrs: object = {}): Element { - const elem = fromKey(key) - if (elem !== undefined) { - Object.entries(attrs).forEach(([key, value]) => { - elem.setAttribute(key, value) - }) - return elem - } else { - return h('span', {}) - } -} - -// https://yqnn.github.io/svg-path-editor/ -function fromKey(key: string): Element | undefined { - if (key == 'house') { - return s('svg', - { viewBox: '0 0 10 10' }, - s('g', { 'stroke': 'none' }, - s('path', { d: 'M0 4V5H1.5V10H4V7C4.4 6.5 5.6 6.5 6 7V10H8.5V5H10V4L5 0Z' }) - ) - ) - } else if (key == 'music') { - return s('svg', - { viewBox: '0 0 10 10' }, - s('g', { 'stroke': 'none' }, - s('ellipse', { cx: '2', cy: '8.5', rx: '2', ry: '1.5' }), - s('ellipse', { cx: '8', cy: '7', rx: '2', ry: '1.5' }), - s('path', { d: 'M2.5 8.5 H4 V4.5 L8.5 3 V7 H10 V0 L2.5 2.5 Z' }), - ) - ) - } else if (key == 'shopping-cart') { - return s('svg', - { viewBox: '0 0 10 10' }, - s('circle', { cx: '3.3', cy: '8.5', r: '0.8' }), - s('circle', { cx: '7.3', cy: '8.5', r: '0.8' }), - s('path', { d: 'M.5.6C1.3.6 1.8.7 2.1 1L2.3 6H8.5', fill: 'transparent' }), - s('path', { d: 'M2.3 1.9H9.4L8.6 4H2.4' }), - ) - } else if (key == 'medical') { - return s('svg', - { viewBox: '0 0 10 10' }, - s('path', { d: 'M5 1V9M1 5H9', style: 'stroke-width: 3' }), - ) - } else if (key == 'envelope') { - return s('svg', - { viewBox: '0 0 10 10' }, - s('path', { d: 'M.5 2.5H9.5V7.5H.5ZM.5 3.4 3.5 5Q5 5.8 6.6 5L9.5 3.4', style: 'fill: transparent' }), - ) - } -} - -// Good to add: -// - loisir / cinéma / piscine -// - école -// - gare -// - bus -export function keys(): string[] { - return [ 'house', - 'music', - 'shopping-cart', - 'medical', - 'envelope', - ] -} diff --git a/src/lib/layout.ts b/src/lib/layout.ts deleted file mode 100644 index 1e38bfd..0000000 --- a/src/lib/layout.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { h, Children, concatClassName } from 'lib/h' - -export function section(attrs: object, ...children: Children): Element { - return h('div', - concatClassName(attrs, 'g-Layout__Section'), - ...children - ) -} - -export function line(attrs: object, ...children: Children): Element { - return h('div', - concatClassName(attrs, 'g-Layout__Line'), - ...children - ) -} diff --git a/src/lib/modal.ts b/src/lib/modal.ts deleted file mode 100644 index 8454e1c..0000000 --- a/src/lib/modal.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { h } from 'lib/h' -import * as Button from 'lib/button' - -export function show(content: Element) { - document.body.appendChild(h('div', - { id: 'g-Modal' }, - h('div', - { className: 'g-Modal__Curtain', - onclick: () => hide() - } - ), - h('div', - { className: 'g-Modal__Window' }, - Button.raw( - { className: 'g-Modal__Close', - onclick: () => hide() - }, - 'x' - ), - content - ) - )) -} - -export function hide() { - const modal = document.querySelector('#g-Modal') - modal && document.body.removeChild(modal) -} |