From c5298a1be63c056d7d0ce357b9260607dc1dff73 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 14 Aug 2026 15:05:48 -0600 Subject: [PATCH 1/2] Fix catalog interactive data module --- API-FRICTION.md | 20 ++++++++++++++ packages/charts-demo-data/package.json | 3 ++- ...a.json => shadcn-area-interactive-data.ts} | 6 +++-- scripts/check-catalog-examples.mjs | 26 ++++++++++++++++--- 4 files changed, 49 insertions(+), 6 deletions(-) rename packages/charts-demo-data/src/{shadcn-area-interactive-data.json => shadcn-area-interactive-data.ts} (98%) diff --git a/API-FRICTION.md b/API-FRICTION.md index 1ac98088..030dcd3f 100644 --- a/API-FRICTION.md +++ b/API-FRICTION.md @@ -322,6 +322,7 @@ Each entry records: | F-283 | Interactive chart shells rendered inert controls | Application | resolved | | F-284 | Stagger timing required repeated callback arithmetic | API | resolved | | F-285 | Absolute catalog links lost their docs navigation tab | Documentation | resolved | +| F-286 | Browser imports treated raw JSON as a source module | Tooling | resolved | ## Findings @@ -8261,3 +8262,22 @@ Each entry records: on path inference for a non-docs route. - Verification: the local tanstack.com collection route renders the `shadcn/ui Charts` sidebar item as active under Examples. + +### F-286 — Browser imports treated raw JSON as a source module + +- Status: resolved +- Severity: high +- Owner: Tooling +- Observed in: opening the published ShadCN area-interactive catalog example +- Friction: the example imported an extensionless JSON fixture through the + catalog's revision-pinned esm.sh source prefix. esm.sh returned 404 because + raw JSON was not a resolvable JavaScript entry, leaving the sandbox root + empty while its status remained Running. The same fixture affected the area, + bar, and line interactive examples. +- Decision: expose the fixture as a TypeScript module and validate every + catalog demo-data import against a browser-loadable JavaScript or TypeScript + source module. JSON and declaration-only files no longer satisfy the public + example contract. +- Verification: the catalog contract validates all example imports, and the + revision-pinned esm.sh URL for the fixture returns a JavaScript module that + renders the production sandbox. diff --git a/packages/charts-demo-data/package.json b/packages/charts-demo-data/package.json index 04c805ce..30005610 100644 --- a/packages/charts-demo-data/package.json +++ b/packages/charts-demo-data/package.json @@ -110,7 +110,8 @@ "default": "./src/shadcn.ts" }, "./shadcn-area-interactive-data": { - "default": "./src/shadcn-area-interactive-data.json" + "types": "./src/shadcn-area-interactive-data.ts", + "default": "./src/shadcn-area-interactive-data.ts" }, "./survey": { "types": "./src/survey.d.ts", diff --git a/packages/charts-demo-data/src/shadcn-area-interactive-data.json b/packages/charts-demo-data/src/shadcn-area-interactive-data.ts similarity index 98% rename from packages/charts-demo-data/src/shadcn-area-interactive-data.json rename to packages/charts-demo-data/src/shadcn-area-interactive-data.ts index a522abc4..c60dfcf5 100644 --- a/packages/charts-demo-data/src/shadcn-area-interactive-data.json +++ b/packages/charts-demo-data/src/shadcn-area-interactive-data.ts @@ -1,4 +1,4 @@ -[ +const interactiveAreaData = [ { "date": "2024-04-01", "desktop": 222, @@ -454,4 +454,6 @@ "desktop": 446, "mobile": 400 } -] +] as const + +export default interactiveAreaData diff --git a/scripts/check-catalog-examples.mjs b/scripts/check-catalog-examples.mjs index 372d83f0..ba8ebc95 100644 --- a/scripts/check-catalog-examples.mjs +++ b/scripts/check-catalog-examples.mjs @@ -5,7 +5,10 @@ import ts from 'typescript' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') const casesRoot = path.join(root, 'benchmarks', 'conformance', 'cases') +const demoDataRoot = path.join(root, 'packages', 'charts-demo-data', 'src') const sourceExtensions = ['.ts', '.tsx', '.js', '.jsx', '.json', '.css'] +const browserModuleExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs'] +const demoDataPrefixes = ['@charts-poc/demo-data/', '@tanstack/charts-data/'] const forbiddenPublicNames = /\b(?:Conformance|tanstackCase|tanstackMount|reactMount|catalogPreviewDefinition)\b/ @@ -69,6 +72,23 @@ for (const directory of directories) { } for (const specifier of importSpecifiers(source, sourcePath)) { + const demoDataPrefix = demoDataPrefixes.find((prefix) => + specifier.startsWith(prefix), + ) + if (demoDataPrefix) { + const demoDataSpecifier = specifier.slice(demoDataPrefix.length) + const resolved = await resolveImport( + demoDataRoot, + `./${demoDataSpecifier}`, + browserModuleExtensions, + ) + if (!resolved) { + failures.push( + `${directory}/${relativePath}: demo-data import is not a browser module (${specifier})`, + ) + } + continue + } if (!specifier.startsWith('.')) continue const resolved = await resolveImport(path.dirname(sourcePath), specifier) if (!resolved) { @@ -190,13 +210,13 @@ function importSpecifiers(source, sourcePath) { return specifiers } -async function resolveImport(parent, specifier) { +async function resolveImport(parent, specifier, extensions = sourceExtensions) { const target = path.resolve(parent, specifier) const candidates = path.extname(target) ? [target] : [ - ...sourceExtensions.map((extension) => `${target}${extension}`), - ...sourceExtensions.map((extension) => + ...extensions.map((extension) => `${target}${extension}`), + ...extensions.map((extension) => path.join(target, `index${extension}`), ), ] From e4f7497b8e09a315ad9e72daa9f5f41e153323fd Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 14 Aug 2026 15:20:08 -0600 Subject: [PATCH 2/2] Refresh catalog preview provenance --- benchmarks/conformance/previews/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/conformance/previews/manifest.json b/benchmarks/conformance/previews/manifest.json index a025bfaf..9d507d04 100644 --- a/benchmarks/conformance/previews/manifest.json +++ b/benchmarks/conformance/previews/manifest.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "width": 288, "height": 192, - "sourceHash": "f6e45af3af0d44a468e0a33b1bda18065ae1fbd1e3a675778f6586ef426fcb9c", + "sourceHash": "c11021e138ff78d85026f99d2da56bf021ab198faa8db0a4844ea6b1028ae87f", "assets": [ { "id": "01-line-gaps",