Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 0 additions & 6 deletions libs/@hashintel/ds-components/figma.config.json

This file was deleted.

4 changes: 1 addition & 3 deletions libs/@hashintel/ds-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"build:buildinfo": "panda ship --config panda.config.ts --outfile dist/panda.buildinfo.json",
"build:ladle": "ladle build",
"build:lib": "tsup --config tsup.config.ts",
"codemod:beta-fractal-pilots": "tsx scripts/migrate-beta-fractal-pilots.ts",
"codegen": "yarn run codegen:colors && yarn run codegen:tokens && yarn run codegen:panda",
"codegen:colors": "tsx scripts/generate-colors-radix.ts",
"codegen:panda": "panda codegen --clean",
Expand All @@ -73,14 +74,12 @@
"dependencies": {
"@ark-ui/react": "5.26.2",
"@hashintel/ds-helpers": "workspace:^",
"@hashintel/refractive": "workspace:^",
"@pandacss/dev": "1.4.3",
"@pandacss/preset-panda": "1.4.3",
"canvas": "3.2.0",
"motion": "12.23.24"
},
"devDependencies": {
"@figma/code-connect": "1.4.3",
"@fontsource-variable/geist-mono": "5.2.7",
"@fontsource-variable/inter": "5.2.8",
"@fontsource-variable/inter-tight": "5.2.7",
Expand Down Expand Up @@ -120,7 +119,6 @@
"peerDependencies": {
"@ark-ui/react": "^5.26.2",
"@hashintel/ds-helpers": "workspace:^",
"@hashintel/refractive": "workspace:^",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { describe, expect, it } from "vitest";

import {
getRecipeSymbols,
migrateComponentModule,
migrateRecipeModule,
rewriteRelativeSpecifiers,
} from "./migrate-beta-fractal-pilots";

describe("rewriteRelativeSpecifiers", () => {
it("rewrites story exports when a stories root file moves to src/beta", () => {
const sourceText = `export { App as basic } from "./basic.story";\n`;
const oldFilePath = "/repo/src/beta/text/text.stories.ts";
const newFilePath = "/repo/src/beta/text.stories.ts";
const moveMap = new Map<string, string>();

const nextSource = rewriteRelativeSpecifiers(
sourceText,
oldFilePath,
newFilePath,
moveMap,
);

expect(nextSource).toBe(
'export { App as basic } from "./text/basic.story";\n',
);
});

it("rewrites story imports when the component root file moves to src/beta", () => {
const sourceText = 'import { Text } from "./text";\n';
const oldFilePath = "/repo/src/beta/text/basic.story.tsx";
const newFilePath = oldFilePath;
const moveMap = new Map<string, string>([
["/repo/src/beta/text/text", "/repo/src/beta/text"],
]);

const nextSource = rewriteRelativeSpecifiers(
sourceText,
oldFilePath,
newFilePath,
moveMap,
);

expect(nextSource).toBe('import { Text } from "../text";\n');
});

it("preserves .recipe suffixes when a recipe root file moves to src/beta", () => {
const sourceText = 'import { textRecipe } from "./text.recipe";\n';
const oldFilePath = "/repo/src/beta/text/text.tsx";
const newFilePath = "/repo/src/beta/text.tsx";
const moveMap = new Map<string, string>([
["/repo/src/beta/text/text", "/repo/src/beta/text"],
["/repo/src/beta/text/text.recipe", "/repo/src/beta/text.recipe"],
]);

const nextSource = rewriteRelativeSpecifiers(
sourceText,
oldFilePath,
newFilePath,
moveMap,
);

expect(nextSource).toBe('import { textRecipe } from "./text.recipe";\n');
});
});

describe("migrateRecipeModule", () => {
it("converts defineRecipe modules to cva recipe modules", () => {
const sourceText = [
'import { defineRecipe } from "@pandacss/dev";',
"",
"export const text = defineRecipe({",
' className: "text",',
" variants: {},",
"});",
"",
].join("\n");

const nextSource = migrateRecipeModule(sourceText, "text", false);

expect(nextSource).toContain(
'import { cva, type RecipeVariantProps } from "@hashintel/ds-helpers/css";',
);
expect(nextSource).toContain(
"export const textRecipe = cva(textRecipeDefinition);",
);
expect(nextSource).toContain(
"export type TextRecipeProps = RecipeVariantProps<typeof textRecipe>;",
);
expect(nextSource).not.toContain("@ts-expect-error");
});

it("converts defineSlotRecipe modules to sva modules with a staged suppression", () => {
const sourceText = [
'import { tooltipAnatomy } from "@ark-ui/react/anatomy";',
'import { defineSlotRecipe } from "@pandacss/dev";',
"",
"export const tooltip = defineSlotRecipe({",
' className: "tooltip",',
" slots: tooltipAnatomy.keys(),",
" base: {},",
"});",
"",
].join("\n");

const nextSource = migrateRecipeModule(sourceText, "tooltip", true);

expect(nextSource).toContain(
'import { tooltipAnatomy } from "@ark-ui/react/anatomy";',
);
expect(nextSource).toContain(
'import { sva, type RecipeVariantProps } from "@hashintel/ds-helpers/css";',
);
expect(nextSource).toContain(
"// @ts-expect-error TODO(beta-graduation): invalid strict tokens remain in this beta recipe; remove before moving to src/components",
);
expect(nextSource).toContain(
"export const tooltipSlotRecipe = sva(tooltipSlotRecipeDefinition);",
);
expect(nextSource).toContain(
"export type TooltipSlotRecipeProps = RecipeVariantProps<typeof tooltipSlotRecipe>;",
);
});
});

describe("migrateComponentModule", () => {
it("switches generated recipe imports to local cva recipe imports", () => {
const sourceText = [
'import { ark } from "@ark-ui/react/factory";',
'import { styled } from "@hashintel/ds-helpers/jsx";',
'import { text } from "@hashintel/ds-helpers/recipes";',
"const Field = styled(ark.text, text);",
'export const Text = styled("p", text);',
"",
].join("\n");

const nextSource = migrateComponentModule(sourceText, "text");

expect(nextSource).toContain('import { textRecipe } from "./text.recipe";');
expect(nextSource).toContain("const Field = styled(ark.text, textRecipe);");
expect(nextSource).toContain(
'export const Text = styled("p", textRecipe);',
);
});

it("switches generated slot recipe imports to local slot recipe imports", () => {
const sourceText = [
'import { createStyleContext } from "@hashintel/ds-helpers/jsx";',
'import { tooltip } from "@hashintel/ds-helpers/recipes";',
"const { withRootProvider } = createStyleContext(tooltip);",
"",
].join("\n");

const nextSource = migrateComponentModule(sourceText, "tooltip");

expect(nextSource).toContain(
'import { tooltipSlotRecipe } from "./tooltip.recipe";',
);
expect(nextSource).toContain(
"const { withRootProvider } = createStyleContext(tooltipSlotRecipe);",
);
});
});

describe("getRecipeSymbols", () => {
it("derives explicit recipe names for cva and sva helpers", () => {
expect(getRecipeSymbols("tooltip", "cva")).toEqual({
definitionName: "tooltipRecipeDefinition",
exportName: "tooltipRecipe",
typeName: "TooltipRecipeProps",
});
expect(getRecipeSymbols("radio-card-group", "sva")).toEqual({
definitionName: "radioCardGroupSlotRecipeDefinition",
exportName: "radioCardGroupSlotRecipe",
typeName: "RadioCardGroupSlotRecipeProps",
});
});
});
Loading
Loading