diff --git a/go/jsbundler/faicons.go b/go/jsbundler/faicons.go
index a9dfe2bc..670202d7 100644
--- a/go/jsbundler/faicons.go
+++ b/go/jsbundler/faicons.go
@@ -119,6 +119,15 @@ func generateFAIcons() error {
}
b.WriteString("};\n")
+ // Skip the write when content is unchanged so the file's mtime doesn't
+ // advance on every SPA source edit — the dev watcher treats any mtime bump
+ // as a real change and hot-reloads Icons.tsx (the nearest HMR boundary that
+ // imports this file), which is wasteful when nothing about the icon set
+ // actually changed.
+ if existing, err := os.ReadFile(faOutPath()); err == nil && string(existing) == b.String() {
+ return nil
+ }
+
if err := os.MkdirAll(filepath.Dir(faOutPath()), 0755); err != nil {
return err
}
diff --git a/go/jsruntime/uikit/AutoTable.tsx b/go/jsruntime/uikit/AutoTable.tsx
index 0640cfa9..1268b8c4 100644
--- a/go/jsruntime/uikit/AutoTable.tsx
+++ b/go/jsruntime/uikit/AutoTable.tsx
@@ -4144,7 +4144,7 @@ export function AutoTable(props: AutoTableProps) {
(small ? CONTROL_H_SM : CONTROL_H);
function _fieldBorder(error?: unknown, success?: unknown, onDark?: boolean): string {
- const borderNormal = onDark ? "border-border-on-dark focus:outline-sky-500" : "border-line-strong focus:outline-sky-500";
+ const borderNormal = onDark ? "border-border-on-dark focus:outline-sky-500" : "border-neutral-300 focus:outline-sky-500";
return error ? "border-red-500 focus:outline-red-500"
: success ? "border-green-500 focus:outline-green-500"
: borderNormal;
@@ -37,33 +38,33 @@ function _textareaCls(small?: boolean, error?: unknown, extra?: string, onDark?:
function _prefixCls(small?: boolean, error?: unknown, onDark?: boolean): string {
const base = onDark
? "bg-dark-raised text-text-on-dark-muted border shadow-xs border-r-0 flex items-center shrink-0 rounded-l-default"
- : "bg-surface-raised border shadow-xs border-r-0 flex items-center shrink-0 rounded-l-default";
- const borderNormal = onDark ? "border-border-on-dark" : "border-line-strong";
+ : "bg-neutral-100 border shadow-xs border-r-0 flex items-center shrink-0 rounded-l-default";
+ const borderNormal = onDark ? "border-border-on-dark" : "border-neutral-300";
return base
+ (error ? " border-red-500" : " " + borderNormal)
+ (small ? " p-1 text-sm" : " p-2");
}
-const FORM_ERROR = "block text-red-600 dark:text-red-400 text-xs mt-1";
-const FORM_SUCCESS = "block text-green-600 dark:text-green-400 text-xs mt-1";
+const FORM_ERROR = "block text-red-600 text-xs mt-1";
+const FORM_SUCCESS = "block text-green-600 text-xs mt-1";
const INPUT_GROUP = "flex flex-row items-stretch w-full text-sm";
-const TRIGGER_BASE = "bg-surface border border-line-strong rounded-default shadow-xs text-sm w-full text-left flex items-center justify-between gap-2 cursor-pointer disabled:bg-surface-raised disabled:cursor-not-allowed";
+const TRIGGER_BASE = "bg-white border border-neutral-300 rounded-default shadow-xs text-sm w-full text-left flex items-center justify-between gap-2 cursor-pointer disabled:bg-neutral-100 disabled:cursor-not-allowed";
const TRIGGER_BASE_DARK = "bg-dark-raised border border-border-on-dark text-text-on-dark rounded-default shadow-xs text-sm w-full text-left flex items-center justify-between gap-2 cursor-pointer hover:border-border-on-dark-hover disabled:opacity-50 disabled:cursor-not-allowed";
-const DROPDOWN = "bg-surface border border-line-strong rounded-default shadow-lg max-h-60 overflow-auto";
+const DROPDOWN = "bg-white border border-neutral-300 rounded-default shadow-lg max-h-60 overflow-auto";
const DROPDOWN_DARK = "bg-dark-raised border border-border-on-dark rounded-default shadow-lg max-h-60 overflow-auto";
-const DROPDOWN_SEARCH_WRAP = "sticky top-0 bg-surface border-b border-line p-2";
+const DROPDOWN_SEARCH_WRAP = "sticky top-0 bg-white border-b border-neutral-200 p-2";
const DROPDOWN_SEARCH_WRAP_DARK = "sticky top-0 bg-dark-raised border-b border-border-on-dark p-2";
-const DROPDOWN_SEARCH_INPUT = "w-full bg-surface border border-line-strong rounded-default shadow-xs text-sm p-1 focus:outline-2 focus:outline-sky-500 focus:outline-offset-1";
+const DROPDOWN_SEARCH_INPUT = "w-full bg-white border border-neutral-300 rounded-default shadow-xs text-sm p-1 focus:outline-2 focus:outline-sky-500 focus:outline-offset-1";
const DROPDOWN_SEARCH_INPUT_DARK = "w-full bg-dark border border-border-on-dark text-text-on-dark placeholder:text-text-on-dark-faint rounded-default shadow-xs text-sm p-1 focus:outline-2 focus:outline-sky-500 focus:outline-offset-1";
-const DROPDOWN_OPTION = "w-full text-left p-2 text-sm cursor-pointer flex items-center gap-2 bg-transparent border-none hover:bg-surface-raised disabled:text-ink-faint disabled:cursor-not-allowed whitespace-nowrap";
+const DROPDOWN_OPTION = "w-full text-left p-2 text-sm cursor-pointer flex items-center gap-2 bg-transparent border-none hover:bg-neutral-100 disabled:text-neutral-400 disabled:cursor-not-allowed whitespace-nowrap";
const DROPDOWN_OPTION_DARK = "w-full text-left p-2 text-sm cursor-pointer flex items-center gap-2 bg-transparent border-none text-text-on-dark hover:bg-white/5 disabled:text-text-on-dark-faint disabled:cursor-not-allowed whitespace-nowrap";
-const DROPDOWN_OPTION_HIGHLIGHT = "bg-surface-raised";
+const DROPDOWN_OPTION_HIGHLIGHT = "bg-neutral-100";
const DROPDOWN_OPTION_HIGHLIGHT_DARK = "bg-white/10";
-const DROPDOWN_NO_RESULTS = "p-2 text-sm text-ink-muted text-center";
+const DROPDOWN_NO_RESULTS = "p-2 text-sm text-neutral-500 text-center";
const DROPDOWN_NO_RESULTS_DARK = "p-2 text-sm text-text-on-dark-muted text-center";
-const SELECT_ALL_WRAP = "border-b border-line";
-const SELECT_ALL_BTN = "w-full text-left p-2 text-sm cursor-pointer text-ink-soft font-medium bg-transparent border-none hover:bg-surface-raised";
+const SELECT_ALL_WRAP = "border-b border-neutral-200";
+const SELECT_ALL_BTN = "w-full text-left p-2 text-sm cursor-pointer text-neutral-600 font-medium bg-transparent border-none hover:bg-neutral-100";
// -- Shared types --------------------------------------------------
type CommonInputAttrs =
@@ -373,7 +374,7 @@ export function FormCurrencyInput(props: {showIcon?: boolean} & FormInputProps)
}
};
- return ;
+ return ;
}
@@ -393,7 +394,7 @@ export function FormPercentInput(props: {showIcon?: boolean} & FormInputProps) {
}
};
- return ;
+ return ;
}
export function FormPhoneInput(props: {showIcon?: boolean; icon?: string} & FormInputProps) {
@@ -404,6 +405,9 @@ export function FormPhoneInput(props: {showIcon?: boolean; icon?: string} & Form
const input = e.currentTarget;
let digits = input.value.replace(/\D/g, "");
+ if (digits[0] === "0" || digits[0] === "1") {
+ digits = digits.slice(1);
+ }
digits = digits.slice(0, 10);
let formatted = "";
if (digits.length > 0) {
@@ -634,7 +638,7 @@ export function FormSignaturePad(props: { value?: () => string; onchange?: (svg:
};
return