Fishies 0.8.11
This commit is contained in:
parent
9020cffee7
commit
ed00d055ae
23 changed files with 108 additions and 52 deletions
|
|
@ -1,7 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState, type ImgHTMLAttributes, type Ref } from 'react'
|
||||
import { reveal } from './fx-image'
|
||||
import { imageFallback, reveal } from './fx-image'
|
||||
import './loader.css'
|
||||
|
||||
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect
|
||||
|
|
@ -23,9 +23,16 @@ export default function FishiesImg({ ref, decoding, ...props }: ImgHTMLAttribute
|
|||
mounted.current = true
|
||||
reveal(img, first && img.complete)
|
||||
const settle = () => reveal(img)
|
||||
delete img.dataset.webpFallback
|
||||
|
||||
const failed = () => {
|
||||
const png = imageFallback(img.currentSrc || img.src)
|
||||
if (png && !img.dataset.webpFallback) { img.dataset.webpFallback = '1'; img.src = png; return }
|
||||
reveal(img)
|
||||
}
|
||||
img.addEventListener('load', settle)
|
||||
img.addEventListener('error', settle)
|
||||
return () => { img.removeEventListener('load', settle); img.removeEventListener('error', settle) }
|
||||
img.addEventListener('error', failed)
|
||||
return () => { img.removeEventListener('load', settle); img.removeEventListener('error', failed) }
|
||||
}, [props.src, props.srcSet])
|
||||
return <img {...props} ref={setRef} decoding={decoding ?? 'async'} data-fx="wait" suppressHydrationWarning/>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
export type FxState = 'wait' | 'fade' | 'ready' | 'error'
|
||||
|
||||
let alternative: (src: string) => string | null = () => null
|
||||
export function configureImageFallback(find: (src: string) => string | null): void { alternative = find }
|
||||
export const imageFallback = (src: string): string | null => alternative(src)
|
||||
|
||||
export function reveal(img: HTMLImageElement, instant?: boolean): void {
|
||||
if (img.getAttribute('data-fx') !== 'wait' || !img.complete) return
|
||||
const src = img.currentSrc || img.src
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly sharpTo: number; readonly usedBy: readonly string[] }>> = {
|
||||
"feed": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"net": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -17,8 +17,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"clean": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -26,8 +26,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"decorate": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
|
|
@ -37,7 +37,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"remedy": {
|
||||
|
|
@ -68,8 +69,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"explore": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -86,8 +87,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"shop": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -112,8 +113,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"inventory": {
|
||||
"px": 56,
|
||||
"sharpTo": 28,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -147,16 +148,16 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"pin": {
|
||||
"px": 40,
|
||||
"sharpTo": 20,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
]
|
||||
},
|
||||
"menu": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -164,8 +165,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"bell": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -192,8 +193,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"sound": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -202,8 +203,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"mute": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
|
|
@ -211,17 +212,18 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
]
|
||||
},
|
||||
"music": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
]
|
||||
},
|
||||
"fullscreen": {
|
||||
"px": 52,
|
||||
"sharpTo": 26,
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Reef Journal",
|
||||
"Video player"
|
||||
]
|
||||
},
|
||||
|
|
@ -310,7 +312,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
"Keeper OS",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"lock": {
|
||||
|
|
@ -375,6 +378,7 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
|
|
@ -424,6 +428,7 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
|
|
@ -438,7 +443,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"block": {
|
||||
|
|
@ -498,7 +504,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"thermometer": {
|
||||
|
|
@ -520,7 +527,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
]
|
||||
},
|
||||
"gift": {
|
||||
|
|
@ -551,15 +559,17 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
"Keeper OS",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"quest": {
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"px": 320,
|
||||
"sharpTo": 160,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
"Keeper OS",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"check": {
|
||||
|
|
@ -620,7 +630,8 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
"usedBy": [
|
||||
"Game"
|
||||
"Game",
|
||||
"Keeper OS"
|
||||
]
|
||||
},
|
||||
"journal": {
|
||||
|
|
@ -630,6 +641,14 @@ export const ICON_FACTS: Readonly<Record<string, { readonly px: number; readonly
|
|||
"Game"
|
||||
]
|
||||
},
|
||||
"research": {
|
||||
"px": 320,
|
||||
"sharpTo": 160,
|
||||
"usedBy": [
|
||||
"Game",
|
||||
"Reef Journal"
|
||||
]
|
||||
},
|
||||
"add": {
|
||||
"px": 168,
|
||||
"sharpTo": 84,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ export const SYSTEM_ICONS = [
|
|||
ui('keyboard', 'Keys', 'system', 'shortcuts and keys'), ui('external', 'Opens elsewhere', 'system', 'opens in a new tab'),
|
||||
|
||||
ui('journal', 'Reef Journal', 'places', 'the Reef Journal notebook'),
|
||||
ui('research', 'Research', 'places', 'the Research app: studies, levers and the tree'),
|
||||
ui('add', 'New', 'system', 'new, create'), ui('download', 'Download', 'system', 'download'), ui('mail', 'Mail', 'system', 'email, the newsletter'),
|
||||
emote('hello', 'Hello', 'wave hello'), emote('heart', 'Love', 'send love'), emote('question', 'Question', 'wonder aloud'), emote('surprise', 'Surprise', 'be surprised'),
|
||||
emote('food', 'Food', 'ask for food'), emote('sleep', 'Sleepy', 'feel sleepy'), emote('music', 'Music', 'enjoy the music'), emote('sparkle', 'Sparkle', 'something wonderful'),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue