feat: add number property type

This commit is contained in:
lucaronin
2026-04-18 19:40:00 +02:00
parent 8c0a2e7ec8
commit 7deeb49751
8 changed files with 318 additions and 68 deletions

View File

@@ -2,10 +2,10 @@ import type { FrontmatterValue } from '../components/Inspector'
import { getAppStorageItem } from '../constants/appStorage'
import { isValidCssColor, isColorKeyName } from './colorUtils'
import { updateVaultConfigField } from './vaultConfigStore'
import { CalendarIcon, Type, ToggleLeft, Circle, Link, Tag, Palette } from 'lucide-react'
import { CalendarIcon, Type, ToggleLeft, Circle, Link, Tag, Palette, Hash } from 'lucide-react'
import { canonicalSystemMetadataKey } from './systemMetadata'
export type PropertyDisplayMode = 'text' | 'date' | 'boolean' | 'status' | 'url' | 'tags' | 'color'
export type PropertyDisplayMode = 'text' | 'number' | 'date' | 'boolean' | 'status' | 'url' | 'tags' | 'color'
const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2})?)?/
const COMMON_DATE_RE = /^\d{1,2}\/\d{1,2}\/\d{2,4}$/
@@ -33,17 +33,35 @@ function isDateString(value: string): boolean {
return ISO_DATE_RE.test(value) || COMMON_DATE_RE.test(value)
}
function isStatusKey(key: string): boolean {
return keyMatchesPatterns(key, STATUS_KEY_PATTERNS)
}
function isDateKey(key: string): boolean {
return keyMatchesPatterns(key, DATE_KEY_PATTERNS)
}
function isStatusString(key: string, value: string): boolean {
if (isStatusKey(key)) return true
if (isDateKey(key)) return false
return STATUS_VALUES.has(value.toLowerCase())
}
function isColorString(key: string, value: string): boolean {
return isValidCssColor(value) && (value.startsWith('#') || isColorKeyName(key))
}
function detectStringType(key: string, strValue: string): PropertyDisplayMode {
if (isIconKey(key)) return 'text'
if (keyMatchesPatterns(key, STATUS_KEY_PATTERNS)) return 'status'
if (STATUS_VALUES.has(strValue.toLowerCase()) && !keyMatchesPatterns(key, DATE_KEY_PATTERNS)) return 'status'
if (isStatusString(key, strValue)) return 'status'
if (isDateString(strValue)) return 'date'
if (isValidCssColor(strValue) && (strValue.startsWith('#') || isColorKeyName(key))) return 'color'
if (isColorString(key, strValue)) return 'color'
return 'text'
}
export function detectPropertyType(key: string, value: FrontmatterValue): PropertyDisplayMode {
if (value === null || value === undefined) return 'text'
if (typeof value === 'number') return 'number'
if (typeof value === 'boolean') return 'boolean'
if (isIconKey(key)) return 'text'
if (keyMatchesPatterns(key, TAGS_KEY_PATTERNS)) return 'tags'
@@ -95,22 +113,25 @@ export function getEffectiveDisplayMode(
return overrides[key] ?? detectPropertyType(key, value)
}
export function formatDateValue(value: string): string {
function resolveDateFromValue(value: string): Date | null {
const isoMatch = value.match(ISO_DATE_RE)
if (isoMatch) {
const d = new Date(isoMatch[0])
if (!isNaN(d.getTime())) {
return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
}
const date = new Date(isoMatch[0])
return Number.isNaN(date.getTime()) ? null : date
}
const parts = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/)
if (parts) {
const d = new Date(Number(parts[3]), Number(parts[1]) - 1, Number(parts[2]))
if (!isNaN(d.getTime())) {
return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
}
}
return value
if (!parts) return null
const date = new Date(Number(parts[3]), Number(parts[1]) - 1, Number(parts[2]))
return Number.isNaN(date.getTime()) ? null : date
}
export function formatDateValue(value: string): string {
const date = resolveDateFromValue(value)
return date
? date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
: value
}
export function toISODate(value: string): string {
@@ -123,11 +144,12 @@ export function toISODate(value: string): string {
}
export const DISPLAY_MODE_ICONS: Record<PropertyDisplayMode, typeof Type> = {
text: Type, date: CalendarIcon, boolean: ToggleLeft, status: Circle, url: Link, tags: Tag, color: Palette,
text: Type, number: Hash, date: CalendarIcon, boolean: ToggleLeft, status: Circle, url: Link, tags: Tag, color: Palette,
}
export const DISPLAY_MODE_OPTIONS: { value: PropertyDisplayMode; label: string }[] = [
{ value: 'text', label: 'Text' },
{ value: 'number', label: 'Number' },
{ value: 'date', label: 'Date' },
{ value: 'boolean', label: 'Boolean' },
{ value: 'status', label: 'Status' },