commit09bed34946Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 8 14:03:50 2022 +0100 Fixed the layout of a search list item commit90126d43adAuthor: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 17:25:13 2022 +0100 Insanely complicated path search results highlighitng and truncating commita4bbd5521eAuthor: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 14:05:01 2022 +0100 Improved the title editing in the header commit5814053968Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 13:38:33 2022 +0100 Improved text highlight colour commit110de37242Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 13:36:57 2022 +0100 Icon hover state now uses isHighlighted commitfb6da943d9Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 13:31:11 2022 +0100 Light mode styling commit2c378d5158Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 12:24:43 2022 +0100 Spacing between search items no longer a hack commit85d90bb0aeAuthor: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 12:19:10 2022 +0100 Added ellipsis to search matches if they are windowed commit91f3e70676Author: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 12:08:00 2022 +0100 Fixed search item icons commite384c87c6fAuthor: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 11:52:58 2022 +0100 Improved hover state commitf4681edc07Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 11:47:33 2022 +0100 Removed focus state on button commitfaa2d0663cAuthor: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 11:26:42 2022 +0100 made the search palette a little bigger commitdf8bd521feAuthor: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 11:26:14 2022 +0100 Remove onOverlayClick prop commitecd046b3b2Author: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 11:18:46 2022 +0100 Close search when the overlay is clicked commitfba330b5d9Author: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 11:10:35 2022 +0100 hitting esc when search input is focused and empty should close the search commitfc2fe8ae6fAuthor: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 11:00:08 2022 +0100 Highlight the window of the best search match in the search results commit45193ec92cAuthor: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 10:45:01 2022 +0100 Now you can arrow down to the last item in the list commit0de5fef7e9Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Apr 1 10:37:20 2022 +0100 Added a hacky margin between items and remove the transition to make it feel snappier commit167b548343Author: Eric Allam <eallam@icloud.com> Date: Fri Apr 1 09:30:33 2022 +0100 WIP implementing search commit5655631f12Author: James Ritchie <james@jamesritchie.co.uk> Date: Fri Mar 25 15:28:19 2022 +0000 Build and styled search modal commite368db81c8Author: Eric Allam <eallam@icloud.com> Date: Fri Mar 25 14:42:03 2022 +0000 Implement JSON search through fuse.js + web worker + react hook commit8caa11ba1cAuthor: Eric Allam <eallam@icloud.com> Date: Wed Mar 23 10:21:33 2022 +0000 Start of the Command Palette using radix-ui Dialog commit904b64d781Author: Eric Allam <eallam@icloud.com> Date: Wed Mar 23 09:58:52 2022 +0000 Uncommented out the search bar field
157 lines
3.4 KiB
TypeScript
157 lines
3.4 KiB
TypeScript
import { Temporal } from "@js-temporal/polyfill";
|
|
import { inferTemporal } from "./inferredTemporal";
|
|
|
|
import {
|
|
JSONDateTimeFormat,
|
|
JSONStringFormat,
|
|
JSONValueType,
|
|
} from "@jsonhero/json-infer-types";
|
|
|
|
export function formatRawValue(type: JSONValueType): string {
|
|
switch (type.name) {
|
|
case "string":
|
|
return type.value;
|
|
case "int":
|
|
return type.value.toString();
|
|
case "float":
|
|
return type.value.toString();
|
|
case "bool":
|
|
return type.value ? "true" : "false";
|
|
case "null":
|
|
return "null";
|
|
case "array":
|
|
return "[]";
|
|
case "object":
|
|
return "{}";
|
|
}
|
|
}
|
|
|
|
export type FormatValueOptions = {
|
|
leafNodesOnly?: boolean;
|
|
};
|
|
|
|
export function formatValue(
|
|
type: JSONValueType,
|
|
options?: FormatValueOptions
|
|
): string | undefined {
|
|
switch (type.name) {
|
|
case "array": {
|
|
if (options?.leafNodesOnly) {
|
|
return;
|
|
}
|
|
|
|
if (type.value.length == 0) {
|
|
return formatRawValue(type);
|
|
} else if (type.value.length === 1) {
|
|
return `1 item`;
|
|
} else {
|
|
return `${type.value.length} items`;
|
|
}
|
|
}
|
|
case "object": {
|
|
if (options?.leafNodesOnly) {
|
|
return;
|
|
}
|
|
|
|
if (Object.keys(type.value).length == 0) {
|
|
return formatRawValue(type);
|
|
} else if (Object.keys(type.value).length === 1) {
|
|
return `1 field`;
|
|
} else {
|
|
return `${Object.keys(type.value).length} fields`;
|
|
}
|
|
}
|
|
case "bool": {
|
|
return type.value ? "true" : "false";
|
|
}
|
|
case "float":
|
|
case "int":
|
|
return formatNumber(type.value);
|
|
case "null": {
|
|
return "null";
|
|
}
|
|
case "string":
|
|
return formatString(type.value, type.format);
|
|
default:
|
|
const _exhaustiveCheck: never = type;
|
|
return _exhaustiveCheck;
|
|
}
|
|
}
|
|
|
|
const numberFormatter = new Intl.NumberFormat(undefined, {
|
|
maximumFractionDigits: 6,
|
|
});
|
|
|
|
export function formatNumber(value: number): string {
|
|
return numberFormatter.format(value);
|
|
}
|
|
|
|
function formatString(value: string, format?: JSONStringFormat): string {
|
|
if (!format) {
|
|
return value;
|
|
}
|
|
|
|
switch (format.name) {
|
|
case "email":
|
|
return value;
|
|
case "uri":
|
|
return value;
|
|
case "datetime":
|
|
return formatDateTime(value, format);
|
|
default:
|
|
return value;
|
|
}
|
|
}
|
|
|
|
export function formatDateTime(
|
|
value: string,
|
|
format?: JSONDateTimeFormat
|
|
): string {
|
|
if (!format) {
|
|
return value;
|
|
}
|
|
|
|
const temporal = inferTemporal(value, format);
|
|
|
|
if (!temporal) {
|
|
return value;
|
|
}
|
|
|
|
switch (format.parts) {
|
|
case "datetime":
|
|
return temporal.toLocaleString("en-US", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
hour: "numeric",
|
|
minute: "numeric",
|
|
second: "numeric",
|
|
timeZoneName: "short",
|
|
});
|
|
case "date":
|
|
return temporal.toLocaleString("en-US", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
});
|
|
case "time":
|
|
return temporal.toLocaleString("en-US", {
|
|
hour: "numeric",
|
|
minute: "numeric",
|
|
second: "numeric",
|
|
});
|
|
}
|
|
}
|
|
|
|
export function formatBytes(bytes: number, decimals = 2): string {
|
|
if (bytes === 0) return "0 Bytes";
|
|
|
|
const k = 1024;
|
|
const dm = decimals < 0 ? 0 : decimals;
|
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
|
}
|