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 / kql.ts
Last active September 20, 2023 07:23
Vue composable to fetch KQL queries
import { $fetch } from "ofetch";
import { hash } from "ohash";
import { toValue } from "@vueuse/core";
import { useQuery } from "vue-unquery";
import { useI18n } from "@byjohann/vue-i18n";
import type { MaybeRefOrGetter } from "@vueuse/core";
import type { TurboVueOptions } from "vue-unquery";
import type { KirbyQueryRequest, KirbyQueryResponse } from "kirby-types";
let responseCache: KirbyQueryResponse | undefined;
@johannschopplich
johannschopplich / spreadsheet.ts
Last active February 12, 2024 13:19
Fetch data from Google Sheets API in TypeScript
export interface SpreadsheetValues {
majorDimension: "DIMENSION_UNSPECIFIED" | "ROWS" | "COLUMNS";
range: string;
values: string[][];
}
export async function getSpreadsheetValues(
id: string,
sheet: string
): Promise<Record<string, string>[]> {
@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)),