Browse Source

Review fixes

pull/652/head
philon- 1 year ago
parent
commit
05de7a4f95
  1. 24
      src/components/UI/Input.tsx
  2. 68
      src/core/utils/deepCompareConfig.ts
  3. 3
      src/core/utils/eventBus.ts
  4. 2
      src/i18n/locales/en/common.json

24
src/components/UI/Input.tsx

@ -6,16 +6,17 @@ import { useCopyToClipboard } from "@core/hooks/useCopyToClipboard.ts";
import { usePasswordVisibilityToggle } from "@core/hooks/usePasswordVisibilityToggle.ts"; import { usePasswordVisibilityToggle } from "@core/hooks/usePasswordVisibilityToggle.ts";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const cnInvalidBase = "border-2 border-red-500 dark:border-red-500";
const cnDirtyBase = "border-2 border-sky-500 dark:border-sky-500";
const inputVariants = cva( const inputVariants = cva(
"flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-400 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-500 dark:bg-transparet dark:text-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-600", "flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-400 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-500 dark:bg-transparet dark:text-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-600",
{ {
variants: { variants: {
variant: { variant: {
default: "border-slate-300 dark:border-slate-500", default: "border-slate-300 dark:border-slate-500",
invalid: invalid: `${cnInvalidBase} focus:ring-red-500 dark:focus:ring-red-500`,
"border-2 border-red-500 dark:border-red-500 focus:ring-red-500 dark:focus:ring-red-500", dirty: `${cnDirtyBase} focus:ring-sky-500 dark:focus:ring-sky-500`,
dirty:
"border-2 border-sky-500 dark:border-sky-500 focus:ring-sky-500 dark:focus:ring-sky-500",
}, },
}, },
defaultVariants: { defaultVariants: {
@ -140,6 +141,11 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
className, className,
); );
const extrasClassName = cn([
variant === "invalid" && `${cnInvalidBase} border-l-0`,
variant === "dirty" && `${cnDirtyBase} border-l-0`,
]);
return ( return (
<div <div
className={cn("relative flex w-full items-stretch", containerClassName)} className={cn("relative flex w-full items-stretch", containerClassName)}
@ -165,10 +171,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<span <span
className={cn( className={cn(
"inline-flex items-center border border-l-0 border-slate-300 bg-slate-100/80 px-3 text-sm text-slate-600 dark:border-slate-700 dark:bg-slate-700 dark:text-slate-300", "inline-flex items-center border border-l-0 border-slate-300 bg-slate-100/80 px-3 text-sm text-slate-600 dark:border-slate-700 dark:bg-slate-700 dark:text-slate-300",
variant === "invalid" && extrasClassName,
"border-2 border-l-0 border-red-500 dark:border-red-500",
variant === "dirty" &&
"border-2 border-l-0 border-sky-500 dark:border-sky-500",
!hasActions && "rounded-r-md", !hasActions && "rounded-r-md",
)} )}
> >
@ -180,10 +183,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<div <div
className={cn( className={cn(
"flex items-center divide-x divide-slate-300 border border-l-0 border-slate-300 dark:divide-slate-700 dark:border-slate-500", "flex items-center divide-x divide-slate-300 border border-l-0 border-slate-300 dark:divide-slate-700 dark:border-slate-500",
variant === "invalid" && extrasClassName,
"border-2 border-l-0 border-red-500 dark:border-red-500",
variant === "dirty" &&
"border-2 border-l-0 border-sky-500 dark:border-sky-500",
disabled && disabled &&
"border-slate-200 dark:border-slate-700 divide-slate-200", "border-slate-200 dark:border-slate-700 divide-slate-200",
!hasSuffix && "rounded-r-md", !hasSuffix && "rounded-r-md",

68
src/core/utils/deepCompareConfig.ts

@ -1,66 +1,56 @@
function isObject(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
export function deepCompareConfig( export function deepCompareConfig(
existing: unknown, a: unknown,
working: unknown, b: unknown,
allowUndefined = false, allowUndefined = false,
): boolean { ): boolean {
if (existing === working) return true; if (a === b) {
return true;
}
if ( // If allowUndefined is true, and one is undefined, they are considered equal. // This check is placed early to simplify subsequent logic.
allowUndefined && if (allowUndefined && (a === undefined || b === undefined)) {
(typeof existing === "undefined" || typeof working === "undefined") return true;
) return true; }
if (typeof existing !== typeof working) { if (typeof a !== typeof b || a === null || b === null) {
return false; return false;
} }
if (existing === null || working === null) { if (Array.isArray(a) && Array.isArray(b)) {
if (existing !== working) { if (a.length !== b.length && !allowUndefined) {
return false; return false;
} }
return true;
}
if (Array.isArray(existing) && Array.isArray(working)) { const longestLength = Math.max(a.length, b.length);
if (existing.length !== working.length && !allowUndefined) { for (let i = 0; i < longestLength; i++) {
return false; if (!deepCompareConfig(a[i], b[i], allowUndefined)) {
}
for (let i = 0; i < existing.length; i++) {
if (
!deepCompareConfig(existing[i], working[i], allowUndefined)
) {
return false; return false;
} }
} }
return true; return true;
} }
if (typeof existing === "object" && typeof working === "object") { if (isObject(a) && isObject(b)) {
const exObj = existing as Record<string, unknown>; const aKeys = Object.keys(a);
const woObj = working as Record<string, unknown>; const bKeys = Object.keys(b);
const keys = new Set<string>([ const allKeys = new Set([...aKeys, ...bKeys]);
...Object.keys(exObj),
...Object.keys(woObj),
]);
for (const key of keys) { for (const key of allKeys) {
if (key === "$typeName") continue; if (key === "$typeName") {
const hasExisting = Object.prototype.hasOwnProperty.call(exObj, key);
const hasWorking = Object.prototype.hasOwnProperty.call(woObj, key);
const valExisting = exObj[key];
const valWorking = woObj[key];
if (!hasWorking && allowUndefined && hasExisting) {
continue; continue;
} }
if ( const aValue = a[key];
!deepCompareConfig(valExisting, valWorking, allowUndefined) const bValue = b[key];
) {
if (!deepCompareConfig(aValue, bValue, allowUndefined)) {
return false; return false;
} }
} }
return true; return true;
} }

3
src/core/utils/eventBus.ts

@ -2,9 +2,6 @@ export type EventMap = {
"dialog:unsafeRoles": { "dialog:unsafeRoles": {
action: "confirm" | "dismiss"; action: "confirm" | "dismiss";
}; };
"dialog:managedMode": {
action: "confirm" | "dismiss";
};
}; };
export type EventName = keyof EventMap; export type EventName = keyof EventMap;

2
src/i18n/locales/en/common.json

@ -71,7 +71,7 @@
"unset": "UNSET", "unset": "UNSET",
"fallbackName": "Meshtastic {{last4}}", "fallbackName": "Meshtastic {{last4}}",
"formValidation": { "formValidation": {
"unsavedChanges": "There are unsaved changes", "unsavedChanges": "Unsaved changes",
"tooBig": { "tooBig": {
"string": "Too long, expected less than or equal to {{maximum}} characters.", "string": "Too long, expected less than or equal to {{maximum}} characters.",
"number": "Too big, expected a number smaller than or equal to {{maximum}}.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.",

Loading…
Cancel
Save