forked from nostr/nostrweb
refactor: type elem and enforce inferred generic type
typed elem so that it returns the exact type of the HTMLElement, and that name must be a key of HTMLElementTagNameMap. example: elem('form'); // returns HTMLFormElement elem('abc'); // not assignable to parameter of type 'keyof HTMLElementTagNameMap'
parent
2d46687e12
commit
489a260427
30
src/main.js
30
src/main.js
|
@ -3,7 +3,7 @@ import {sub24hFeed, subNote, subProfile} from './subscriptions'
|
|||
import {publish} from './relays';
|
||||
import {getReplyTo, hasEventTag, isMention, sortByCreatedAt, sortEventCreatedAt, validatePow} from './events';
|
||||
import {clearView, getViewContent, getViewElem, setViewElem, view} from './view';
|
||||
import {bounce, dateTime, elem, formatTime, getHost, getNoxyUrl, isWssUrl, parseTextContent, zeroLeadingBitsCount} from './utils';
|
||||
import {bounce, dateTime, elem, elemCanvas, elemShrink, formatTime, getHost, getNoxyUrl, isWssUrl, parseTextContent, zeroLeadingBitsCount} from './utils';
|
||||
// curl -H 'accept: application/nostr+json' https://relay.nostr.ch/
|
||||
|
||||
function onEvent(evt, relay) {
|
||||
|
@ -415,22 +415,6 @@ function setMetadata(evt, relay, content) {
|
|||
// }
|
||||
}
|
||||
|
||||
const elemCanvas = (text) => {
|
||||
const canvas = elem('canvas', {height: 80, width: 80, data: {pubkey: text}});
|
||||
const context = canvas.getContext('2d');
|
||||
const color = `#${text.slice(0, 6)}`;
|
||||
context.fillStyle = color;
|
||||
context.fillRect(0, 0, 80, 80);
|
||||
context.fillStyle = '#111';
|
||||
context.fillRect(0, 50, 80, 32);
|
||||
context.font = 'bold 18px monospace';
|
||||
if (color === '#000000') {
|
||||
context.fillStyle = '#fff';
|
||||
}
|
||||
context.fillText(text.slice(0, 8), 2, 46);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function getMetadata(evt, relay) {
|
||||
const host = getHost(relay);
|
||||
const user = userList.find(user => user.pubkey === evt.pubkey);
|
||||
|
@ -450,20 +434,12 @@ function getMetadata(evt, relay) {
|
|||
|
||||
const writeForm = document.querySelector('#writeForm');
|
||||
|
||||
const elemShrink = () => {
|
||||
const height = writeInput.style.height || writeInput.getBoundingClientRect().height;
|
||||
const shrink = elem('div', {className: 'shrink-out'});
|
||||
shrink.style.height = `${height}px`;
|
||||
shrink.addEventListener('animationend', () => shrink.remove(), {once: true});
|
||||
return shrink;
|
||||
}
|
||||
|
||||
writeInput.addEventListener('focusout', () => {
|
||||
const reply_to = localStorage.getItem('reply_to');
|
||||
if (reply_to && writeInput.value === '') {
|
||||
writeInput.addEventListener('transitionend', (event) => {
|
||||
if (!reply_to || reply_to === localStorage.getItem('reply_to') && !writeInput.style.height) { // should prob use some class or data-attr instead of relying on height
|
||||
writeForm.after(elemShrink());
|
||||
writeForm.after(elemShrink(writeInput));
|
||||
writeForm.remove();
|
||||
localStorage.removeItem('reply_to');
|
||||
}
|
||||
|
@ -472,7 +448,7 @@ writeInput.addEventListener('focusout', () => {
|
|||
});
|
||||
|
||||
function appendReplyForm(el) {
|
||||
writeForm.before(elemShrink());
|
||||
writeForm.before(elemShrink(writeInput));
|
||||
writeInput.blur();
|
||||
writeInput.style.removeProperty('height');
|
||||
el.after(writeForm);
|
||||
|
|
|
@ -18,11 +18,11 @@ type Attributes = {
|
|||
* @param {Array<HTMLElement|string>} children
|
||||
* @return HTMLElement
|
||||
*/
|
||||
export const elem = (
|
||||
name: keyof HTMLElementTagNameMap,
|
||||
attrs: Attributes = {},
|
||||
children: Array<Node> | string = []
|
||||
) => {
|
||||
export const elem = <Name extends keyof HTMLElementTagNameMap>(
|
||||
name: Extract<Name, keyof HTMLElementTagNameMap>,
|
||||
attrs: Attributes = {}, // TODO optional
|
||||
children: Array<Node> | string = [], // TODO optional
|
||||
): HTMLElementTagNameMap[Name] => {
|
||||
const {data, ...props} = attrs;
|
||||
const el = document.createElement(name);
|
||||
Object.assign(el, props);
|
||||
|
@ -127,3 +127,44 @@ export const parseTextContent = (
|
|||
{firstLink}
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* creates a small profile image
|
||||
* @param text to pass pubkey
|
||||
* @returns HTMLCanvasElement | null
|
||||
*/
|
||||
export const elemCanvas = (text: string) => {
|
||||
const canvas = elem('canvas', {
|
||||
height: 80,
|
||||
width: 80,
|
||||
data: {pubkey: text}
|
||||
});
|
||||
const context = canvas.getContext('2d');
|
||||
if (!context) {
|
||||
return null;
|
||||
}
|
||||
const color = `#${text.slice(0, 6)}`;
|
||||
context.fillStyle = color;
|
||||
context.fillRect(0, 0, 80, 80);
|
||||
context.fillStyle = '#111';
|
||||
context.fillRect(0, 50, 80, 32);
|
||||
context.font = 'bold 18px monospace';
|
||||
if (color === '#000000') {
|
||||
context.fillStyle = '#fff';
|
||||
}
|
||||
context.fillText(text.slice(0, 8), 2, 46);
|
||||
return canvas;
|
||||
};
|
||||
|
||||
/**
|
||||
* creates a placeholder element that animates the height to 0
|
||||
* @param element to get the initial height from
|
||||
* @returns HTMLDivElement
|
||||
*/
|
||||
export const elemShrink = (el: HTMLElement) => {
|
||||
const height = el.style.height || el.getBoundingClientRect().height;
|
||||
const shrink = elem('div', {className: 'shrink-out'});
|
||||
shrink.style.height = `${height}px`;
|
||||
shrink.addEventListener('animationend', () => shrink.remove(), {once: true});
|
||||
return shrink;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export {zeroLeadingBitsCount} from './crypto';
|
||||
export {elem, parseTextContent} from './dom';
|
||||
export {elem, elemCanvas, elemShrink, parseTextContent} from './dom';
|
||||
export {bounce, dateTime, formatTime} from './time';
|
||||
export {getHost, getNoxyUrl, isHttpUrl, isWssUrl} from './url';
|
||||
|
|
|
@ -2,7 +2,7 @@ import {elem} from './utils';
|
|||
|
||||
type Container = {
|
||||
id: string;
|
||||
view: HTMLSelectElement;
|
||||
view: HTMLElement;
|
||||
content: HTMLDivElement;
|
||||
dom: {
|
||||
[eventId: string]: HTMLElement
|
||||
|
|
Loading…
Reference in New Issue