feat: publish HoloLake model-native living system source

This commit is contained in:
冰朔 2026-08-03 10:04:41 +08:00
commit c395dd3a99
2467 changed files with 615073 additions and 0 deletions

View file

@ -0,0 +1,62 @@
import type { VaultEntry } from '../../types'
import type { RetargetOption } from './RetargetNoteDialog'
import { RetargetNoteDialog } from './RetargetNoteDialog'
interface NoteRetargetingDialogsProps {
dialogState: { kind: 'type' | 'folder'; notePath: string } | null
dialogEntry: VaultEntry | null
typeOptions: RetargetOption[]
folderOptions: RetargetOption[]
onClose: () => void
onSelectType: (type: string) => boolean | Promise<boolean>
onSelectFolder: (folderPath: string) => boolean | Promise<boolean>
}
function typeDialogDescription(entry: VaultEntry | null): string {
return entry
? `Set a new type for "${entry.title}".`
: 'Select a type for the active note.'
}
function folderDialogDescription(entry: VaultEntry | null): string {
return entry
? `Choose a destination folder for "${entry.title}".`
: 'Select a destination folder for the active note.'
}
export function NoteRetargetingDialogs({
dialogState,
dialogEntry,
typeOptions,
folderOptions,
onClose,
onSelectType,
onSelectFolder,
}: NoteRetargetingDialogsProps) {
return (
<>
<RetargetNoteDialog
open={dialogState?.kind === 'type'}
title="Change Note Type"
description={typeDialogDescription(dialogEntry)}
searchPlaceholder="Search types"
emptyMessage="No other note types available."
options={typeOptions}
onClose={onClose}
onSelect={onSelectType}
testIdPrefix="retarget-note-type"
/>
<RetargetNoteDialog
open={dialogState?.kind === 'folder'}
title="Move Note to Folder"
description={folderDialogDescription(dialogEntry)}
searchPlaceholder="Search folders"
emptyMessage="No other folders available."
options={folderOptions}
onClose={onClose}
onSelect={onSelectFolder}
testIdPrefix="retarget-note-folder"
/>
</>
)
}

View file

@ -0,0 +1,175 @@
import { Check, StackSimple } from '@phosphor-icons/react'
import { useMemo, useState, type KeyboardEvent } from 'react'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { ScrollArea } from '@/components/ui/scroll-area'
import { cn } from '@/lib/utils'
export interface RetargetOption {
id: string
label: string
detail?: string
current?: boolean
}
interface RetargetNoteDialogProps {
open: boolean
title: string
description: string
searchPlaceholder: string
emptyMessage: string
options: RetargetOption[]
onClose: () => void
onSelect: (id: string) => boolean | Promise<boolean>
testIdPrefix: string
}
function matchesQuery(option: RetargetOption, query: string): boolean {
const normalized = query.trim().toLowerCase()
if (!normalized) return true
return option.label.toLowerCase().includes(normalized)
|| option.detail?.toLowerCase().includes(normalized)
|| false
}
function initialHighlightIndex(options: RetargetOption[]): number {
if (options.length === 0) return -1
const currentIndex = options.findIndex((option) => option.current)
return currentIndex >= 0 ? currentIndex : 0
}
function nextHighlightIndex(current: number, total: number, direction: 'next' | 'previous'): number {
if (total === 0) return -1
if (current < 0) return direction === 'next' ? 0 : total - 1
return direction === 'next'
? (current + 1) % total
: (current - 1 + total) % total
}
export function RetargetNoteDialog({
open,
title,
description,
searchPlaceholder,
emptyMessage,
options,
onClose,
onSelect,
testIdPrefix,
}: RetargetNoteDialogProps) {
const [query, setQuery] = useState('')
const [highlightedIndex, setHighlightedIndex] = useState(-1)
const filteredOptions = useMemo(
() => options.filter((option) => matchesQuery(option, query)),
[options, query],
)
const effectiveHighlightedIndex = highlightedIndex >= 0 && highlightedIndex < filteredOptions.length
? highlightedIndex
: initialHighlightIndex(filteredOptions)
const resetDialogState = () => {
setQuery('')
setHighlightedIndex(-1)
}
const submitSelection = async (optionId: string) => {
const shouldClose = await onSelect(optionId)
if (!shouldClose) return
resetDialogState()
onClose()
}
const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'ArrowDown') {
event.preventDefault()
setHighlightedIndex((current) => nextHighlightIndex(current, filteredOptions.length, 'next'))
return
}
if (event.key === 'ArrowUp') {
event.preventDefault()
setHighlightedIndex((current) => nextHighlightIndex(current, filteredOptions.length, 'previous'))
return
}
if (event.key === 'Enter' && effectiveHighlightedIndex >= 0) {
event.preventDefault()
const highlightedOption = filteredOptions.at(effectiveHighlightedIndex)
if (highlightedOption) void submitSelection(highlightedOption.id)
}
}
return (
<Dialog
open={open}
onOpenChange={(nextOpen) => {
if (nextOpen) return
resetDialogState()
onClose()
}}
>
<DialogContent className="max-w-xl gap-3" showCloseButton={true}>
<DialogHeader className="gap-1">
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<Input
autoFocus
value={query}
onChange={(event) => setQuery(event.target.value)}
onKeyDown={handleSearchKeyDown}
placeholder={searchPlaceholder}
data-testid={`${testIdPrefix}-search`}
/>
<ScrollArea className="max-h-80 rounded-md border">
{filteredOptions.length === 0 ? (
<div className="px-4 py-6 text-sm text-muted-foreground" data-testid={`${testIdPrefix}-empty`}>
{emptyMessage}
</div>
) : (
<div className="p-1" data-testid={`${testIdPrefix}-options`}>
{filteredOptions.map((option, index) => (
<Button
key={option.id}
type="button"
variant="ghost"
className={cn(
'h-auto w-full justify-start rounded-md px-3 py-2 text-left',
effectiveHighlightedIndex === index && 'bg-accent text-accent-foreground',
)}
data-testid={`${testIdPrefix}-option:${option.id}`}
onMouseMove={() => setHighlightedIndex(index)}
onClick={() => { void submitSelection(option.id) }}
>
<div className="flex min-w-0 flex-1 items-start gap-2">
<span className="mt-0.5 shrink-0 text-muted-foreground">
{option.current ? <Check size={14} weight="bold" /> : <StackSimple size={14} />}
</span>
<span className="flex min-w-0 flex-1 flex-col">
<span className="truncate text-sm font-medium text-foreground">{option.label}</span>
{option.detail && (
<span className="truncate text-xs text-muted-foreground">{option.detail}</span>
)}
</span>
</div>
{option.current && (
<span className="shrink-0 text-xs font-medium text-muted-foreground">
Current
</span>
)}
</Button>
))}
</div>
)}
</ScrollArea>
</DialogContent>
</Dialog>
)
}