diff --git a/packages/propel/.storybook/preview.tsx b/packages/propel/.storybook/preview.tsx index 92d1d76..9b3e4df 100644 --- a/packages/propel/.storybook/preview.tsx +++ b/packages/propel/.storybook/preview.tsx @@ -31,11 +31,9 @@ const withTheme: Decorator = (Story, context) => { const theme: Theme = THEMES.includes(candidate as Theme) ? (candidate as Theme) : TEST_THEME; useLayoutEffect(() => { const el = document.documentElement; - const previous = el.dataset.theme; el.dataset.theme = theme; return () => { - if (previous == null) delete el.dataset.theme; - else el.dataset.theme = previous; + delete el.dataset.theme; }; }, [theme]); return ; diff --git a/packages/propel/README.md b/packages/propel/README.md index 481f2a5..e7760c5 100644 --- a/packages/propel/README.md +++ b/packages/propel/README.md @@ -93,6 +93,17 @@ vp test # run tests folder; static wildcard `exports` (`./components/*`, `./hooks/*`) expose them as `@plane/propel/components/` / `hooks/` automatically — no `exports` edits and no barrel to maintain when you add a folder. +- **Component folders have a public boundary.** `index.tsx` only re-exports the + public API for that component folder. Public components and public child + components live in sibling kebab-case files (`button.tsx`, + `accordion-trigger.tsx`, `table-cell.tsx`). Do not use `Object.assign` or + namespace-style APIs such as `Foo.Bar`; export `FooBar` as its own component + instead. +- **Keep shared implementation private and accurately named.** Shared class + maps, CVA variants, and helpers should live in private sibling files such as + `*-styles.ts`, `*-shared.tsx`, or a real `*-context.tsx` when React context is + involved. Do not create public child files that only re-export from a + monolithic parent file. - `vp pack` needs at least one component or hook to build (a component library with zero entries has nothing to compile). - Compose classes with [`clsx`](https://github.com/lukeed/clsx) only — **do not diff --git a/packages/propel/package.json b/packages/propel/package.json index 39fc172..45fc789 100644 --- a/packages/propel/package.json +++ b/packages/propel/package.json @@ -30,6 +30,14 @@ "**/*.css" ], "exports": { + "./base/*": { + "types": "./dist/base/*/index.d.ts", + "import": "./dist/base/*/index.js" + }, + "./ui/*": { + "types": "./dist/ui/*/index.d.ts", + "import": "./dist/ui/*/index.js" + }, "./components/*": { "types": "./dist/components/*/index.d.ts", "import": "./dist/components/*/index.js" diff --git a/packages/propel/src/base/text-area/index.ts b/packages/propel/src/base/text-area/index.ts new file mode 100644 index 0000000..695e7b9 --- /dev/null +++ b/packages/propel/src/base/text-area/index.ts @@ -0,0 +1 @@ +export { BaseTextArea, type BaseTextAreaProps } from "./text-area"; diff --git a/packages/propel/src/base/text-area/text-area.tsx b/packages/propel/src/base/text-area/text-area.tsx new file mode 100644 index 0000000..64575ab --- /dev/null +++ b/packages/propel/src/base/text-area/text-area.tsx @@ -0,0 +1,32 @@ +import { Field as BaseField } from "@base-ui/react/field"; +import * as React from "react"; + +type BaseFieldControlProps = React.ComponentProps; + +type NativeTextAreaProps = Omit< + React.ComponentProps<"textarea">, + keyof BaseFieldControlProps | "children" | "className" | "style" +>; + +export type BaseTextAreaProps = BaseFieldControlProps & + NativeTextAreaProps & { + /** The default value of the textarea. Use when uncontrolled. */ + defaultValue?: React.ComponentProps<"textarea">["defaultValue"]; + /** The value of the textarea. Use when controlled. */ + value?: React.ComponentProps<"textarea">["value"]; + }; + +/** + * A native textarea element that automatically works with Field. Renders a `