diff --git a/apps/docs/content/docs/components/actions/button.mdx b/apps/docs/content/docs/components/actions/button.mdx
index f8dd1b36..c7e0ec39 100644
--- a/apps/docs/content/docs/components/actions/button.mdx
+++ b/apps/docs/content/docs/components/actions/button.mdx
@@ -5,7 +5,7 @@ source: packages/@luke-ui/react/src/button
reactAria: https://react-spectrum.adobe.com/react-aria/Button.html
props:
- name: ButtonProps
- path: packages/@luke-ui/react/src/button/index.tsx
+ path: packages/@luke-ui/react/src/button/button.tsx
---
`Button` triggers an action, such as saving a form, opening a dialog, or deleting an item. Use
diff --git a/apps/docs/content/docs/components/actions/icon-button.mdx b/apps/docs/content/docs/components/actions/icon-button.mdx
index 1846f151..09fd65e4 100644
--- a/apps/docs/content/docs/components/actions/icon-button.mdx
+++ b/apps/docs/content/docs/components/actions/icon-button.mdx
@@ -5,7 +5,7 @@ source: packages/@luke-ui/react/src/icon-button
reactAria: https://react-spectrum.adobe.com/react-aria/Button.html
props:
- name: IconButtonProps
- path: packages/@luke-ui/react/src/icon-button/index.tsx
+ path: packages/@luke-ui/react/src/icon-button/icon-button.tsx
---
`IconButton` triggers a familiar compact action, such as closing a panel, deleting a row, or adding
diff --git a/apps/docs/content/docs/components/actions/link.mdx b/apps/docs/content/docs/components/actions/link.mdx
index 2703388e..45605c8d 100644
--- a/apps/docs/content/docs/components/actions/link.mdx
+++ b/apps/docs/content/docs/components/actions/link.mdx
@@ -5,7 +5,7 @@ source: packages/@luke-ui/react/src/link
reactAria: https://react-spectrum.adobe.com/react-aria/Link.html
props:
- name: LinkProps
- path: packages/@luke-ui/react/src/link/index.tsx
+ path: packages/@luke-ui/react/src/link/link.tsx
---
`Link` navigates to another URL or route. Use [`Button`](/components/actions/button) for an action
diff --git a/apps/docs/content/docs/components/feedback/loading-skeleton.mdx b/apps/docs/content/docs/components/feedback/loading-skeleton.mdx
index 5f03c6b1..9f806ca7 100644
--- a/apps/docs/content/docs/components/feedback/loading-skeleton.mdx
+++ b/apps/docs/content/docs/components/feedback/loading-skeleton.mdx
@@ -4,7 +4,7 @@ description: Replaces content with a placeholder that keeps its shape while it l
source: packages/@luke-ui/react/src/loading-skeleton
props:
- name: LoadingSkeletonProps
- path: packages/@luke-ui/react/src/loading-skeleton/index.tsx
+ path: packages/@luke-ui/react/src/loading-skeleton/loading-skeleton.tsx
---
Use `LoadingSkeleton` when content is loading but its layout is known. Wrap the content that will
diff --git a/apps/docs/content/docs/components/feedback/loading-spinner.mdx b/apps/docs/content/docs/components/feedback/loading-spinner.mdx
index 4caacfb4..c3976b9d 100644
--- a/apps/docs/content/docs/components/feedback/loading-spinner.mdx
+++ b/apps/docs/content/docs/components/feedback/loading-spinner.mdx
@@ -4,7 +4,7 @@ description: Animated indicator for work that is still in progress.
source: packages/@luke-ui/react/src/loading-spinner
props:
- name: LoadingSpinnerProps
- path: packages/@luke-ui/react/src/loading-spinner/index.tsx
+ path: packages/@luke-ui/react/src/loading-spinner/loading-spinner.tsx
---
`LoadingSpinner` shows that work is in progress. Use it on its own for a small loading region. Wrap
diff --git a/apps/docs/content/docs/components/forms/checkbox.mdx b/apps/docs/content/docs/components/forms/checkbox.mdx
index b15b0137..dc02a62c 100644
--- a/apps/docs/content/docs/components/forms/checkbox.mdx
+++ b/apps/docs/content/docs/components/forms/checkbox.mdx
@@ -6,7 +6,7 @@ source: packages/@luke-ui/react/src/checkbox
reactAria: https://react-spectrum.adobe.com/react-aria/Checkbox.html
props:
- name: CheckboxProps
- path: packages/@luke-ui/react/src/checkbox/index.tsx
+ path: packages/@luke-ui/react/src/checkbox/checkbox.tsx
---
Use `Checkbox` when someone can choose an option independently of nearby controls. Pass
diff --git a/apps/docs/content/docs/components/forms/combobox-field.mdx b/apps/docs/content/docs/components/forms/combobox-field.mdx
index 0f7a38aa..d18e5b76 100644
--- a/apps/docs/content/docs/components/forms/combobox-field.mdx
+++ b/apps/docs/content/docs/components/forms/combobox-field.mdx
@@ -5,7 +5,7 @@ source: packages/@luke-ui/react/src/combobox-field
reactAria: https://react-spectrum.adobe.com/react-aria/ComboBox.html
props:
- name: ComboboxFieldProps
- path: packages/@luke-ui/react/src/combobox-field/index.tsx
+ path: packages/@luke-ui/react/src/combobox-field/combobox-field.tsx
---
Use `ComboboxField` when someone needs to search for or choose one option from a list. It combines
diff --git a/apps/docs/content/docs/components/forms/text-field.mdx b/apps/docs/content/docs/components/forms/text-field.mdx
index 6d8e81b1..b411b09d 100644
--- a/apps/docs/content/docs/components/forms/text-field.mdx
+++ b/apps/docs/content/docs/components/forms/text-field.mdx
@@ -6,7 +6,7 @@ source: packages/@luke-ui/react/src/text-field
reactAria: https://react-spectrum.adobe.com/react-aria/TextField.html
props:
- name: TextFieldProps
- path: packages/@luke-ui/react/src/text-field/index.tsx
+ path: packages/@luke-ui/react/src/text-field/text-field.tsx
---
Use `TextField` to collect a single line of text. It combines an input with a label, description,
diff --git a/apps/docs/content/docs/components/layout/box.mdx b/apps/docs/content/docs/components/layout/box.mdx
index 19e3b04d..e90a02f9 100644
--- a/apps/docs/content/docs/components/layout/box.mdx
+++ b/apps/docs/content/docs/components/layout/box.mdx
@@ -4,7 +4,7 @@ description: A layout element with responsive Luke UI layout properties.
source: packages/@luke-ui/react/src/box
props:
- name: BoxProps
- path: packages/@luke-ui/react/src/box/index.tsx
+ path: packages/@luke-ui/react/src/box/box.tsx
---
`Box` accepts Luke UI layout properties and renders a `div` by default. It places content in a
diff --git a/apps/docs/content/docs/components/primitives/button.mdx b/apps/docs/content/docs/components/primitives/button.mdx
index b8dfaa88..aee51405 100644
--- a/apps/docs/content/docs/components/primitives/button.mdx
+++ b/apps/docs/content/docs/components/primitives/button.mdx
@@ -5,7 +5,7 @@ source: packages/@luke-ui/react/src/primitives/button
reactAria: https://react-spectrum.adobe.com/react-aria/Button.html
props:
- name: ButtonProps
- path: packages/@luke-ui/react/src/primitives/button/index.tsx
+ path: packages/@luke-ui/react/src/primitives/button/button.tsx
---
Use the button primitive to build a custom button pattern. It provides Luke UI button styles and
diff --git a/apps/docs/content/docs/components/primitives/checkbox.mdx b/apps/docs/content/docs/components/primitives/checkbox.mdx
index c3097e4f..e4620f2d 100644
--- a/apps/docs/content/docs/components/primitives/checkbox.mdx
+++ b/apps/docs/content/docs/components/primitives/checkbox.mdx
@@ -5,16 +5,16 @@ source: packages/@luke-ui/react/src/primitives/checkbox
reactAria: https://react-spectrum.adobe.com/react-aria/Checkbox.html
props:
- name: CheckboxProps
- path: packages/@luke-ui/react/src/primitives/checkbox/index.tsx
+ path: packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
heading: Checkbox
- name: CheckboxContentProps
- path: packages/@luke-ui/react/src/primitives/checkbox/index.tsx
+ path: packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
heading: CheckboxContent
- name: CheckboxControlProps
- path: packages/@luke-ui/react/src/primitives/checkbox/index.tsx
+ path: packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
heading: CheckboxControl
- name: CheckboxIndicatorProps
- path: packages/@luke-ui/react/src/primitives/checkbox/index.tsx
+ path: packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
heading: CheckboxIndicator
---
diff --git a/apps/docs/content/docs/components/primitives/field.mdx b/apps/docs/content/docs/components/primitives/field.mdx
index 8ff625a8..0c54accc 100644
--- a/apps/docs/content/docs/components/primitives/field.mdx
+++ b/apps/docs/content/docs/components/primitives/field.mdx
@@ -4,7 +4,7 @@ description: Shared label, description, and validation parts for custom fields.
source: packages/@luke-ui/react/src/primitives/field
props:
- name: FieldProps
- path: packages/@luke-ui/react/src/primitives/field/index.tsx
+ path: packages/@luke-ui/react/src/primitives/field/field.tsx
heading: Field
- name: FieldLabelProps
path: packages/@luke-ui/react/src/primitives/field/label.tsx
diff --git a/apps/docs/content/docs/components/primitives/input-group.mdx b/apps/docs/content/docs/components/primitives/input-group.mdx
index f82e70bb..f4f8bad7 100644
--- a/apps/docs/content/docs/components/primitives/input-group.mdx
+++ b/apps/docs/content/docs/components/primitives/input-group.mdx
@@ -4,16 +4,16 @@ description: Lower-level parts for composing a text input with content at either
source: packages/@luke-ui/react/src/primitives/input-group
props:
- name: InputGroupProps
- path: packages/@luke-ui/react/src/primitives/input-group/index.tsx
+ path: packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
heading: InputGroup
- name: InputGroupInputProps
- path: packages/@luke-ui/react/src/primitives/input-group/index.tsx
+ path: packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
heading: InputGroupInput
- name: InputGroupPrefixProps
- path: packages/@luke-ui/react/src/primitives/input-group/index.tsx
+ path: packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
heading: InputGroupPrefix
- name: InputGroupSuffixProps
- path: packages/@luke-ui/react/src/primitives/input-group/index.tsx
+ path: packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
heading: InputGroupSuffix
---
diff --git a/apps/docs/content/docs/components/primitives/visually-hidden.mdx b/apps/docs/content/docs/components/primitives/visually-hidden.mdx
index bf2311c5..8d77dcc3 100644
--- a/apps/docs/content/docs/components/primitives/visually-hidden.mdx
+++ b/apps/docs/content/docs/components/primitives/visually-hidden.mdx
@@ -4,7 +4,7 @@ description: Hide content visually and keep it available to assistive technology
source: packages/@luke-ui/react/src/visually-hidden
props:
- name: VisuallyHiddenProps
- path: packages/@luke-ui/react/src/visually-hidden/index.tsx
+ path: packages/@luke-ui/react/src/visually-hidden/visually-hidden.tsx
---
Use `VisuallyHidden` to hide content from sight. The content stays in the accessibility tree and the
diff --git a/apps/docs/content/docs/components/typography/blockquote.mdx b/apps/docs/content/docs/components/typography/blockquote.mdx
index 21e21ac5..fedd1b61 100644
--- a/apps/docs/content/docs/components/typography/blockquote.mdx
+++ b/apps/docs/content/docs/components/typography/blockquote.mdx
@@ -4,7 +4,7 @@ description: Block-level quotation from another source.
source: packages/@luke-ui/react/src/blockquote
props:
- name: BlockquoteProps
- path: packages/@luke-ui/react/src/blockquote/index.tsx
+ path: packages/@luke-ui/react/src/blockquote/blockquote.tsx
---
`Blockquote` quotes another source as a block. It renders a native `blockquote` element, which
diff --git a/apps/docs/content/docs/components/typography/code.mdx b/apps/docs/content/docs/components/typography/code.mdx
index db380841..1427f4e9 100644
--- a/apps/docs/content/docs/components/typography/code.mdx
+++ b/apps/docs/content/docs/components/typography/code.mdx
@@ -4,7 +4,7 @@ description: Marks text to signify a short fragment of computer code.
source: packages/@luke-ui/react/src/code
props:
- name: CodeProps
- path: packages/@luke-ui/react/src/code/index.tsx
+ path: packages/@luke-ui/react/src/code/code.tsx
---
`Code` marks a short fragment of computer code. It renders a native `code` element, which conveys
diff --git a/apps/docs/content/docs/components/typography/em.mdx b/apps/docs/content/docs/components/typography/em.mdx
index ed7f5e38..2c29a588 100644
--- a/apps/docs/content/docs/components/typography/em.mdx
+++ b/apps/docs/content/docs/components/typography/em.mdx
@@ -4,7 +4,7 @@ description: Marks text to stress emphasis.
source: packages/@luke-ui/react/src/em
props:
- name: EmProps
- path: packages/@luke-ui/react/src/em/index.tsx
+ path: packages/@luke-ui/react/src/em/em.tsx
---
`Em` stresses a word or phrase, changing how the sentence reads. It renders a native `em` element,
diff --git a/apps/docs/content/docs/components/typography/emoji.mdx b/apps/docs/content/docs/components/typography/emoji.mdx
index ff058da2..48df66bc 100644
--- a/apps/docs/content/docs/components/typography/emoji.mdx
+++ b/apps/docs/content/docs/components/typography/emoji.mdx
@@ -4,7 +4,7 @@ description: Emoji rendering with a reliable screen reader label.
source: packages/@luke-ui/react/src/emoji
props:
- name: EmojiProps
- path: packages/@luke-ui/react/src/emoji/index.tsx
+ path: packages/@luke-ui/react/src/emoji/emoji.tsx
---
`Emoji` renders an emoji with a reliable accessible name. It inherits its size from the surrounding
diff --git a/apps/docs/content/docs/components/typography/heading.mdx b/apps/docs/content/docs/components/typography/heading.mdx
index 1af2d2f8..be7b4da0 100644
--- a/apps/docs/content/docs/components/typography/heading.mdx
+++ b/apps/docs/content/docs/components/typography/heading.mdx
@@ -4,7 +4,7 @@ description: Semantic heading with automatic level management.
source: packages/@luke-ui/react/src/heading
props:
- name: HeadingProps
- path: packages/@luke-ui/react/src/heading/index.tsx
+ path: packages/@luke-ui/react/src/heading/heading.tsx
---
`Heading` renders a semantic section heading. It reads its level from `HeadingLevels` context. Set
diff --git a/apps/docs/content/docs/components/typography/kbd.mdx b/apps/docs/content/docs/components/typography/kbd.mdx
index 9621d611..f59cd580 100644
--- a/apps/docs/content/docs/components/typography/kbd.mdx
+++ b/apps/docs/content/docs/components/typography/kbd.mdx
@@ -4,7 +4,7 @@ description: Represents keyboard input or a hotkey.
source: packages/@luke-ui/react/src/kbd
props:
- name: KbdProps
- path: packages/@luke-ui/react/src/kbd/index.tsx
+ path: packages/@luke-ui/react/src/kbd/kbd.tsx
---
`Kbd` marks keyboard input, such as a shortcut or a key name. It renders a native `kbd` element,
diff --git a/apps/docs/content/docs/components/typography/numeral.mdx b/apps/docs/content/docs/components/typography/numeral.mdx
index c9bb9333..dbb6ad1a 100644
--- a/apps/docs/content/docs/components/typography/numeral.mdx
+++ b/apps/docs/content/docs/components/typography/numeral.mdx
@@ -4,7 +4,7 @@ description: Locale-aware number formatting powered by Intl.NumberFormat.
source: packages/@luke-ui/react/src/numeral
props:
- name: NumeralProps
- path: packages/@luke-ui/react/src/numeral/index.tsx
+ path: packages/@luke-ui/react/src/numeral/numeral.tsx
---
`Numeral` formats a number with `Intl.NumberFormat`. It reads the active locale from React Aria's
diff --git a/apps/docs/content/docs/components/typography/quote.mdx b/apps/docs/content/docs/components/typography/quote.mdx
index fb3f40b1..e66be4ab 100644
--- a/apps/docs/content/docs/components/typography/quote.mdx
+++ b/apps/docs/content/docs/components/typography/quote.mdx
@@ -4,7 +4,7 @@ description: Short inline quotation.
source: packages/@luke-ui/react/src/quote
props:
- name: QuoteProps
- path: packages/@luke-ui/react/src/quote/index.tsx
+ path: packages/@luke-ui/react/src/quote/quote.tsx
---
`Quote` marks a short quotation inside a sentence. It renders a native `q` element, which conveys
diff --git a/apps/docs/content/docs/components/typography/strong.mdx b/apps/docs/content/docs/components/typography/strong.mdx
index 7b25f1d3..5ba01efd 100644
--- a/apps/docs/content/docs/components/typography/strong.mdx
+++ b/apps/docs/content/docs/components/typography/strong.mdx
@@ -4,7 +4,7 @@ description: Marks text to signify strong importance.
source: packages/@luke-ui/react/src/strong
props:
- name: StrongProps
- path: packages/@luke-ui/react/src/strong/index.tsx
+ path: packages/@luke-ui/react/src/strong/strong.tsx
---
`Strong` marks text as important. It renders a native `strong` element, which conveys importance to
diff --git a/apps/docs/content/docs/components/typography/text.mdx b/apps/docs/content/docs/components/typography/text.mdx
index 3ca5f184..273d0f6c 100644
--- a/apps/docs/content/docs/components/typography/text.mdx
+++ b/apps/docs/content/docs/components/typography/text.mdx
@@ -4,7 +4,7 @@ description: Styled text with semantic typography styles and colour roles.
source: packages/@luke-ui/react/src/text
props:
- name: TextProps
- path: packages/@luke-ui/react/src/text/index.tsx
+ path: packages/@luke-ui/react/src/text/text.tsx
---
`Text` applies Luke UI typography without adding heading semantics. It needs a Luke UI theme root.
diff --git a/apps/docs/content/docs/components/visuals/icon.mdx b/apps/docs/content/docs/components/visuals/icon.mdx
index 1b3027c3..a61b38ab 100644
--- a/apps/docs/content/docs/components/visuals/icon.mdx
+++ b/apps/docs/content/docs/components/visuals/icon.mdx
@@ -4,7 +4,7 @@ description: SVG icon component backed by the generated spritesheet.
source: packages/@luke-ui/react/src/icon
props:
- name: IconProps
- path: packages/@luke-ui/react/src/icon/index.tsx
+ path: packages/@luke-ui/react/src/icon/icon.tsx
---
`Icon` renders a symbol from the generated Luke UI spritesheet. It needs an
diff --git a/apps/docs/source.config.ts b/apps/docs/source.config.ts
index 48010ccd..51f58447 100644
--- a/apps/docs/source.config.ts
+++ b/apps/docs/source.config.ts
@@ -28,7 +28,7 @@ export const docs = defineDocs({
heading: z.string().optional(),
/** Exported type name to render, e.g. `ButtonProps`. */
name: z.string(),
- /** Repo-relative path to the file exporting `name`, e.g. `packages/@luke-ui/react/src/button/index.tsx`. */
+ /** Repo-relative path to the file exporting `name`, e.g. `packages/@luke-ui/react/src/button/button.tsx`. */
path: z.string(),
}),
)
diff --git a/apps/docs/src/lib/generate-props-pages.test.ts b/apps/docs/src/lib/generate-props-pages.test.ts
index cb31554a..f64d6497 100644
--- a/apps/docs/src/lib/generate-props-pages.test.ts
+++ b/apps/docs/src/lib/generate-props-pages.test.ts
@@ -27,7 +27,7 @@ source: packages/@luke-ui/react/src/button
reactAria: https://react-spectrum.adobe.com/react-aria/Button.html
props:
- name: ButtonProps
- path: packages/@luke-ui/react/src/button/index.tsx
+ path: packages/@luke-ui/react/src/button/button.tsx
---
`);
@@ -42,7 +42,7 @@ reactAria: https://react-spectrum.adobe.com/react-aria/Button.html
## Props
-
+
`);
});
@@ -53,7 +53,7 @@ description: Shared label, description, and validation parts for custom fields.
source: packages/@luke-ui/react/src/primitives/field
props:
- name: FieldProps
- path: packages/@luke-ui/react/src/primitives/field/index.tsx
+ path: packages/@luke-ui/react/src/primitives/field/field.tsx
heading: Field
- name: FieldLabelProps
path: packages/@luke-ui/react/src/primitives/field/label.tsx
@@ -73,7 +73,7 @@ source: packages/@luke-ui/react/src/primitives/field
### Field
-
+
### FieldLabel
@@ -151,7 +151,7 @@ const SCRATCH_GUIDE = `---
title: Button
props:
- name: ButtonProps
- path: packages/@luke-ui/react/src/button/index.tsx
+ path: packages/@luke-ui/react/src/button/button.tsx
---
Guide body.
diff --git a/docs/COMPONENTS.md b/docs/COMPONENTS.md
index 9f62cc16..a747992b 100644
--- a/docs/COMPONENTS.md
+++ b/docs/COMPONENTS.md
@@ -31,6 +31,9 @@ pnpm run generate:component --args
Primitive scaffolding is not handled by the component generator.
+Public subpath `index.ts` files are export-only. A component's implementation lives in a named
+sibling file. Support modules and multi-part primitives each keep their own file.
+
The component creation rules live in `packages/turbo-generators/src/component-creation-plan.ts`.
Turbo and Plop are adapters that apply the plan. Keep new creation rules in the plan module so
dry-run tests can prove which files, exports, stories, docs, and checks a component needs.
diff --git a/docs/CONVENTIONS.md b/docs/CONVENTIONS.md
index 16f1d80a..1d32cf55 100644
--- a/docs/CONVENTIONS.md
+++ b/docs/CONVENTIONS.md
@@ -27,7 +27,7 @@ not as inline string constants.
## Naming
-- Components: `PascalCase`, for example `Button.tsx`.
+- Components: `PascalCase`, for example `IconButton`.
- Props: `PascalCaseProps`, for example `ButtonProps`.
- Files: `kebab-case`, for example `icon-button.tsx`.
- CSS: `*.css.ts`.
diff --git a/knip.config.ts b/knip.config.ts
index 98de3b8e..60a4ff45 100644
--- a/knip.config.ts
+++ b/knip.config.ts
@@ -24,12 +24,9 @@ export default {
'packages/@luke-ui/react': {
entry: [
'src/**/*.stories.tsx',
- 'src/**/index.tsx',
'src/**/index.ts',
'src/stylesheet.css.ts',
'src/styles/index.css.ts',
- 'src/theme/index.tsx',
- 'src/utils/index.ts',
'scripts/**/*.ts',
],
project: ['src/**/*.{ts,tsx}'],
diff --git a/packages/@luke-ui/react/AGENTS.md b/packages/@luke-ui/react/AGENTS.md
index a51d633b..2563b2da 100644
--- a/packages/@luke-ui/react/AGENTS.md
+++ b/packages/@luke-ui/react/AGENTS.md
@@ -21,7 +21,8 @@ A component directory contains:
- `[component].stories.tsx`: Storybook documentation and render/a11y fixtures
- `[component].browser.test.tsx`: component behaviour, conformance, and the integration tripwire
- `[component].visual.test.tsx`: visual regression captures when the component has a visual surface
-- `index.tsx`: component implementation
+- `.tsx`: component implementation
+- `index.ts`: export-only public subpath barrel
- `recipe.css.ts`: public recipe contract (scaffolded by the generator)
- `styles.css.ts`: private implementation styling when needed
diff --git a/packages/@luke-ui/react/package.json b/packages/@luke-ui/react/package.json
index 6178b1b3..0c2064b6 100644
--- a/packages/@luke-ui/react/package.json
+++ b/packages/@luke-ui/react/package.json
@@ -63,7 +63,7 @@
"build": "pnpm run build:tsdown",
"build:storybook": "storybook build",
"build:tsdown": "vp pack",
- "check:barrels": "unbarrelify --check --skip src/styles/index.ts --skip src/primitives/combobox/index.tsx",
+ "check:barrels": "unbarrelify --check --skip 'src/*/index.ts' --skip 'src/primitives/*/index.ts' --skip 'src/themes/*/index.ts'",
"check:format": "vp fmt . --check",
"check:lint": "vp lint . --type-aware",
"check:story-plays": "tsx scripts/check-story-plays.ts",
diff --git a/packages/@luke-ui/react/src/blockquote/index.tsx b/packages/@luke-ui/react/src/blockquote/blockquote.tsx
similarity index 79%
rename from packages/@luke-ui/react/src/blockquote/index.tsx
rename to packages/@luke-ui/react/src/blockquote/blockquote.tsx
index c5ba78a6..7a33c805 100644
--- a/packages/@luke-ui/react/src/blockquote/index.tsx
+++ b/packages/@luke-ui/react/src/blockquote/blockquote.tsx
@@ -1,12 +1,10 @@
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { blockquoteRecipe } from './recipe.css.js';
-export { type BlockquoteRecipeVariants, blockquoteRecipe } from './recipe.css.js';
-
type _BlockquoteOmit = DistributiveOmit;
interface _BlockquoteProps extends _BlockquoteOmit {}
diff --git a/packages/@luke-ui/react/src/blockquote/index.ts b/packages/@luke-ui/react/src/blockquote/index.ts
new file mode 100644
index 00000000..0ecc08ac
--- /dev/null
+++ b/packages/@luke-ui/react/src/blockquote/index.ts
@@ -0,0 +1,2 @@
+export { Blockquote, type BlockquoteProps } from './blockquote.js';
+export { type BlockquoteRecipeVariants, blockquoteRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/box/index.tsx b/packages/@luke-ui/react/src/box/box.tsx
similarity index 98%
rename from packages/@luke-ui/react/src/box/index.tsx
rename to packages/@luke-ui/react/src/box/box.tsx
index 2d9ee9b1..2b6cc959 100644
--- a/packages/@luke-ui/react/src/box/index.tsx
+++ b/packages/@luke-ui/react/src/box/box.tsx
@@ -3,7 +3,7 @@ import type { SprinklesProps } from '../styles/utilities.css.js';
import { createSprinkles } from '../styles/utilities.css.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { mergeProps } from '../utils/index.js';
+import { mergeProps } from '../utils/utils.js';
/** Props for `Box`. */
export type BoxProps = Prettify<_BoxElementProps | _BoxRenderProps>;
diff --git a/packages/@luke-ui/react/src/box/index.ts b/packages/@luke-ui/react/src/box/index.ts
new file mode 100644
index 00000000..4cc734ce
--- /dev/null
+++ b/packages/@luke-ui/react/src/box/index.ts
@@ -0,0 +1 @@
+export { Box, type BoxProps } from './box.js';
diff --git a/packages/@luke-ui/react/src/button/index.tsx b/packages/@luke-ui/react/src/button/button.tsx
similarity index 92%
rename from packages/@luke-ui/react/src/button/index.tsx
rename to packages/@luke-ui/react/src/button/button.tsx
index fe5bae8c..f67b6c0c 100644
--- a/packages/@luke-ui/react/src/button/index.tsx
+++ b/packages/@luke-ui/react/src/button/button.tsx
@@ -1,11 +1,9 @@
-export { type ButtonRecipeVariants, buttonRecipe } from '../primitives/button/recipe.css.js';
-
import type { JSX, ReactNode } from 'react';
-import { LoadingSpinner } from '../loading-spinner/index.js';
-import type { ButtonProps as PrimitiveButtonProps } from '../primitives/button/index.js';
-import { Button as PrimitiveButton } from '../primitives/button/index.js';
+import { LoadingSpinner } from '../loading-spinner/loading-spinner.js';
+import type { ButtonProps as PrimitiveButtonProps } from '../primitives/button/button.js';
+import { Button as PrimitiveButton } from '../primitives/button/button.js';
import type * as primitiveStyles from '../primitives/button/recipe.css.js';
-import { Text } from '../text/index.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { DocumentedPressProps } from '../types/documented-rac-props.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/button/index.ts b/packages/@luke-ui/react/src/button/index.ts
new file mode 100644
index 00000000..58bbed93
--- /dev/null
+++ b/packages/@luke-ui/react/src/button/index.ts
@@ -0,0 +1,2 @@
+export { type ButtonRecipeVariants, buttonRecipe } from '../primitives/button/recipe.css.js';
+export { Button, type ButtonProps } from './button.js';
diff --git a/packages/@luke-ui/react/src/checkbox/index.tsx b/packages/@luke-ui/react/src/checkbox/checkbox.tsx
similarity index 92%
rename from packages/@luke-ui/react/src/checkbox/index.tsx
rename to packages/@luke-ui/react/src/checkbox/checkbox.tsx
index 33b54358..e51667eb 100644
--- a/packages/@luke-ui/react/src/checkbox/index.tsx
+++ b/packages/@luke-ui/react/src/checkbox/checkbox.tsx
@@ -1,16 +1,15 @@
-export { checkboxRecipe, type CheckboxRecipeVariants } from '../primitives/checkbox/recipe.css.js';
import { useObjectRef } from '@react-aria/utils';
import type { JSX, ReactNode, Ref } from 'react';
import type { CheckboxFieldProps as RacCheckboxFieldProps } from 'react-aria-components/Checkbox';
-import type { CheckboxProps as PrimitiveCheckboxProps } from '../primitives/checkbox/index.js';
+import type { CheckboxProps as PrimitiveCheckboxProps } from '../primitives/checkbox/checkbox.js';
import {
CheckboxContent,
CheckboxControl,
CheckboxIndicator,
Checkbox as PrimitiveCheckbox,
-} from '../primitives/checkbox/index.js';
-import type { FieldErrorProps } from '../primitives/field/index.js';
-import { FieldDescription, FieldError } from '../primitives/field/index.js';
+} from '../primitives/checkbox/checkbox.js';
+import type { FieldErrorProps } from '../primitives/field/field.js';
+import { FieldDescription, FieldError } from '../primitives/field/field.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/checkbox/index.ts b/packages/@luke-ui/react/src/checkbox/index.ts
new file mode 100644
index 00000000..8550f049
--- /dev/null
+++ b/packages/@luke-ui/react/src/checkbox/index.ts
@@ -0,0 +1,2 @@
+export { type CheckboxRecipeVariants, checkboxRecipe } from '../primitives/checkbox/recipe.css.js';
+export { Checkbox, type CheckboxProps } from './checkbox.js';
diff --git a/packages/@luke-ui/react/src/code/index.tsx b/packages/@luke-ui/react/src/code/code.tsx
similarity index 84%
rename from packages/@luke-ui/react/src/code/index.tsx
rename to packages/@luke-ui/react/src/code/code.tsx
index 534bf976..0ae31a3a 100644
--- a/packages/@luke-ui/react/src/code/index.tsx
+++ b/packages/@luke-ui/react/src/code/code.tsx
@@ -1,7 +1,6 @@
-export { codeRecipe, type CodeRecipeVariants } from './recipe.css.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { codeRecipe } from './recipe.css.js';
type _CodeOmit = DistributiveOmit, never>;
diff --git a/packages/@luke-ui/react/src/code/index.ts b/packages/@luke-ui/react/src/code/index.ts
new file mode 100644
index 00000000..52c9543c
--- /dev/null
+++ b/packages/@luke-ui/react/src/code/index.ts
@@ -0,0 +1,2 @@
+export { Code, type CodeProps } from './code.js';
+export { type CodeRecipeVariants, codeRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/combobox-field/index.tsx b/packages/@luke-ui/react/src/combobox-field/combobox-field.tsx
similarity index 98%
rename from packages/@luke-ui/react/src/combobox-field/index.tsx
rename to packages/@luke-ui/react/src/combobox-field/combobox-field.tsx
index 2616a325..9b5011d1 100644
--- a/packages/@luke-ui/react/src/combobox-field/index.tsx
+++ b/packages/@luke-ui/react/src/combobox-field/combobox-field.tsx
@@ -12,8 +12,8 @@ import { useSlottedContext } from 'react-aria-components/slots';
import type { FieldSlotProps } from '../field/compose-field.js';
import { composeField } from '../field/compose-field.js';
import { IconSizeProvider } from '../icon/icon-size-context.js';
-import { Icon } from '../icon/index.js';
-import { LoadingSpinner } from '../loading-spinner/index.js';
+import { Icon } from '../icon/icon.js';
+import { LoadingSpinner } from '../loading-spinner/loading-spinner.js';
import { MobileOverlay } from '../overlays/mobile-overlay.js';
import { useIsMobileDevice } from '../overlays/use-is-mobile-device.js';
import { ComboboxClearButton } from '../primitives/combobox/clear-button.js';
@@ -30,11 +30,11 @@ import type { ComboboxRootProps, ComboboxSize } from '../primitives/combobox/roo
import { ComboboxRoot } from '../primitives/combobox/root.js';
import { comboboxRecipe } from '../primitives/combobox/styles.css.js';
import { ComboboxTrigger } from '../primitives/combobox/trigger.js';
-import { Field } from '../primitives/field/index.js';
+import { Field } from '../primitives/field/field.js';
import { COMBOBOX_ICON_SIZE } from '../sizing/combobox-sizing.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
type ComboboxLoadingState = 'error' | 'filtering' | 'idle' | 'loading' | 'loadingMore' | 'sorting';
diff --git a/packages/@luke-ui/react/src/combobox-field/index.ts b/packages/@luke-ui/react/src/combobox-field/index.ts
new file mode 100644
index 00000000..c66a32c6
--- /dev/null
+++ b/packages/@luke-ui/react/src/combobox-field/index.ts
@@ -0,0 +1 @@
+export { ComboboxField, type ComboboxFieldProps } from './combobox-field.js';
diff --git a/packages/@luke-ui/react/src/conformance/manifest.test.ts b/packages/@luke-ui/react/src/conformance/manifest.test.ts
index 6cb86eee..cd36948d 100644
--- a/packages/@luke-ui/react/src/conformance/manifest.test.ts
+++ b/packages/@luke-ui/react/src/conformance/manifest.test.ts
@@ -6,6 +6,14 @@ import { componentTestManifest } from './manifest.js';
const sourceRoot = resolve(import.meta.dirname, '..');
const packageRoot = resolve(sourceRoot, '..');
+// Public subpaths that are not normal component entrypoints, so they are exempt from the
+// conformance manifest. `theme` is deliberately absent from this set: it has its own manifest
+// entry (conformance tier `none`), so it must keep flowing through the normal check below. Keep
+// this list explicit and named rather than deriving it from the manifest itself, so a public
+// component entrypoint missing from the manifest fails this test instead of being silently
+// skipped.
+const NON_COMPONENT_EXPORTS = new Set(['styles', 'themes/paper', 'themes/tactile', 'utils']);
+
function isRecord(value: unknown): value is Record {
return typeof value === 'object' && value !== null;
}
@@ -22,7 +30,10 @@ function getExportPaths() {
for (const exportPath of Object.keys(packageJson.exports)) {
if (!exportPath.startsWith('./') || exportPath.includes('*')) continue;
const sourcePath = exportPath.slice(2);
- if (existsSync(resolve(sourceRoot, sourcePath, 'index.tsx'))) paths.push(sourcePath);
+ if (NON_COMPONENT_EXPORTS.has(sourcePath)) continue;
+ if (existsSync(resolve(sourceRoot, sourcePath, 'index.ts'))) {
+ paths.push(sourcePath);
+ }
}
return paths.sort();
@@ -34,7 +45,7 @@ test('covers every public component entrypoint exactly once', () => {
expect(new Set(paths).size).toBe(paths.length);
expect([...paths].sort()).toEqual(getExportPaths());
for (const path of paths) {
- expect(existsSync(resolve(sourceRoot, path, 'index.tsx'))).toBe(true);
+ expect(existsSync(resolve(sourceRoot, path, 'index.ts'))).toBe(true);
}
});
diff --git a/packages/@luke-ui/react/src/em/index.tsx b/packages/@luke-ui/react/src/em/em.tsx
similarity index 88%
rename from packages/@luke-ui/react/src/em/index.tsx
rename to packages/@luke-ui/react/src/em/em.tsx
index 9638393c..081c8e5f 100644
--- a/packages/@luke-ui/react/src/em/index.tsx
+++ b/packages/@luke-ui/react/src/em/em.tsx
@@ -1,8 +1,8 @@
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { em } from './styles.css.js';
interface EmStyleProps {
diff --git a/packages/@luke-ui/react/src/em/index.ts b/packages/@luke-ui/react/src/em/index.ts
new file mode 100644
index 00000000..8f6e5d70
--- /dev/null
+++ b/packages/@luke-ui/react/src/em/index.ts
@@ -0,0 +1 @@
+export { Em, type EmProps } from './em.js';
diff --git a/packages/@luke-ui/react/src/emoji/index.tsx b/packages/@luke-ui/react/src/emoji/emoji.tsx
similarity index 95%
rename from packages/@luke-ui/react/src/emoji/index.tsx
rename to packages/@luke-ui/react/src/emoji/emoji.tsx
index 98c75015..049564bb 100644
--- a/packages/@luke-ui/react/src/emoji/index.tsx
+++ b/packages/@luke-ui/react/src/emoji/emoji.tsx
@@ -1,4 +1,4 @@
-import { Text } from '../text/index.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/emoji/index.ts b/packages/@luke-ui/react/src/emoji/index.ts
new file mode 100644
index 00000000..4ceb9217
--- /dev/null
+++ b/packages/@luke-ui/react/src/emoji/index.ts
@@ -0,0 +1 @@
+export { Emoji, type EmojiProps } from './emoji.js';
diff --git a/packages/@luke-ui/react/src/heading/index.tsx b/packages/@luke-ui/react/src/heading/heading.tsx
similarity index 88%
rename from packages/@luke-ui/react/src/heading/index.tsx
rename to packages/@luke-ui/react/src/heading/heading.tsx
index 7d5455f1..9edb31d2 100644
--- a/packages/@luke-ui/react/src/heading/index.tsx
+++ b/packages/@luke-ui/react/src/heading/heading.tsx
@@ -1,14 +1,10 @@
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { Prettify } from '../types/prettify.js';
import type { HeadingLevel, HeadingLevelsProps } from './heading-context.js';
import { HeadingLevels, HeadingPresenceProvider } from './heading-context.js';
-export type {
- HeadingLevel,
- HeadingLevelsProps,
- HeadingLevelsRenderProps,
-} from './heading-context.js';
+export type { HeadingLevel } from './heading-context.js';
export { HeadingLevels, useHeadingLevel } from './heading-context.js';
/** Valid heading tag name for Luke UI headings. */
export type HeadingTag = `h${HeadingLevel}`;
diff --git a/packages/@luke-ui/react/src/heading/index.ts b/packages/@luke-ui/react/src/heading/index.ts
new file mode 100644
index 00000000..71885e3a
--- /dev/null
+++ b/packages/@luke-ui/react/src/heading/index.ts
@@ -0,0 +1,9 @@
+export {
+ Heading,
+ type HeadingLevel,
+ HeadingLevels,
+ type HeadingProps,
+ type HeadingTag,
+ useHeadingLevel,
+} from './heading.js';
+export type { HeadingLevelsProps, HeadingLevelsRenderProps } from './heading-context.js';
diff --git a/packages/@luke-ui/react/src/icon-button/index.tsx b/packages/@luke-ui/react/src/icon-button/icon-button.tsx
similarity index 84%
rename from packages/@luke-ui/react/src/icon-button/index.tsx
rename to packages/@luke-ui/react/src/icon-button/icon-button.tsx
index c7f307ed..9a78d046 100644
--- a/packages/@luke-ui/react/src/icon-button/index.tsx
+++ b/packages/@luke-ui/react/src/icon-button/icon-button.tsx
@@ -1,15 +1,13 @@
-export { type IconButtonRecipeVariants, iconButtonRecipe } from './recipe.css.js';
-
import type { JSX } from 'react';
import { composeRenderProps } from 'react-aria-components/composeRenderProps';
-import type { IconName } from '../icon/index.js';
-import { Icon } from '../icon/index.js';
-import type { ButtonProps as PrimitiveButtonProps } from '../primitives/button/index.js';
-import { Button } from '../primitives/button/index.js';
+import type { IconName } from '../icon/icon.js';
+import { Icon } from '../icon/icon.js';
+import type { ButtonProps as PrimitiveButtonProps } from '../primitives/button/button.js';
+import { Button } from '../primitives/button/button.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { DocumentedPressProps } from '../types/documented-rac-props.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import type { IconButtonRecipeVariants } from './recipe.css.js';
import { iconButtonIcon, iconButtonRecipe, iconButtonReset } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/icon-button/index.ts b/packages/@luke-ui/react/src/icon-button/index.ts
new file mode 100644
index 00000000..d51997aa
--- /dev/null
+++ b/packages/@luke-ui/react/src/icon-button/index.ts
@@ -0,0 +1,2 @@
+export { IconButton, type IconButtonProps } from './icon-button.js';
+export { type IconButtonRecipeVariants, iconButtonRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/icon-button/recipe.css.ts b/packages/@luke-ui/react/src/icon-button/recipe.css.ts
index bf706d8a..0b4a4ca2 100644
--- a/packages/@luke-ui/react/src/icon-button/recipe.css.ts
+++ b/packages/@luke-ui/react/src/icon-button/recipe.css.ts
@@ -17,12 +17,12 @@ export const iconButtonReset = styleInLayer('recipes', {
paddingInline: 0,
selectors: {
'&[data-pending="true"]::after': {
+ blockSize: vars.iconSize.xsmall,
borderColor: 'currentColor',
borderInlineEndColor: 'transparent',
borderRadius: vars.radius.full,
borderStyle: 'solid',
borderWidth: '2px',
- blockSize: vars.iconSize.xsmall,
content: '',
inlineSize: vars.iconSize.xsmall,
position: 'absolute',
diff --git a/packages/@luke-ui/react/src/icon/index.tsx b/packages/@luke-ui/react/src/icon/icon.tsx
similarity index 97%
rename from packages/@luke-ui/react/src/icon/index.tsx
rename to packages/@luke-ui/react/src/icon/icon.tsx
index 628e5307..6312515d 100644
--- a/packages/@luke-ui/react/src/icon/index.tsx
+++ b/packages/@luke-ui/react/src/icon/icon.tsx
@@ -1,12 +1,10 @@
-export { type IconRecipeVariants, iconRecipe } from './recipe.css.js';
-
import type { JSX, ReactNode, SVGAttributes } from 'react';
import { createContext, useContext } from 'react';
import { iconNames, iconViewBoxes } from '../../.generated/icon-data.js';
import { ICON_VIEWBOX } from '../sizing/icon-sizing.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { useIconSizeContext } from './icon-size-context.js';
import type { IconRecipeVariants } from './recipe.css.js';
import { iconRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/icon/index.ts b/packages/@luke-ui/react/src/icon/index.ts
new file mode 100644
index 00000000..2ffeb606
--- /dev/null
+++ b/packages/@luke-ui/react/src/icon/index.ts
@@ -0,0 +1,14 @@
+export {
+ type CreateIconOptions,
+ type CustomIconProps,
+ createIcon,
+ Icon,
+ type IconName,
+ type IconProps,
+ IconSizeProvider,
+ IconSpritesheetProvider,
+ type IconSpritesheetProviderProps,
+ iconNames,
+ iconViewBoxes,
+} from './icon.js';
+export { type IconRecipeVariants, iconRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/kbd/index.ts b/packages/@luke-ui/react/src/kbd/index.ts
new file mode 100644
index 00000000..f467185e
--- /dev/null
+++ b/packages/@luke-ui/react/src/kbd/index.ts
@@ -0,0 +1,2 @@
+export { Kbd, type KbdProps } from './kbd.js';
+export { type KbdRecipeVariants, kbdRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/kbd/index.tsx b/packages/@luke-ui/react/src/kbd/kbd.tsx
similarity index 84%
rename from packages/@luke-ui/react/src/kbd/index.tsx
rename to packages/@luke-ui/react/src/kbd/kbd.tsx
index 2c11bbd0..13367f27 100644
--- a/packages/@luke-ui/react/src/kbd/index.tsx
+++ b/packages/@luke-ui/react/src/kbd/kbd.tsx
@@ -1,8 +1,6 @@
-export { type KbdRecipeVariants, kbdRecipe } from './recipe.css.js';
-
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { kbdRecipe } from './recipe.css.js';
type _KbdOmit = DistributiveOmit, never>;
diff --git a/packages/@luke-ui/react/src/link/index.ts b/packages/@luke-ui/react/src/link/index.ts
new file mode 100644
index 00000000..fd4b1850
--- /dev/null
+++ b/packages/@luke-ui/react/src/link/index.ts
@@ -0,0 +1,2 @@
+export { Link, type LinkProps } from './link.js';
+export { type LinkRecipeVariants, linkRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/link/index.tsx b/packages/@luke-ui/react/src/link/link.tsx
similarity index 92%
rename from packages/@luke-ui/react/src/link/index.tsx
rename to packages/@luke-ui/react/src/link/link.tsx
index fb67b4ea..b7da3642 100644
--- a/packages/@luke-ui/react/src/link/index.tsx
+++ b/packages/@luke-ui/react/src/link/link.tsx
@@ -1,5 +1,3 @@
-export { type LinkRecipeVariants, linkRecipe } from './recipe.css.js';
-
import type { JSX } from 'react';
import type { LinkProps as RacLinkProps } from 'react-aria-components/Link';
import { Link as RacLink } from 'react-aria-components/Link';
@@ -7,7 +5,7 @@ import { composeRenderProps } from 'react-aria-components/composeRenderProps';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { DocumentedLinkProps } from '../types/documented-rac-props.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import type { LinkRecipeVariants } from './recipe.css.js';
import { linkRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/loading-skeleton/index.ts b/packages/@luke-ui/react/src/loading-skeleton/index.ts
new file mode 100644
index 00000000..d117ff93
--- /dev/null
+++ b/packages/@luke-ui/react/src/loading-skeleton/index.ts
@@ -0,0 +1,6 @@
+export {
+ LoadingSkeleton,
+ type LoadingSkeletonProps,
+ LoadingSkeletonProvider,
+ type LoadingSkeletonProviderProps,
+} from './loading-skeleton.js';
diff --git a/packages/@luke-ui/react/src/loading-skeleton/index.tsx b/packages/@luke-ui/react/src/loading-skeleton/loading-skeleton.tsx
similarity index 98%
rename from packages/@luke-ui/react/src/loading-skeleton/index.tsx
rename to packages/@luke-ui/react/src/loading-skeleton/loading-skeleton.tsx
index 3cd1209f..f677c2f0 100644
--- a/packages/@luke-ui/react/src/loading-skeleton/index.tsx
+++ b/packages/@luke-ui/react/src/loading-skeleton/loading-skeleton.tsx
@@ -3,7 +3,7 @@ import { createContext, isValidElement, useContext } from 'react';
import { vars } from '../theme/contract.css.js';
import type { Prettify } from '../types/prettify.js';
import { useSynchronizeAnimations } from '../use-synchronize-animations/use-synchronize-animations.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import {
loadingSkeletonClassName,
skeletonAnimationName,
diff --git a/packages/@luke-ui/react/src/loading-spinner/index.ts b/packages/@luke-ui/react/src/loading-spinner/index.ts
new file mode 100644
index 00000000..a754ab79
--- /dev/null
+++ b/packages/@luke-ui/react/src/loading-spinner/index.ts
@@ -0,0 +1,2 @@
+export { LoadingSpinner, type LoadingSpinnerProps } from './loading-spinner.js';
+export { type LoadingSpinnerRecipeVariants, loadingSpinnerRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/loading-spinner/index.tsx b/packages/@luke-ui/react/src/loading-spinner/loading-spinner.tsx
similarity index 95%
rename from packages/@luke-ui/react/src/loading-spinner/index.tsx
rename to packages/@luke-ui/react/src/loading-spinner/loading-spinner.tsx
index a15761a1..d984b399 100644
--- a/packages/@luke-ui/react/src/loading-spinner/index.tsx
+++ b/packages/@luke-ui/react/src/loading-spinner/loading-spinner.tsx
@@ -1,5 +1,3 @@
-export { type LoadingSpinnerRecipeVariants, loadingSpinnerRecipe } from './recipe.css.js';
-
import type { ComponentProps, ReactNode } from 'react';
import { useId } from 'react';
import { useIconSizeContext } from '../icon/icon-size-context.js';
@@ -12,7 +10,7 @@ import {
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
import { useSynchronizeAnimations } from '../use-synchronize-animations/use-synchronize-animations.js';
-import { VisuallyHidden } from '../visually-hidden/index.js';
+import { VisuallyHidden } from '../visually-hidden/visually-hidden.js';
import type { LoadingSpinnerRecipeVariants } from './recipe.css.js';
import { loadingSpinnerRecipe, rubberBandAnimationName, spinAnimationName } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/loading-spinner/recipe.css.ts b/packages/@luke-ui/react/src/loading-spinner/recipe.css.ts
index 47c33bd0..6a82ab24 100644
--- a/packages/@luke-ui/react/src/loading-spinner/recipe.css.ts
+++ b/packages/@luke-ui/react/src/loading-spinner/recipe.css.ts
@@ -33,25 +33,19 @@ export const rubberBandAnimationName = keyframes({
* `hiddenChildren`, and `spinnerOverlay`.
*/
const loadingSpinnerConfig = {
+ defaultVariants: {
+ size: 'medium',
+ },
slots: {
- root: {
- '@media': {
- '(forced-colors: active)': { animationName: 'none' },
- '(prefers-reduced-motion: reduce)': { animationName: 'none' },
- },
- animationDuration: rotationDuration,
- animationIterationCount: 'infinite',
- animationName: spinAnimationName,
- animationTimingFunction: 'linear',
- color: 'currentColor',
+ childrenWrapper: {
+ alignItems: 'center',
display: 'inline-flex',
- flexShrink: 0,
+ justifyContent: 'center',
+ position: 'relative',
},
- svg: {
- blockSize: '100%',
- display: 'block',
- inlineSize: '100%',
- transform: 'rotate(-90deg)',
+ hiddenChildren: {
+ display: 'contents',
+ visibility: 'hidden',
},
indicator: {
'@media': {
@@ -72,20 +66,26 @@ const loadingSpinnerConfig = {
animationTimingFunction: rubberBandEasing,
strokeDasharray: '100 100',
},
- childrenWrapper: {
- alignItems: 'center',
+ root: {
+ animationDuration: rotationDuration,
+ animationIterationCount: 'infinite',
+ animationName: spinAnimationName,
+ animationTimingFunction: 'linear',
+ color: 'currentColor',
display: 'inline-flex',
- justifyContent: 'center',
- position: 'relative',
- },
- hiddenChildren: {
- display: 'contents',
- visibility: 'hidden',
+ flexShrink: 0,
+ '@media': {
+ '(forced-colors: active)': { animationName: 'none' },
+ '(prefers-reduced-motion: reduce)': { animationName: 'none' },
+ },
},
spinnerOverlay: spinnerOverlayBase,
- },
- defaultVariants: {
- size: 'medium',
+ svg: {
+ blockSize: '100%',
+ display: 'block',
+ inlineSize: '100%',
+ transform: 'rotate(-90deg)',
+ },
},
variants: {
color: {
diff --git a/packages/@luke-ui/react/src/numeral/index.ts b/packages/@luke-ui/react/src/numeral/index.ts
new file mode 100644
index 00000000..25a589f3
--- /dev/null
+++ b/packages/@luke-ui/react/src/numeral/index.ts
@@ -0,0 +1,7 @@
+export {
+ Numeral,
+ type NumeralAbbreviation,
+ type NumeralFormat,
+ type NumeralPrecision,
+ type NumeralProps,
+} from './numeral.js';
diff --git a/packages/@luke-ui/react/src/numeral/index.tsx b/packages/@luke-ui/react/src/numeral/numeral.tsx
similarity index 98%
rename from packages/@luke-ui/react/src/numeral/index.tsx
rename to packages/@luke-ui/react/src/numeral/numeral.tsx
index 5505be0b..7c9daaa7 100644
--- a/packages/@luke-ui/react/src/numeral/index.tsx
+++ b/packages/@luke-ui/react/src/numeral/numeral.tsx
@@ -1,7 +1,7 @@
import { useLocale } from 'react-aria-components/I18nProvider';
import { useIsWithinHeading } from '../heading/heading-context.js';
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/numeral/numeral.visual.test.tsx b/packages/@luke-ui/react/src/numeral/numeral.visual.test.tsx
index bb967c54..3eda5620 100644
--- a/packages/@luke-ui/react/src/numeral/numeral.visual.test.tsx
+++ b/packages/@luke-ui/react/src/numeral/numeral.visual.test.tsx
@@ -27,8 +27,8 @@ for (const appearance of visualAppearances) {
diff --git a/packages/@luke-ui/react/src/overlays/mobile-overlay.tsx b/packages/@luke-ui/react/src/overlays/mobile-overlay.tsx
index 4da968ec..8de1967f 100644
--- a/packages/@luke-ui/react/src/overlays/mobile-overlay.tsx
+++ b/packages/@luke-ui/react/src/overlays/mobile-overlay.tsx
@@ -2,8 +2,8 @@ import type { JSX, ReactNode, Ref } from 'react';
import type { DialogProps } from 'react-aria-components/Dialog';
import { Dialog, OverlayTriggerStateContext } from 'react-aria-components/Dialog';
import { Modal, ModalOverlay } from 'react-aria-components/Modal';
-import { rootClassName } from '../theme/index.js';
-import { cx } from '../utils/index.js';
+import { rootClassName } from '../theme/theme.js';
+import { cx } from '../utils/utils.js';
import { mobileDialog, mobileModal, mobileOverlay } from './mobile-overlay.css.js';
interface MobileOverlayProps {
diff --git a/packages/@luke-ui/react/src/primitives/button/index.tsx b/packages/@luke-ui/react/src/primitives/button/button.tsx
similarity index 94%
rename from packages/@luke-ui/react/src/primitives/button/index.tsx
rename to packages/@luke-ui/react/src/primitives/button/button.tsx
index 5106bb92..8a26ce62 100644
--- a/packages/@luke-ui/react/src/primitives/button/index.tsx
+++ b/packages/@luke-ui/react/src/primitives/button/button.tsx
@@ -1,5 +1,3 @@
-export { type ButtonRecipeVariants, buttonRecipe } from './recipe.css.js';
-
import type { JSX } from 'react';
import type { ButtonProps as RacButtonProps } from 'react-aria-components/Button';
import { Button as RacButton } from 'react-aria-components/Button';
@@ -7,7 +5,7 @@ import { composeRenderProps } from 'react-aria-components/composeRenderProps';
import { IconSizeProvider } from '../../icon/icon-size-context.js';
import { BUTTON_ICON_SIZE } from '../../sizing/button-sizing.js';
import type { Prettify } from '../../types/prettify.js';
-import { cx } from '../../utils/index.js';
+import { cx } from '../../utils/utils.js';
import type { ButtonRecipeVariants } from './recipe.css.js';
import { buttonRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/primitives/button/index.ts b/packages/@luke-ui/react/src/primitives/button/index.ts
new file mode 100644
index 00000000..fcc5457f
--- /dev/null
+++ b/packages/@luke-ui/react/src/primitives/button/index.ts
@@ -0,0 +1,2 @@
+export { Button, type ButtonProps } from './button.js';
+export { type ButtonRecipeVariants, buttonRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/primitives/checkbox/index.tsx b/packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
similarity index 98%
rename from packages/@luke-ui/react/src/primitives/checkbox/index.tsx
rename to packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
index 6fe957d4..260b39be 100644
--- a/packages/@luke-ui/react/src/primitives/checkbox/index.tsx
+++ b/packages/@luke-ui/react/src/primitives/checkbox/checkbox.tsx
@@ -1,5 +1,3 @@
-export { type CheckboxRecipeVariants, checkboxRecipe } from './recipe.css.js';
-
import type { ComponentProps, JSX } from 'react';
import type {
CheckboxButtonProps as RacCheckboxButtonProps,
diff --git a/packages/@luke-ui/react/src/primitives/checkbox/index.ts b/packages/@luke-ui/react/src/primitives/checkbox/index.ts
new file mode 100644
index 00000000..ede3d0a0
--- /dev/null
+++ b/packages/@luke-ui/react/src/primitives/checkbox/index.ts
@@ -0,0 +1,11 @@
+export {
+ Checkbox,
+ CheckboxContent,
+ type CheckboxContentProps,
+ CheckboxControl,
+ type CheckboxControlProps,
+ CheckboxIndicator,
+ type CheckboxIndicatorProps,
+ type CheckboxProps,
+} from './checkbox.js';
+export { type CheckboxRecipeVariants, checkboxRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/primitives/combobox/index.tsx b/packages/@luke-ui/react/src/primitives/combobox/index.ts
similarity index 100%
rename from packages/@luke-ui/react/src/primitives/combobox/index.tsx
rename to packages/@luke-ui/react/src/primitives/combobox/index.ts
diff --git a/packages/@luke-ui/react/src/primitives/combobox/item.tsx b/packages/@luke-ui/react/src/primitives/combobox/item.tsx
index 1cfa581a..6eb0e73a 100644
--- a/packages/@luke-ui/react/src/primitives/combobox/item.tsx
+++ b/packages/@luke-ui/react/src/primitives/combobox/item.tsx
@@ -9,7 +9,7 @@ import {
} from 'react-aria-components/ComboBox';
import { composeRenderProps } from 'react-aria-components/composeRenderProps';
import { IconSizeProvider } from '../../icon/icon-size-context.js';
-import { Icon } from '../../icon/index.js';
+import { Icon } from '../../icon/icon.js';
import { COMBOBOX_CHECK_ICON_SIZE, COMBOBOX_ICON_SIZE } from '../../sizing/combobox-sizing.js';
import type { DistributiveOmit } from '../../types/distributive-omit.js';
import type { Prettify } from '../../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/primitives/combobox/popover.tsx b/packages/@luke-ui/react/src/primitives/combobox/popover.tsx
index 8f41ff54..5c9712f3 100644
--- a/packages/@luke-ui/react/src/primitives/combobox/popover.tsx
+++ b/packages/@luke-ui/react/src/primitives/combobox/popover.tsx
@@ -2,10 +2,10 @@ import type { JSX, Ref } from 'react';
import type { PopoverProps as RacPopoverProps } from 'react-aria-components/ComboBox';
import { Popover as RacPopover } from 'react-aria-components/ComboBox';
import { composeRenderProps } from 'react-aria-components/composeRenderProps';
-import { rootClassName } from '../../theme/index.js';
+import { rootClassName } from '../../theme/theme.js';
import type { DistributiveOmit } from '../../types/distributive-omit.js';
import type { Prettify } from '../../types/prettify.js';
-import { cx } from '../../utils/index.js';
+import { cx } from '../../utils/utils.js';
import { comboboxRecipe } from './styles.css.js';
type _ComboboxPopoverOmit = DistributiveOmit;
diff --git a/packages/@luke-ui/react/src/primitives/field/index.tsx b/packages/@luke-ui/react/src/primitives/field/field.tsx
similarity index 95%
rename from packages/@luke-ui/react/src/primitives/field/index.tsx
rename to packages/@luke-ui/react/src/primitives/field/field.tsx
index 14d880d8..6c400d4c 100644
--- a/packages/@luke-ui/react/src/primitives/field/index.tsx
+++ b/packages/@luke-ui/react/src/primitives/field/field.tsx
@@ -1,4 +1,3 @@
-export { fieldRecipe, type FieldRecipeVariants } from './recipe.css.js';
import type { ComponentProps, JSX, ReactNode } from 'react';
import type { FieldSlotProps } from '../../field/compose-field.js';
import type { DistributiveOmit } from '../../types/distributive-omit.js';
diff --git a/packages/@luke-ui/react/src/primitives/field/index.ts b/packages/@luke-ui/react/src/primitives/field/index.ts
new file mode 100644
index 00000000..9fd8ac64
--- /dev/null
+++ b/packages/@luke-ui/react/src/primitives/field/index.ts
@@ -0,0 +1,12 @@
+export {
+ Field,
+ FieldDescription,
+ type FieldDescriptionProps,
+ FieldError,
+ type FieldErrorProps,
+ FieldLabel,
+ type FieldLabelProps,
+ type FieldNecessityIndicator,
+ type FieldProps,
+} from './field.js';
+export { type FieldRecipeVariants, fieldRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/primitives/input-group/index.ts b/packages/@luke-ui/react/src/primitives/input-group/index.ts
new file mode 100644
index 00000000..3e9d7a59
--- /dev/null
+++ b/packages/@luke-ui/react/src/primitives/input-group/index.ts
@@ -0,0 +1,15 @@
+export {
+ InputGroup,
+ InputGroupInput,
+ type InputGroupInputProps,
+ InputGroupPrefix,
+ type InputGroupPrefixProps,
+ type InputGroupProps,
+ InputGroupSuffix,
+ type InputGroupSuffixProps,
+} from './input-group.js';
+export {
+ type InputGroupRecipeVariants,
+ type InputGroupSize,
+ inputGroupRecipe,
+} from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/primitives/input-group/index.tsx b/packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
similarity index 97%
rename from packages/@luke-ui/react/src/primitives/input-group/index.tsx
rename to packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
index 1b34f949..4bc48117 100644
--- a/packages/@luke-ui/react/src/primitives/input-group/index.tsx
+++ b/packages/@luke-ui/react/src/primitives/input-group/input-group.tsx
@@ -1,9 +1,3 @@
-export {
- type InputGroupRecipeVariants,
- type InputGroupSize,
- inputGroupRecipe,
-} from './recipe.css.js';
-
import type { ComponentProps, JSX, Ref } from 'react';
import { createContext, use } from 'react';
import type { GroupProps as RacGroupProps } from 'react-aria-components/Group';
@@ -12,7 +6,7 @@ import type { InputProps as RacInputProps } from 'react-aria-components/Input';
import { Input as RacInput } from 'react-aria-components/Input';
import { composeRenderProps } from 'react-aria-components/composeRenderProps';
import { IconSizeProvider } from '../../icon/icon-size-context.js';
-import { Icon } from '../../icon/index.js';
+import { Icon } from '../../icon/icon.js';
import { INPUT_GROUP_ICON_SIZE } from '../../sizing/input-group-sizing.js';
import type { DistributiveOmit } from '../../types/distributive-omit.js';
import type { Prettify } from '../../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/quote/index.ts b/packages/@luke-ui/react/src/quote/index.ts
new file mode 100644
index 00000000..99f84939
--- /dev/null
+++ b/packages/@luke-ui/react/src/quote/index.ts
@@ -0,0 +1 @@
+export { Quote, type QuoteProps } from './quote.js';
diff --git a/packages/@luke-ui/react/src/quote/index.tsx b/packages/@luke-ui/react/src/quote/quote.tsx
similarity index 91%
rename from packages/@luke-ui/react/src/quote/index.tsx
rename to packages/@luke-ui/react/src/quote/quote.tsx
index 0ef5883a..e00f579d 100644
--- a/packages/@luke-ui/react/src/quote/index.tsx
+++ b/packages/@luke-ui/react/src/quote/quote.tsx
@@ -1,5 +1,5 @@
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/strong/index.ts b/packages/@luke-ui/react/src/strong/index.ts
new file mode 100644
index 00000000..fa0dee63
--- /dev/null
+++ b/packages/@luke-ui/react/src/strong/index.ts
@@ -0,0 +1 @@
+export { Strong, type StrongProps } from './strong.js';
diff --git a/packages/@luke-ui/react/src/strong/index.tsx b/packages/@luke-ui/react/src/strong/strong.tsx
similarity index 89%
rename from packages/@luke-ui/react/src/strong/index.tsx
rename to packages/@luke-ui/react/src/strong/strong.tsx
index c29e99ee..0381f6c7 100644
--- a/packages/@luke-ui/react/src/strong/index.tsx
+++ b/packages/@luke-ui/react/src/strong/strong.tsx
@@ -1,8 +1,8 @@
-import type { TextProps } from '../text/index.js';
-import { Text } from '../text/index.js';
+import type { TextProps } from '../text/text.js';
+import { Text } from '../text/text.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { strong } from './styles.css.js';
interface StrongStyleProps {
diff --git a/packages/@luke-ui/react/src/styles/recipe.ts b/packages/@luke-ui/react/src/styles/recipe.ts
index 3dafa4d6..1745d566 100644
--- a/packages/@luke-ui/react/src/styles/recipe.ts
+++ b/packages/@luke-ui/react/src/styles/recipe.ts
@@ -2,7 +2,7 @@ import type { StyleRule } from '@vanilla-extract/css';
import { addFunctionSerializer } from '@vanilla-extract/css/functionSerializer';
import { recipe as vanillaRecipe } from '@vanilla-extract/recipes';
import type { DistributiveOmit } from '../types/distributive-omit.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
/**
* `recipe()` styling helper for Vanilla Extract.
diff --git a/packages/@luke-ui/react/src/text-field/index.ts b/packages/@luke-ui/react/src/text-field/index.ts
new file mode 100644
index 00000000..80e7dede
--- /dev/null
+++ b/packages/@luke-ui/react/src/text-field/index.ts
@@ -0,0 +1 @@
+export { TextField, type TextFieldProps } from './text-field.js';
diff --git a/packages/@luke-ui/react/src/text-field/index.tsx b/packages/@luke-ui/react/src/text-field/text-field.tsx
similarity index 92%
rename from packages/@luke-ui/react/src/text-field/index.tsx
rename to packages/@luke-ui/react/src/text-field/text-field.tsx
index a695dc86..6e92a926 100644
--- a/packages/@luke-ui/react/src/text-field/index.tsx
+++ b/packages/@luke-ui/react/src/text-field/text-field.tsx
@@ -6,14 +6,14 @@ import type {
import { TextField as RacTextField } from 'react-aria-components/TextField';
import type { FieldSlotProps } from '../field/compose-field.js';
import { composeField } from '../field/compose-field.js';
-import { Field } from '../primitives/field/index.js';
-import type { InputGroupSize } from '../primitives/input-group/index.js';
+import { Field } from '../primitives/field/field.js';
import {
InputGroup,
InputGroupInput,
InputGroupPrefix,
InputGroupSuffix,
-} from '../primitives/input-group/index.js';
+} from '../primitives/input-group/input-group.js';
+import type { InputGroupSize } from '../primitives/input-group/recipe.css.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { DocumentedInputProps } from '../types/documented-rac-props.js';
import type { Prettify } from '../types/prettify.js';
diff --git a/packages/@luke-ui/react/src/text/index.ts b/packages/@luke-ui/react/src/text/index.ts
new file mode 100644
index 00000000..108b0153
--- /dev/null
+++ b/packages/@luke-ui/react/src/text/index.ts
@@ -0,0 +1,2 @@
+export { type TextRecipeVariants, textRecipe } from './recipe.css.js';
+export { Text, type TextProps } from './text.js';
diff --git a/packages/@luke-ui/react/src/text/index.tsx b/packages/@luke-ui/react/src/text/text.tsx
similarity index 97%
rename from packages/@luke-ui/react/src/text/index.tsx
rename to packages/@luke-ui/react/src/text/text.tsx
index 62be8e2f..1b92b00f 100644
--- a/packages/@luke-ui/react/src/text/index.tsx
+++ b/packages/@luke-ui/react/src/text/text.tsx
@@ -1,10 +1,8 @@
-export { type TextRecipeVariants, textRecipe } from './recipe.css.js';
-
import { Text as RacText } from 'react-aria-components/Text';
import { typeStyleWeightRole } from '../theme/contract.js';
import type { DistributiveOmit } from '../types/distributive-omit.js';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import type { TextRecipeVariants } from './recipe.css.js';
import { textRecipe } from './recipe.css.js';
diff --git a/packages/@luke-ui/react/src/theme/index.ts b/packages/@luke-ui/react/src/theme/index.ts
new file mode 100644
index 00000000..b2087744
--- /dev/null
+++ b/packages/@luke-ui/react/src/theme/index.ts
@@ -0,0 +1,16 @@
+export { ThemeContrastError, ThemeGenerationError } from './build-theme.js';
+export type { ThemeContrastFailure, ThemeInheritance } from './build-theme.js';
+export { vars } from './contract.css.js';
+export { spaceScale, typeStyles } from './contract.js';
+export type { FontWeightRole, SpaceStep, TypeStyle } from './contract.js';
+export { defaultControlFinish, defaultDepth, defaultScrim, defineTheme } from './define-theme.js';
+export type {
+ ColorInput,
+ ControlFinish,
+ DepthLadder,
+ ExtendingThemeInput,
+ ThemeInput,
+} from './define-theme.js';
+export { deriveConcentricRadius, deriveNestedRadius } from './foundation.js';
+export { getThemeClassName } from './theme-class-name.js';
+export { rootClassName } from './theme.js';
diff --git a/packages/@luke-ui/react/src/theme/index.tsx b/packages/@luke-ui/react/src/theme/index.tsx
deleted file mode 100644
index b05c9eb4..00000000
--- a/packages/@luke-ui/react/src/theme/index.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { lukeUiClassNames } from '../styles/class-names.js';
-import { cx } from '../utils/index.js';
-
-/**
- * Applies the descendant CSS reset and the base Luke UI typography and theme layer. It carries no
- * theme identity of its own. Apply it to ``, ``, an app shell, or any element you
- * already own.
- */
-export const rootClassName = cx(lukeUiClassNames.themeRoot, lukeUiClassNames.resetRoot);
-
-/**
- * Typed access to the semantic theme custom properties. Each path resolves to a stable global
- * `--luke-*` variable reference, for example `vars.color.background.danger.solid.hover`.
- */
-export { vars } from './contract.css.js';
-
-/** The fixed spacing steps shared by the built-in themes. */
-export { spaceScale } from './contract.js';
-export type { SpaceStep } from './contract.js';
-
-/** Public semantic type style keys in ascending visual size. */
-export { typeStyles } from './contract.js';
-
-/** A public semantic type style key. */
-export type { TypeStyle } from './contract.js';
-
-/** Theme font-weight role keys used by typography defaults and weight overrides. */
-export type { FontWeightRole } from './contract.js';
-
-/**
- * `ThemeContrastError` is thrown by `defineTheme` when a hard-gated pair misses WCAG 2.2 AA: 4.5:1
- * for text/on-solid pairs, 3:1 for the focus ring and `border.control`. The six semantic
- * `border.` pairs are measured but advisory only and cannot trigger this error. It carries
- * every failing mode-and-pair in its `failures` array. For a theme built with `extends`, it also
- * carries `inheritance`, naming the chain of themes and which colours came from a base.
- * `ThemeGenerationError` is thrown when a role that must guarantee on-solid contrast (an
- * inaccessible explicit per-mode accent, for example) cannot reach an accessible solid. It names the
- * failing `role` and `mode`.
- */
-export { ThemeContrastError, ThemeGenerationError } from './build-theme.js';
-
-/** One WCAG contrast failure recorded on a {@link ThemeContrastError}. */
-export type { ThemeContrastFailure } from './build-theme.js';
-
-/** The colour provenance a `ThemeContrastError` carries for a theme built with `extends`. */
-export type { ThemeInheritance } from './build-theme.js';
-
-/**
- * `defineTheme(input)` is the curated authoring entry point: it normalises a small {@link ThemeInput}
- * (accent + neutral character, with everything else defaulting) into the per-mode foundation and
- * compiles it through `buildTheme`. It adapts single-value accents and neutrals per mode, generates
- * the radius scale, and merges optional materials over curated defaults. It also accepts an
- * {@link ExtendingThemeInput} and resolves its `extends` chain first. It throws the same
- * {@link ThemeContrastError} and {@link ThemeGenerationError} as `buildTheme`.
- */
-export { defineTheme } from './define-theme.js';
-
-/** The curated `defineTheme` authoring input plus its colour and material building blocks. */
-export type {
- ColorInput,
- ControlFinish,
- DepthLadder,
- ExtendingThemeInput,
- ThemeInput,
-} from './define-theme.js';
-
-/** Curated defaults `defineTheme` applies for omitted materials and scrim. */
-export { defaultControlFinish, defaultDepth, defaultScrim } from './define-theme.js';
-
-/**
- * `getThemeClassName(name)` returns a theme's identity class, `luke-ui-theme-${name}`. Pass the same
- * `name` the theme's {@link ThemeInput} declares. Apply the result to the theme root when one
- * document loads more than one theme stylesheet, so the explicit identity outranks another theme's
- * `:root` fallback. It throws when the name is not the kebab-case `defineTheme` requires.
- */
-export { getThemeClassName } from './theme-class-name.js';
-
-/** Derives a concentric outer corner from an inner radius plus the intervening gap. */
-export { deriveConcentricRadius } from './foundation.js';
-
-/** Derives a concentric inner corner from an outer radius plus the intervening gap. */
-export { deriveNestedRadius } from './foundation.js';
diff --git a/packages/@luke-ui/react/src/theme/theme.ts b/packages/@luke-ui/react/src/theme/theme.ts
new file mode 100644
index 00000000..0177dead
--- /dev/null
+++ b/packages/@luke-ui/react/src/theme/theme.ts
@@ -0,0 +1,9 @@
+import { lukeUiClassNames } from '../styles/class-names.js';
+import { cx } from '../utils/utils.js';
+
+/**
+ * Applies the descendant CSS reset and the base Luke UI typography and theme layer. It carries no
+ * theme identity of its own. Apply it to ``, ``, an app shell, or any element you
+ * already own.
+ */
+export const rootClassName = cx(lukeUiClassNames.themeRoot, lukeUiClassNames.resetRoot);
diff --git a/packages/@luke-ui/react/src/themes/paper/index.ts b/packages/@luke-ui/react/src/themes/paper/index.ts
index fe570bcc..1f8bf36b 100644
--- a/packages/@luke-ui/react/src/themes/paper/index.ts
+++ b/packages/@luke-ui/react/src/themes/paper/index.ts
@@ -1,10 +1,2 @@
-import type { ThemeInput } from '../../theme/define-theme.js';
-import { paperTheme } from '../../theme/foundations/paper.js';
-
+export { theme } from './theme.js';
export { themeClassName } from './theme-class-name.js';
-
-/**
- * Paper's `defineTheme` input, the materially minimal bundled theme: a flat, hairline-bordered
- * look with a blue accent. Set it as `extends` on your own input to start from Paper.
- */
-export const theme: ThemeInput = paperTheme;
diff --git a/packages/@luke-ui/react/src/themes/paper/theme.ts b/packages/@luke-ui/react/src/themes/paper/theme.ts
new file mode 100644
index 00000000..20b2a2a6
--- /dev/null
+++ b/packages/@luke-ui/react/src/themes/paper/theme.ts
@@ -0,0 +1,8 @@
+import type { ThemeInput } from '../../theme/define-theme.js';
+import { paperTheme } from '../../theme/foundations/paper.js';
+
+/**
+ * Paper's `defineTheme` input, the materially minimal bundled theme: a flat, hairline-bordered
+ * look with a blue accent. Set it as `extends` on your own input to start from Paper.
+ */
+export const theme: ThemeInput = paperTheme;
diff --git a/packages/@luke-ui/react/src/themes/tactile/index.ts b/packages/@luke-ui/react/src/themes/tactile/index.ts
index a3c18ddf..1f8bf36b 100644
--- a/packages/@luke-ui/react/src/themes/tactile/index.ts
+++ b/packages/@luke-ui/react/src/themes/tactile/index.ts
@@ -1,11 +1,2 @@
-import type { ThemeInput } from '../../theme/define-theme.js';
-import { tactileTheme } from '../../theme/foundations/tactile.js';
-
+export { theme } from './theme.js';
export { themeClassName } from './theme-class-name.js';
-
-/**
- * Tactile's `defineTheme` input, the Luke UI default: a teal accent, a neutral near-white light
- * canvas, and a compact tactile material. Set it as `extends` on your own input to start from
- * Tactile.
- */
-export const theme: ThemeInput = tactileTheme;
diff --git a/packages/@luke-ui/react/src/themes/tactile/theme.ts b/packages/@luke-ui/react/src/themes/tactile/theme.ts
new file mode 100644
index 00000000..74a4bbaf
--- /dev/null
+++ b/packages/@luke-ui/react/src/themes/tactile/theme.ts
@@ -0,0 +1,9 @@
+import type { ThemeInput } from '../../theme/define-theme.js';
+import { tactileTheme } from '../../theme/foundations/tactile.js';
+
+/**
+ * Tactile's `defineTheme` input, the Luke UI default: a teal accent, a neutral near-white light
+ * canvas, and a compact tactile material. Set it as `extends` on your own input to start from
+ * Tactile.
+ */
+export const theme: ThemeInput = tactileTheme;
diff --git a/packages/@luke-ui/react/src/utils/index.ts b/packages/@luke-ui/react/src/utils/index.ts
index bb45b988..6ffde591 100644
--- a/packages/@luke-ui/react/src/utils/index.ts
+++ b/packages/@luke-ui/react/src/utils/index.ts
@@ -1,103 +1,9 @@
-/**
- * Joins a space-separated token list, such as class names or an `aria-labelledby` ID list, and
- * skips empty values.
- */
-export function cx(...parts: Array): string {
- let result = '';
- for (const part of parts) {
- if (part) {
- result = result ? `${result} ${part.trim()}` : part.trim();
- }
- }
- return result;
-}
-
-type Merged = {
- [K in keyof A | keyof B]: K extends 'className'
- ? string
- : K extends 'style'
- ? Record
- : K extends keyof B
- ? B[K]
- : K extends keyof A
- ? A[K]
- : never;
-};
-
-type MergeableProps = {
- className?: unknown;
- style?: unknown;
-};
-
-/**
- * Merges two prop objects, concatenating `className` with `cx` and shallowly
- * merging `style` objects (later props win). All other properties are overwritten
- * by the later object. Useful for combining component props with `createSprinkles()` output.
- */
-export function mergeProps(a: A, b: B): Merged {
- const result = { ...a } as Record;
- const aProps = a as MergeableProps;
- const bProps = b as MergeableProps;
-
- result.className = cx(
- typeof aProps.className === 'string' && aProps.className,
- typeof bProps.className === 'string' && bProps.className,
- );
- result.style = {
- ...(typeof aProps.style === 'object' && aProps.style !== null ? aProps.style : {}),
- ...(typeof bProps.style === 'object' && bProps.style !== null ? bProps.style : {}),
- };
-
- for (const key in b) {
- if (key !== 'className' && key !== 'style') {
- result[key] = b[key as keyof B];
- }
- }
-
- return result as Merged;
-}
-
-/** Converts a pixel value to rem. */
-export function pxToRem(px: number, base: number = 16): string {
- return `${px / base}rem`;
-}
-
-/** Typed key-value pair from an object. */
-export type ObjectEntry = { [K in keyof T]-?: [K, T[K]] }[keyof T];
-
-/**
- * An alternative to `Object.entries()` that avoids type widening.
- *
- * @example
- * Object.entries({ foo: 1, bar: 2 }) // [string, number][]
- * typedEntries({ foo: 1, bar: 2 }) // ["foo" | "bar", number][]
- */
-export function typedEntries(value: T) {
- return Object.entries(value) as Array>;
-}
-
-/**
- * An alternative to `Object.keys()` that avoids type widening.
- *
- * @example
- * Object.keys({ foo: 1, bar: 2 }) // string[]
- * typedKeys({ foo: 1, bar: 2 }) // ("foo" | "bar")[]
- */
-export function typedKeys(value: T) {
- return Object.keys(value) as Array;
-}
-
-/**
- * An alternative to `Object.fromEntries()` that avoids type widening. Must be
- * used in conjunction with `typedEntries` or `typedKeys`.
- *
- * @example
- * const obj = { name: 'Alice', age: 30 };
- * const rebuilt1 = Object.fromEntries(Object.entries(obj));
- * // ^? { [k: string]: string | number }
- * const rebuilt2 = typedFromEntries(typedEntries(obj));
- * // ^? { name: string, age: number }
- */
-export function typedFromEntries(entries: Array>) {
- return Object.fromEntries(entries) as T;
-}
+export {
+ cx,
+ mergeProps,
+ type ObjectEntry,
+ pxToRem,
+ typedEntries,
+ typedFromEntries,
+ typedKeys,
+} from './utils.js';
diff --git a/packages/@luke-ui/react/src/utils/utils.ts b/packages/@luke-ui/react/src/utils/utils.ts
new file mode 100644
index 00000000..bb45b988
--- /dev/null
+++ b/packages/@luke-ui/react/src/utils/utils.ts
@@ -0,0 +1,103 @@
+/**
+ * Joins a space-separated token list, such as class names or an `aria-labelledby` ID list, and
+ * skips empty values.
+ */
+export function cx(...parts: Array): string {
+ let result = '';
+ for (const part of parts) {
+ if (part) {
+ result = result ? `${result} ${part.trim()}` : part.trim();
+ }
+ }
+ return result;
+}
+
+type Merged = {
+ [K in keyof A | keyof B]: K extends 'className'
+ ? string
+ : K extends 'style'
+ ? Record
+ : K extends keyof B
+ ? B[K]
+ : K extends keyof A
+ ? A[K]
+ : never;
+};
+
+type MergeableProps = {
+ className?: unknown;
+ style?: unknown;
+};
+
+/**
+ * Merges two prop objects, concatenating `className` with `cx` and shallowly
+ * merging `style` objects (later props win). All other properties are overwritten
+ * by the later object. Useful for combining component props with `createSprinkles()` output.
+ */
+export function mergeProps(a: A, b: B): Merged {
+ const result = { ...a } as Record;
+ const aProps = a as MergeableProps;
+ const bProps = b as MergeableProps;
+
+ result.className = cx(
+ typeof aProps.className === 'string' && aProps.className,
+ typeof bProps.className === 'string' && bProps.className,
+ );
+ result.style = {
+ ...(typeof aProps.style === 'object' && aProps.style !== null ? aProps.style : {}),
+ ...(typeof bProps.style === 'object' && bProps.style !== null ? bProps.style : {}),
+ };
+
+ for (const key in b) {
+ if (key !== 'className' && key !== 'style') {
+ result[key] = b[key as keyof B];
+ }
+ }
+
+ return result as Merged;
+}
+
+/** Converts a pixel value to rem. */
+export function pxToRem(px: number, base: number = 16): string {
+ return `${px / base}rem`;
+}
+
+/** Typed key-value pair from an object. */
+export type ObjectEntry = { [K in keyof T]-?: [K, T[K]] }[keyof T];
+
+/**
+ * An alternative to `Object.entries()` that avoids type widening.
+ *
+ * @example
+ * Object.entries({ foo: 1, bar: 2 }) // [string, number][]
+ * typedEntries({ foo: 1, bar: 2 }) // ["foo" | "bar", number][]
+ */
+export function typedEntries(value: T) {
+ return Object.entries(value) as Array>;
+}
+
+/**
+ * An alternative to `Object.keys()` that avoids type widening.
+ *
+ * @example
+ * Object.keys({ foo: 1, bar: 2 }) // string[]
+ * typedKeys({ foo: 1, bar: 2 }) // ("foo" | "bar")[]
+ */
+export function typedKeys(value: T) {
+ return Object.keys(value) as Array;
+}
+
+/**
+ * An alternative to `Object.fromEntries()` that avoids type widening. Must be
+ * used in conjunction with `typedEntries` or `typedKeys`.
+ *
+ * @example
+ * const obj = { name: 'Alice', age: 30 };
+ * const rebuilt1 = Object.fromEntries(Object.entries(obj));
+ * // ^? { [k: string]: string | number }
+ * const rebuilt2 = typedFromEntries(typedEntries(obj));
+ * // ^? { name: string, age: number }
+ */
+export function typedFromEntries(entries: Array>) {
+ return Object.fromEntries(entries) as T;
+}
diff --git a/packages/@luke-ui/react/src/visually-hidden/index.ts b/packages/@luke-ui/react/src/visually-hidden/index.ts
new file mode 100644
index 00000000..6a6b9b60
--- /dev/null
+++ b/packages/@luke-ui/react/src/visually-hidden/index.ts
@@ -0,0 +1,2 @@
+export { visuallyHiddenRecipe } from './recipe.css.js';
+export { VisuallyHidden, type VisuallyHiddenProps } from './visually-hidden.js';
diff --git a/packages/@luke-ui/react/src/visually-hidden/index.tsx b/packages/@luke-ui/react/src/visually-hidden/visually-hidden.tsx
similarity index 92%
rename from packages/@luke-ui/react/src/visually-hidden/index.tsx
rename to packages/@luke-ui/react/src/visually-hidden/visually-hidden.tsx
index 46cb3d4c..7b227a45 100644
--- a/packages/@luke-ui/react/src/visually-hidden/index.tsx
+++ b/packages/@luke-ui/react/src/visually-hidden/visually-hidden.tsx
@@ -1,8 +1,7 @@
-export { visuallyHiddenRecipe } from './recipe.css.js';
import type { ComponentPropsWithRef, JSX } from 'react';
import { Text as RacText } from 'react-aria-components/Text';
import type { Prettify } from '../types/prettify.js';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { visuallyHiddenRecipe } from './recipe.css.js';
type _VisuallyHiddenProps = ComponentPropsWithRef;
diff --git a/packages/@luke-ui/react/vite.config.ts b/packages/@luke-ui/react/vite.config.ts
index a9062e7d..d073da50 100644
--- a/packages/@luke-ui/react/vite.config.ts
+++ b/packages/@luke-ui/react/vite.config.ts
@@ -58,8 +58,8 @@ export default defineConfig({
dts: true,
entry: {
stylesheet: 'src/stylesheet.css.ts',
- '*': ['src/*/index.tsx', 'src/*/index.ts'],
- 'primitives/*': ['src/primitives/*/index.tsx', 'src/primitives/*/index.ts'],
+ '*': ['src/*/index.ts'],
+ 'primitives/*': ['src/primitives/*/index.ts'],
'themes/*': ['src/themes/*/index.ts'],
},
exports: {
diff --git a/packages/turbo-generators/README.md b/packages/turbo-generators/README.md
index 27a8fbd1..a9549b7a 100644
--- a/packages/turbo-generators/README.md
+++ b/packages/turbo-generators/README.md
@@ -9,6 +9,8 @@ Custom generators for `turbo generate`.
The component generator asks for name and docs group. Primitive scaffolding is tracked separately.
+Generated component folders use a named implementation file and an export-only `index.ts` barrel.
+
## Usage
```bash
diff --git a/packages/turbo-generators/src/apply-component-creation-plan.test.ts b/packages/turbo-generators/src/apply-component-creation-plan.test.ts
index 5eb59a03..71852b2d 100644
--- a/packages/turbo-generators/src/apply-component-creation-plan.test.ts
+++ b/packages/turbo-generators/src/apply-component-creation-plan.test.ts
@@ -28,7 +28,7 @@ describe('applyComponentCreationPlan', () => {
files: [
{
contents: 'export const StatusBadge = 1;\n',
- path: 'packages/@luke-ui/react/src/status-badge/index.tsx',
+ path: 'packages/@luke-ui/react/src/status-badge/status-badge.tsx',
},
],
jsonEdits: [
@@ -53,7 +53,7 @@ describe('applyComponentCreationPlan', () => {
await applyComponentCreationPlan(root, plan);
await expect(
- readFile(join(root, 'packages/@luke-ui/react/src/status-badge/index.tsx'), 'utf8'),
+ readFile(join(root, 'packages/@luke-ui/react/src/status-badge/status-badge.tsx'), 'utf8'),
).resolves.toBe('export const StatusBadge = 1;\n');
await expect(readJson(root, 'apps/docs/content/docs/components/meta.json')).resolves.toEqual({
pages: ['feedback'],
diff --git a/packages/turbo-generators/src/component-creation-plan.test.ts b/packages/turbo-generators/src/component-creation-plan.test.ts
index a1d0ccfc..0da0846c 100644
--- a/packages/turbo-generators/src/component-creation-plan.test.ts
+++ b/packages/turbo-generators/src/component-creation-plan.test.ts
@@ -36,10 +36,11 @@ describe('createComponentPlan', () => {
'apps/docs/content/docs/components/feedback/status-badge.mdx',
'apps/docs/src/examples/status-badge/basic.tsx',
'packages/@luke-ui/react/src/status-badge/component-test-registration.ts',
- 'packages/@luke-ui/react/src/status-badge/index.tsx',
+ 'packages/@luke-ui/react/src/status-badge/index.ts',
'packages/@luke-ui/react/src/status-badge/recipe.css.ts',
'packages/@luke-ui/react/src/status-badge/status-badge.browser.test.tsx',
'packages/@luke-ui/react/src/status-badge/status-badge.stories.tsx',
+ 'packages/@luke-ui/react/src/status-badge/status-badge.tsx',
'packages/@luke-ui/react/src/status-badge/status-badge.visual.test.tsx',
]);
expect(plan.sortedImportEdits).toEqual([
@@ -53,14 +54,23 @@ describe('createComponentPlan', () => {
"\t['StatusBadge', 'status-badge', 'universal', 'none', 'applicable'],",
]);
- const indexSource = plan.files.find((file) =>
- file.path.endsWith('/status-badge/index.tsx'),
- )?.contents;
const recipeSource = plan.files.find((file) =>
file.path.endsWith('/status-badge/recipe.css.ts'),
)?.contents;
+ const indexSource = plan.files.find((file) =>
+ file.path.endsWith('/status-badge/status-badge.tsx'),
+ )?.contents;
+ const barrelSource = plan.files.find((file) =>
+ file.path.endsWith('/status-badge/index.ts'),
+ )?.contents;
- expect(indexSource).toContain('export { statusBadgeRecipe, type StatusBadgeRecipeVariants }');
+ expect(indexSource).not.toContain('export { statusBadgeRecipe');
+ expect(barrelSource).toContain(
+ "export { StatusBadge, type StatusBadgeProps } from './status-badge.js';",
+ );
+ expect(barrelSource).toContain(
+ "export { statusBadgeRecipe, type StatusBadgeRecipeVariants } from './recipe.css.js';",
+ );
expect(recipeSource).toContain('export const statusBadgeRecipe = recipe({');
expect(recipeSource).toContain(
'export type StatusBadgeRecipeVariants = RecipeSelection;',
@@ -137,11 +147,11 @@ describe('createComponentPlan', () => {
{
heading: undefined,
name: 'StatusBadgeProps',
- path: 'packages/@luke-ui/react/src/status-badge/index.tsx',
+ path: 'packages/@luke-ui/react/src/status-badge/status-badge.tsx',
},
]);
expect(renderPropsPage(frontmatter)).toContain(
- '',
+ '',
);
});
@@ -159,9 +169,6 @@ describe('createComponentPlan', () => {
await mkdir(componentDir, { recursive: true });
await mkdir(stylesDir, { recursive: true });
- const indexSource = plan.files.find((file) =>
- file.path.endsWith('/status-badge/index.tsx'),
- )?.contents;
const recipeSource = plan.files.find((file) =>
file.path.endsWith('/status-badge/recipe.css.ts'),
)?.contents;
@@ -169,8 +176,6 @@ describe('createComponentPlan', () => {
throw new Error('Expected generated recipe source.');
}
- expect(indexSource).toContain('export { statusBadgeRecipe, type StatusBadgeRecipeVariants }');
-
await writeFile(join(componentDir, 'recipe.css.ts'), recipeSource, 'utf8');
await writeFile(
join(stylesDir, 'recipe.ts'),
diff --git a/packages/turbo-generators/src/component-creation-plan.ts b/packages/turbo-generators/src/component-creation-plan.ts
index a129d667..ad346011 100644
--- a/packages/turbo-generators/src/component-creation-plan.ts
+++ b/packages/turbo-generators/src/component-creation-plan.ts
@@ -74,7 +74,11 @@ export function createComponentPlan(input: CreateComponentInput): ComponentCreat
recipeName,
variantsType,
}),
- path: `packages/@luke-ui/react/src/${name}/index.tsx`,
+ path: `packages/@luke-ui/react/src/${name}/${name}.tsx`,
+ },
+ {
+ contents: renderComponentBarrel({ name, pascalName, recipeName, variantsType }),
+ path: `packages/@luke-ui/react/src/${name}/index.ts`,
},
{
contents: renderRecipe({ recipeName, variantsType }),
@@ -215,11 +219,9 @@ function renderComponentSource(input: {
variantsType: string;
}): string {
return `import type { ComponentProps, JSX } from 'react';
-import { cx } from '../utils/index.js';
+import { cx } from '../utils/utils.js';
import { ${input.recipeName} } from './recipe.css.js';
-export { ${input.recipeName}, type ${input.variantsType} } from './recipe.css.js';
-
/** Props for \`${input.pascalName}\`. */
export interface ${input.pascalName}Props extends ComponentProps<'div'> {}
@@ -231,6 +233,17 @@ export function ${input.pascalName}(props: ${input.pascalName}Props): JSX.Elemen
`;
}
+function renderComponentBarrel(input: {
+ name: string;
+ pascalName: string;
+ recipeName: string;
+ variantsType: string;
+}): string {
+ return `export { ${input.pascalName}, type ${input.pascalName}Props } from './${input.name}.js';
+export { ${input.recipeName}, type ${input.variantsType} } from './recipe.css.js';
+`;
+}
+
function renderPackageStory(input: {
docsGroup: string;
name: string;
@@ -388,7 +401,7 @@ title: ${input.displayName}
source: packages/@luke-ui/react/src/${input.name}
props:
- name: ${input.pascalName}Props
- path: packages/@luke-ui/react/src/${input.name}/index.tsx
+ path: packages/@luke-ui/react/src/${input.name}/${input.name}.tsx
---