Skip to content

Commit 7dad1bb

Browse files
authored
chore: 🤖 public api as exports source-of-truth (#845)
* fix: 🐛 conflict resolution * chore: 🤖 bump rc number * docs: 📝 build esm, how to use * chore: 🤖 ESM vite builder (wip) * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .tsx extension from import statements * fix: 🐛 remove .ts extension from import statements * fix: 🐛 remove .ts extension from import statements * chore: 🤖 add eslint to assess import extensions not required * chore: 🤖 format * chore: 🤖 temporary custom resolve tsconfig path * refactor: 💡 export from correct theme boundary * chore: 🤖 node externals in vite, remove alias * chore: 🤖 use relative paths * chore: 🤖 use externalize deps * chore: 🤖 for ESM compatibility, tweak/handle CJS components * chore: revert ts alias rewrite to relative * chore: lint do not allow barrel imports * chore: remove excludes from tsconfig * chore: set vite settings to preserve file struct in output * fix: solve import cycles * fix: solve import cycles in stories * fix: build amends * fix: add .js extension * chore: analyze and visualise bundle * chore: split ESM, CJS distribution * chore: format * fix: 🐛 lint code block * fix: 🐛 import Separator * chore: format * fix: 🐛 import Separator * chore: 🤖 add changeset * chore: 🤖 use 0.0.251-rc.62 * chore: 🤖 resolve conflict resolution, deleted files which were removed in main branch * chore: 🤖 resolve conflict resolution, middle truncator * chore: 🤖 resolve conflict resolution, missing container changes * refactor: 💡 FileMultiUpload to follow FileUpload due to middle truncator * fix: 🐛 prevent icon success pushed right * fix: 🐛 remove file size from multiple file upload * chore: 🤖 merge conflict amend for ButtonGroup * chore: 🤖 remove comment * refactor: 💡 reduce import path redundancy (WIP, pt1) * refactor: 💡 accordion as index * refactor: 💡 rename component by directory name to index * refactor: 💡 update import statements to prefer index * chore: 🤖 remove old indexes (this was a failed attempt, which imported the reduntant name) * fix: 🐛 import statements * fix: 🐛 import statements * fix: 🐛 import statements * fix: 🐛 icon names in types * chore: 🤖 add note * chore: 🤖 format * fix: 🐛 icon names location * fix: 🐛 icon names location * chore: 🤖 update changeset * refactor: 💡 use component level barrel, to allow devs see component name on editor * fix: 🐛 import statements * chore: 🤖 add eslint to prevent imports from index and request use of leafs when possible * fix: 🐛 dayjs version * fix: 🐛 merge from main,m incorrectly changed * chore: 🤖 prepare merge main * fix: 🐛 merge conflicts * refactor: 💡 further paths pass * chore: 🤖 add note * chore: 🤖 format * refactor: 💡 further paths pass for AutoComplete * fix: 🐛 merge conflict * refactor: 💡 further paths pass for Collapsible * chore: 🤖 init changeset * fix: 🐛 merge conflict * fix: 🐛 file extension * fix: 🐛 file extension * refactor: 💡 init GenericMenu structure * chore: 🤖 add generic menu test * chore: 🤖 add generic menu story * refactor: 💡 make components/Common to avoid loose files * refactor: 💡 move types * refactor: 💡 update path changes for common components * refactor: 💡 add Text index/exports * refactor: 💡 first pass, move types to *.types.ts * refactor: 💡 second pass, move types to *.types.ts * refactor: 💡 third pass, move types to *.types.ts * refactor: 💡 forth pass, move types to *.types.ts * refactor: 💡 fifth pass, move types to *.types.ts * refactor: 💡 export size color * refactor: 💡 move types for Avatar * fix: 🐛 imports * fix: 🐛 types * fix: 🐛 linter * fix: 🐛 test * chore: 🤖 add hmr benchmark * chore: 🤖 make component build name index to remove redundancy * chore: 🤖 generate exports, e.g. expose direct component imports and its types chore: 🤖 generate exports, e.g. expose direct component imports and its types * perf: ⚡ benchmark hmr deep nested components * chore: 🤖 link @clickhouse/click-ui to itself, required for benchmark * perf: ⚡ generate component exports, e.g. speedy component and type access * refactor: 💡 remove unused re-export files * chore: 🤖 update changeset * chore: 🤖 remove comments * fix: 🐛 TIAS circular dependencies, first 60 * refactor: 💡 make commons their own components * refactor: 💡 split common components * refactor: 💡 common components (styled components) exports * refactor: 💡 types in src/components/types * refactor: 💡 reconsile types * refactor: 💡 exports order * chore: 🤖 update exports * refactor: 💡 logo props * refactor: 💡 IconSize is an Icon type * refactor: 💡 rename icon types file * refactor: 💡 rename icon type import * refactor: 💡 move common icon SVG props * refactor: 💡 move common icon SVG element to icons * refactor: 💡 prefix types with type * chore: 🤖 format * fix: 🐛 redundancy in exports pathnames * refactor: 💡 text types in typography * refactor: 💡 cursor options type in panel * refactor: 💡 common types * chore: 🤖 add changeset * refactor: 💡 shared svg props * refactor: 💡 use shared types * refactor: 💡 remove re-export, prefer shared * refactor: 💡 shared types * refactor: 💡 rename icon size as shared asset size * chore: 🤖 merge conflict * fix: 🐛 resole theme conflicts * fix: 🐛 resolve theme types * refactor: 💡 theme * fix: 🐛 resolve merge conflicts due to circular deps * refactor: 💡 theme * refactor: 💡 remove hard typed theme * refactor: 💡 make theme and click ui provider as providers * refactor: 💡 export ClickUIProvider as named export * refactor: 💡 src/theme * refactor: 💡 theme files now follow the namespace pattern: * refactor: 💡 remove theme index * refactor: 💡 remove src/components/index.ts, prefer main src/index.ts as public api * refactor: 💡 prefer alias for internal inter component imports * refactor: 💡 main exports api * refactor: 💡 storybook * refactor: 💡 storybook * chore: 🤖 remove comment * refactor: 💡 use typescript api to get list of components from source of truth (main re-exports barrel) * chore: 🤖 update exports list * docs: 📝 public api exports management * chore: 🤖 add generate-exports generated component exports summary * chore: 🤖 add generate-exports script alias * chore: 🤖 show warning if package.json has changed, reminding user to commit them * chore: 🤖 add changeset * chore: 🤖 deleted file * fix: 🐛 types deps * refactor: 💡 move THEMES data structure from types * test: 💍 update test (due to merge issues) * chore: 🤖 the asset system has to be updated to reflect architecture decisions, since its automated, here done manual changes * chore: 🤖 merge from refactor/modular-file-architecture * fix: 🐛 error TS2724: './IconButton' has no exported member named 'IconButtonSize'. * chore: 🤖 add TODO * fix: 🐛 circular dep * chore: 🤖 resolve merge conflict missing type * chore: 🤖 remove deprecated * fix: 🐛 ContextMenu.types.ts: Added type?: 'default' | 'danger' to the exported ContextMenuItemProps interface and remove duplicate * refactor: 💡 move local type * refactor: 💡 move local type (missed track file) * refactor: 💡 changeset * refactor: 💡 move ContextMenu types * chore: 🤖 remove FlyoutHeaderProps and FlyoutFooterProps are each declared twice in the same file * refactor: 💡 Replaced stale types in Flyout.types.ts with the correct definitions from Flyout.tsx * fix: 🐛 typo, should be orientation * refactor: 💡 changeset * chore: 🤖 update changeset, include what changed * fix: 🐛 types * fix: 🐛 missing exports InitCUIThemeScript and InitCUIThemeScriptProps * fix: 🐛 merge conflicts, update changeset, remove orphans * fix: 🐛 remove unknown casting in themes in theme.core.ts * refactor: 💡 theme const and types * chore: 🤖 remove unwanted file * fix: 🐛 derived types from THEMES tricky as it can cause circular deps * refactor: 💡 capitalize theme name * chore: 🤖 add bug fix in changeset * chore: 🤖 remove unrelated * refactor: 💡 import path redundancy * chore: 🤖 generate:exports must run build first * docs: 📝 clarify source of truth * chore: 🤖 update exports * chore: 🤖 Changeset should enumerate removed paths: * fix: 🐛 off-by-one in summary log * docs: 📝 redundant build in docs
1 parent 02a4854 commit 7dad1bb

4 files changed

Lines changed: 100 additions & 6 deletions

File tree

.changeset/fiery-shirts-brush.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
'@clickhouse/click-ui': minor
3+
---
4+
5+
The team should have full control over the Public API to manage which resources are available for use in consumer applications. Previously, consumer applications had unrestricted access to internal resources, which is undesirable.
6+
7+
For example, third-party APIs like the primitive components provided by Radix UI were directly exposed, meaning that if those primitives were ever swapped out, any consumer applications depending on them would break due to tight coupling.
8+
9+
With these changes in place, core maintainers can now manage the Public API through a clear and friendlier interface.
10+
11+
## Removed Paths
12+
13+
The following subpath exports have been removed as they were intended as internal implementation details:
14+
15+
- `@clickhouse/click-ui/Collapsible`
16+
- `@clickhouse/click-ui/IconWrapper`
17+
- `@clickhouse/click-ui/MiddleTruncator`
18+
19+
If you were importing from these paths, please migrate to the public API exports from the main entry point (`@clickhouse/click-ui`).
20+
21+
## How to use?
22+
23+
The public API is controlled through the main barrel file at `src/index.ts`. This file serves as the single source of truth for all components, types, and utilities exported by the package.
24+
25+
> **Note:** The `generate:exports` script reads from the compiled output (`dist/esm/components/`) rather than parsing `src/index.ts` directly. Since `dist/` is derived from `src/index.ts` during the build process, the source file remains the ultimate source of truth.
26+
27+
Maintainers can add or remove components from the public API by updating the exports in this file. Each export should include both the component and its associated types to ensure consumers have full type support.
28+
29+
Here's an example of `src/index.ts`:
30+
31+
```ts
32+
// Adding a new component to the public API
33+
export { Button } from './components/Button';
34+
export type { ButtonProps } from './components/Button';
35+
36+
// Removing a component (simply delete)
37+
```
38+
39+
After, you must run the `generate:exports` to update the component-level exports in the package.json file.
40+
41+
Once complete, commit your changes.

.scripts/generate-exports

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ try {
4242

4343
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
4444

45-
console.log(`Generated exports for ${Object.keys(exports).length - 2} components`);
45+
console.log(`Generated exports for ${Object.keys(exports).length - 1} components`);
4646

4747
process.exit(0);
4848
} catch (err) {

README.md

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ You can find the official docs for the Click UI design system and component libr
3131
* [Distribution](#distribution)
3232
- [Build](#build)
3333
- [Use Click UI](#use-click-ui)
34-
- [Deep imports support](#deep-imports-support)
34+
- [Component-level imports](#component-level-imports)
35+
- [Public API](#public-api)
3536
- [Examples](#examples)
3637
* [Themes](#themes)
3738
- [Prevent theme flash](#prevent-theme-flash)
@@ -316,17 +317,68 @@ export default () => {
316317

317318
To learn more about individual components, visit [Click UI components](https://clickhouse.design/click-ui).
318319

319-
### Deep imports support
320+
### Component-level imports
320321

321-
Deep imports are supported, you can import directly from path.
322+
Components can be imported directly by name, providing a succinct import syntax.
323+
324+
```ts
325+
import { Button } from '@clickhouse/click-ui/Button';
326+
```
327+
328+
The exports map is auto-generated from the public API defined in `src/index.ts`, learn to manage by reading the [Public API](#public-api) section.
322329

323330
> [!WARNING]
324-
> At time of writing, there are components that consume from theme provider, which means that these will fail when unwrapped. This will change in future versions.
331+
> Some components depend on the theme provider. These will fail if used outside of `ClickUIProvider`. In next versions, this will change and consumer apps will have the ability to use them without the provider wrapping.
332+
333+
### Public API
334+
335+
The public API is controlled through the main barrel file at `src/index.ts`. This file serves as the single source of truth for all components, types, and utilities exported by the package.
336+
337+
> [!NOTE]
338+
> The `generate:exports` script reads from the compiled output (`dist/esm/components/`) rather than parsing `src/index.ts` directly. Since `dist/` is derived from `src/index.ts` during the build process, the source file remains the ultimate source of truth. The build step ensures the exports reflect exactly what was compiled from your source changes.
339+
340+
Maintainers can add or remove components from the public API by updating the exports in this file. Each export should include both the component and its associated types to ensure consumers have full type support.
341+
342+
Here's an example of `src/index.ts`:
325343

326344
```ts
327-
import { Button } from '@clickhouse/click-ui/Button';
345+
// Adding a new component to the public API
346+
export { Button } from './components/Button';
347+
export type { ButtonProps } from './components/Button';
348+
349+
// Removing a component (simply delete)
350+
```
351+
352+
After, you must run the `generate:exports` to update the component-level exports in the package.json file:
353+
354+
> [!IMPORTANT]
355+
> This script requires a prior build step, as it reads from `dist/esm/components/` (the compiled output). When executing generate:exports the build step is executed for you.
356+
357+
```sh
358+
yarn generate:exports
359+
```
360+
361+
Once complete, commit your changes.
362+
363+
#### Breaking change support
364+
365+
When introducing breaking changes or deprecating types, maintainers can provide retroactive support by creating custom type aliases. This allows consumers to migrate gradually while maintaining backwards compatibility.
366+
367+
```ts
368+
// Backwards compatibility: export legacy type name
369+
// that maps to the new type
370+
export type { NewComponentProps as LegacyComponentProps } from './components/NewComponent';
371+
372+
// Or create a custom type for transition periods
373+
export type DeprecatedProps = NewProps & {
374+
/** @deprecated Use `newProp` instead */
375+
oldProp?: string;
376+
};
328377
```
329378

379+
> [!NOTE]
380+
> When deprecating types or components, consider adding JSDoc `@deprecated` annotations to guide consumers towards the updated API. This provides clear migration paths and IDE warnings.
381+
330382
### Examples
331383

332384
Here's a quick copy and paste NextJS example with interactive components you can play:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330
"dev": "yarn storybook",
331331
"format": ".scripts/bash/format",
332332
"format:fix": ".scripts/bash/format --write",
333+
"generate:exports": "yarn build && .scripts/generate-exports",
333334
"generate:tokens": "node ./.scripts/js/generate-tokens.js && yarn format:fix src/theme/tokens/**/*.ts",
334335
"lint": "eslint src --report-unused-disable-directives",
335336
"lint:fix": "eslint src --report-unused-disable-directives --fix",

0 commit comments

Comments
 (0)