From d88dfb6fc14649a06c7bcf048f22147b7fdab592 Mon Sep 17 00:00:00 2001 From: fat Date: Mon, 9 Mar 2026 20:08:47 -0700 Subject: [PATCH 1/7] fixed some stuff --- .../app/trees/docs/CoreTypes/constants.ts | 31 + apps/docs/app/trees/docs/Icons/content.mdx | 9 + .../docs/app/trees/docs/ReactAPI/constants.ts | 11 +- .../app/trees/docs/VanillaAPI/constants.ts | 11 +- .../tree-examples/CustomIconsSection.tsx | 74 +- .../tree-examples/seti-full.generated.ts | 2732 +++++++++++++++++ packages/trees/src/FileTree.ts | 7 + packages/trees/src/components/Root.tsx | 122 +- packages/trees/src/components/TreeItem.tsx | 12 +- .../test/ssr-declarative-shadow-dom.test.ts | 82 + 10 files changed, 3011 insertions(+), 80 deletions(-) create mode 100644 apps/docs/app/trees/tree-examples/seti-full.generated.ts diff --git a/apps/docs/app/trees/docs/CoreTypes/constants.ts b/apps/docs/app/trees/docs/CoreTypes/constants.ts index 29c2502cd..ec6ac3809 100644 --- a/apps/docs/app/trees/docs/CoreTypes/constants.ts +++ b/apps/docs/app/trees/docs/CoreTypes/constants.ts @@ -179,6 +179,27 @@ interface FileTreeIconConfig { | string | { name: string; width?: number; height?: number; viewBox?: string } >; + + // Remap file icons by exact basename (e.g. package.json, .gitignore). + byFileName?: Record< + string, + | string + | { name: string; width?: number; height?: number; viewBox?: string } + >; + + // Remap file icons by extension (e.g. ts, tsx, spec.ts). + byFileExtension?: Record< + string, + | string + | { name: string; width?: number; height?: number; viewBox?: string } + >; + + // Remap file icons when filename contains a substring (e.g. dockerfile). + byFileNameContains?: Record< + string, + | string + | { name: string; width?: number; height?: number; viewBox?: string } + >; } // Example: replace the file and chevron icons with custom symbols. @@ -202,6 +223,16 @@ const options = { 'file-tree-icon-file': 'my-file', 'file-tree-icon-chevron': { name: 'my-folder', width: 16, height: 16 }, }, + byFileExtension: { + ts: 'my-file', + tsx: 'my-file', + }, + byFileName: { + 'package.json': 'my-file', + }, + byFileNameContains: { + dockerfile: 'my-file', + }, }, };`, }, diff --git a/apps/docs/app/trees/docs/Icons/content.mdx b/apps/docs/app/trees/docs/Icons/content.mdx index 683e77b1e..b3ac452f2 100644 --- a/apps/docs/app/trees/docs/Icons/content.mdx +++ b/apps/docs/app/trees/docs/Icons/content.mdx @@ -8,10 +8,19 @@ own SVG symbols. Try the live demo at injected into the shadow DOM alongside the default sprite sheet. - `remap` — a map from a built-in icon name to either a replacement symbol id (string) or an object with `name`, optional `width`, `height`, and `viewBox`. +- `byFileName` — remap the file icon for exact basenames (for example + `package.json` or `.gitignore`). +- `byFileNameContains` — remap the file icon when a basename contains a pattern + (for example `dockerfile` or `license`). +- `byFileExtension` — remap the file icon by extension (for example `ts`, + `tsx`, `spec.ts`, or `json`). You can re-map any of the existing, default icons (listed below) by creating new SVG symbols that use the same IDs. +For file rows, icon resolution order is: +`byFileName` → `byFileNameContains` → `byFileExtension` (most specific suffix first) → `remap['file-tree-icon-file']` → default file icon. + | Icon ID | Description | | ------------------------ | ------------------------------------------------------------------- | | `file-tree-icon-chevron` | Indicates a directory can be opened. Automatically rotates on open. | diff --git a/apps/docs/app/trees/docs/ReactAPI/constants.ts b/apps/docs/app/trees/docs/ReactAPI/constants.ts index bc7821653..c97bfefce 100644 --- a/apps/docs/app/trees/docs/ReactAPI/constants.ts +++ b/apps/docs/app/trees/docs/ReactAPI/constants.ts @@ -100,8 +100,15 @@ export function CustomIconsTree() { id: 'custom-icons-tree', icons: { spriteSheet: customSpriteSheet, - remap: { - 'file-tree-icon-file': 'my-file', + byFileExtension: { + ts: 'my-file', + tsx: 'my-file', + }, + byFileName: { + 'package.json': 'my-file', + }, + byFileNameContains: { + dockerfile: 'my-file', }, }, }} diff --git a/apps/docs/app/trees/docs/VanillaAPI/constants.ts b/apps/docs/app/trees/docs/VanillaAPI/constants.ts index 36b2145a9..8c5fe365e 100644 --- a/apps/docs/app/trees/docs/VanillaAPI/constants.ts +++ b/apps/docs/app/trees/docs/VanillaAPI/constants.ts @@ -148,8 +148,15 @@ const fileTree = new FileTree({ ], icons: { spriteSheet: customSpriteSheet, - remap: { - 'file-tree-icon-file': 'my-file', + byFileExtension: { + ts: 'my-file', + tsx: 'my-file', + }, + byFileName: { + 'package.json': 'my-file', + }, + byFileNameContains: { + dockerfile: 'my-file', }, }, }); diff --git a/apps/docs/app/trees/tree-examples/CustomIconsSection.tsx b/apps/docs/app/trees/tree-examples/CustomIconsSection.tsx index 689be14ba..ce7076d8e 100644 --- a/apps/docs/app/trees/tree-examples/CustomIconsSection.tsx +++ b/apps/docs/app/trees/tree-examples/CustomIconsSection.tsx @@ -10,27 +10,16 @@ import { DEFAULT_FILE_TREE_PANEL_CLASS, DEFAULT_FILE_TREE_PANEL_STYLE, } from './demo-data'; +import { setiFullIconOverrides } from './seti-full.generated'; import { TreeExampleSection } from './TreeExampleSection'; -const customSpriteSheet = ` - -`; - const panelStyle = { ...DEFAULT_FILE_TREE_PANEL_STYLE, '--trees-search-bg-override': 'light-dark(#fff, oklch(14.5% 0 0))', } as CSSProperties; +const iconOverrides = setiFullIconOverrides; + const defaultPrerenderedHTML = preloadFileTree( { ...baseTreeOptions, @@ -42,31 +31,12 @@ const defaultPrerenderedHTML = preloadFileTree( } ).shadowHtml; -const remappedPrerenderedHTML = preloadFileTree( +const overridePrerenderedHTML = preloadFileTree( { ...baseTreeOptions, - id: 'custom-icons-remapped', + id: 'custom-icons-overrides', lockedPaths: ['package.json'], - icons: { - spriteSheet: customSpriteSheet, - remap: { - 'file-tree-icon-file': { - name: 'custom-file-icon', - width: 12, - height: 12, - }, - 'file-tree-icon-chevron': { - name: 'custom-folder-icon', - width: 12, - height: 12, - }, - 'file-tree-icon-lock': { - name: 'custom-lock-icon', - width: 12, - height: 12, - }, - }, - }, + icons: iconOverrides, }, { initialExpandedItems: ['src', 'src/components'], @@ -119,40 +89,22 @@ export function CustomIconsSection() { icon={} description={ <> - Pass a spriteSheet and remap via the{' '} - icons option. + Pass a spriteSheet, remap,{' '} + byFileExtension, byFileName, and{' '} + byFileNameContains. } > - Remapped + Overrides