Skip to content

Instantly share code, notes, and snippets.

View johannschopplich's full-sized avatar

Johann Schopplich johannschopplich

View GitHub Profile
@johannschopplich
johannschopplich / preload-images.js
Created July 10, 2020 10:12
Web component to preload images
const nanoid = () => Math.random().toString(36).substring(2)
/**
* @module PreloadImages
* @description
* Custom element to preload images
* @property {(string|array)} src Comma seperated list, array or string of image source(s)
*/
export default class PreloadImages extends HTMLElement {
constructor () {
@johannschopplich
johannschopplich / kirby-vue3-starterkit.jhnn.dev-20200711T231402.html
Created July 12, 2020 18:33
Lighthouse report of kirby-vue3-starterkit.jhnn.dev
<!--
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
@johannschopplich
johannschopplich / create.sh
Created July 28, 2020 11:41
Create Ed25519 SSH Key
ssh-keygen -o -a 64 -t ed25519 -f ~/.ssh/id_ed25519 -C "john@example.com"
@johannschopplich
johannschopplich / index.js
Last active December 3, 2020 16:46
Kirby 3.5 accordion block by @distantnative
panel.plugin("distantnative/block-accordion", {
blocks: {
accordion: {
methods: {
addRow() {
this.content.rows.push({ summary: "", detail: "" });
this.update({ rows: this.content.rows });
},
removeRow(index) {
this.content.rows.splice(index, 1);
@johannschopplich
johannschopplich / queries.css
Last active December 16, 2020 14:53
Media queries for differentiating mouse and touch-based screens
@media (hover: none) and (pointer: coarse) {
/* Touchscreens */
}
@media (hover: none) and (pointer: fine) {
/* Stylus */
}
@media (hover: hover) and (pointer: coarse) {
/* Controllers */
}
@media (hover: hover) and (pointer: fine) {
@johannschopplich
johannschopplich / storage.ts
Last active September 5, 2022 18:08
IndexedDB storage wrapper for VueUse
import { useStorageAsync } from "@vueuse/core";
import { get, set, del } from "idb-keyval";
export const STORAGE_KEY_PREFIX = "app.session.";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useIdbStorage<T = any>(key: string, initialValue: T) {
return useStorageAsync(`${STORAGE_KEY_PREFIX}${key}`, initialValue, {
async getItem(key: string) {
return (await get<string>(key)) ?? null;
@johannschopplich
johannschopplich / fetch.ts
Last active October 20, 2022 06:50
Fetch data with typed response from Zog schema
// Create a schema for a post
const Post = z.object({
slug: z.string(),
content: z.string(),
});
// Create a schema for a post collection
const Posts = z.array(Post);
// Fetch a post by slug with the correct typed response
@johannschopplich
johannschopplich / form-data-utils.ts
Created December 12, 2022 21:23
Serialize FormData to object with support for Blobs
import { FormData as _FormData } from 'formdata-polyfill/esm.min.js'
export async function formDataToObject(formData: FormData) {
const obj: Record<string, any> = {}
for (const [key, value] of formData.entries()) {
if (value instanceof Blob) {
obj[key] = {
__type: 'blob',
...(await serializeBlob(value)),
@johannschopplich
johannschopplich / AppIcon.vue
Created February 24, 2023 13:41
Auto-import icons from `assets` in Nuxt
<template>
<span
v-if="icon"
:class="[
'children-[svg]:h-full children-[svg]:w-full',
defaultStyles && 'inline-block h-[1em] w-[1em] align-middle',
]"
v-html="icon"
/>
</template>
@johannschopplich
johannschopplich / index.ts
Created April 20, 2023 09:58
Rust-like result type in TypeScript
/**
* First, create a type helper that represents
* the Result that we'll get from our safe function
*/
type Result<T> =
| {
ok: true;
value: T;
}
| {