Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defaultStyle as function #57

Merged
merged 3 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/orange-planes-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@embellish/react": minor
---

Made `defaultStyle` a function parameterized by the `is` prop (or default).
3 changes: 1 addition & 2 deletions docs/api/react.component.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ P,
C extends string,
DefaultIs extends
| keyof JSX.IntrinsicElements
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| React.JSXElementConstructor<any>,
> = <
Is extends
| keyof JSX.IntrinsicElements
| React.JSXElementConstructor<any> = DefaultIs, // eslint-disable-line @typescript-eslint/no-explicit-any
| React.JSXElementConstructor<any> = DefaultIs,
InlineConditionName extends string = never,
>(
props: ComponentProps<P, C, Is, InlineConditionName>,
Expand Down
4 changes: 3 additions & 1 deletion docs/api/react.componentoptions.defaultstyle.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ Default styles to apply to the element
**Signature:**

```typescript
defaultStyle?: CSSProperties;
defaultStyle?: (
is: keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>,
) => CSSProperties;
```
2 changes: 1 addition & 1 deletion docs/api/react.componentoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ _(Optional)_ Default value for the `is` prop

</td><td>

CSSProperties
( is: keyof JSX.IntrinsicElements \| React.JSXElementConstructor&lt;any&gt;, ) =&gt; CSSProperties


</td><td>
Expand Down
1 change: 0 additions & 1 deletion docs/api/react.componentprops.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Component props
export declare type ComponentProps<
P,
C extends string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Is extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>,
InlineConditionName extends string,
> = {
Expand Down
2 changes: 1 addition & 1 deletion docs/api/react.createcomponent.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ P,
C extends string,
DefaultIs extends
| keyof JSX.IntrinsicElements
| JSXElementConstructor<any> = "div", // eslint-disable-line @typescript-eslint/no-explicit-any
| JSXElementConstructor<any> = "div",
>(options: ComponentOptions<P, C, DefaultIs>): Component<P, C, DefaultIs>;
```

Expand Down
13 changes: 8 additions & 5 deletions packages/react/src/component.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import type {
Condition,
Conditions,
Expand Down Expand Up @@ -25,7 +27,10 @@ export interface ComponentOptions<P, C extends string, DefaultIs> {
defaultIs?: DefaultIs;

/** Default styles to apply to the element */
defaultStyle?: CSSProperties;
defaultStyle?: (
/** The value provided for the `is` prop */
is: keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>,
) => CSSProperties;

/** Component style props */
styleProps?: StyleProps<P>;
Expand Down Expand Up @@ -53,7 +58,6 @@ export interface ComponentOptions<P, C extends string, DefaultIs> {
export type ComponentProps<
P,
C extends string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Is extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>,
InlineConditionName extends string,
> = {
Expand Down Expand Up @@ -96,12 +100,11 @@ export type Component<
C extends string,
DefaultIs extends
| keyof JSX.IntrinsicElements
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| React.JSXElementConstructor<any>,
> = <
Is extends
| keyof JSX.IntrinsicElements
| React.JSXElementConstructor<any> = DefaultIs, // eslint-disable-line @typescript-eslint/no-explicit-any
| React.JSXElementConstructor<any> = DefaultIs,
InlineConditionName extends string = never,
>(
props: ComponentProps<P, C, Is, InlineConditionName>,
Expand All @@ -127,5 +130,5 @@ export function createComponent<
C extends string,
DefaultIs extends
| keyof JSX.IntrinsicElements
| JSXElementConstructor<any> = "div", // eslint-disable-line @typescript-eslint/no-explicit-any
| JSXElementConstructor<any> = "div",
>(options: ComponentOptions<P, C, DefaultIs>): Component<P, C, DefaultIs>;
4 changes: 2 additions & 2 deletions packages/react/src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export function createComponent({
displayName,
styleProps = {},
defaultIs = "div",
defaultStyle = {},
defaultStyle = () => ({}),
conditions: configConditions,
fallback: configFallback = "revert-layer",
}) {
Expand All @@ -111,7 +111,7 @@ export function createComponent({
},
ref,
) => {
const style = { ...defaultStyle },
const style = { ...defaultStyle(Component) },
forwardProps = {};

for (const key in styleProp) {
Expand Down
49 changes: 45 additions & 4 deletions packages/react/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { test } from "node:test";

import type { Browser, Page } from "puppeteer";
import puppeteer from "puppeteer";
import type { CSSProperties } from "react";
import { renderToString } from "react-dom/server";

import {
Expand Down Expand Up @@ -73,9 +74,9 @@ async function queryComputedStyle(

test("default style", async () => {
const Box = createComponent({
defaultStyle: {
defaultStyle: () => ({
background: "#0000ff",
},
}),
});
const style = await withPage(async page => {
await renderContent(page, <Box id="box" />);
Expand Down Expand Up @@ -118,9 +119,9 @@ test("style props", async () => {

test("declaration ordering - default style vs. `style` prop", async () => {
const Box = createComponent({
defaultStyle: {
defaultStyle: () => ({
color: "#0000ff",
},
}),
});
const style = await withPage(async page => {
await renderContent(page, <Box id="box" style={{ color: "#ff0000" }} />);
Expand All @@ -143,6 +144,46 @@ test("declaration ordering - `style` prop vs. style prop", async () => {
assert.strictEqual(hex(style.color), "#ff0000");
});

test("default style as a function of the `is` prop", async () => {
function Component({ id, style }: { id: string; style?: CSSProperties }) {
return <div id={id} style={style} />;
}
const Box = createComponent({
defaultStyle: is => ({
background:
is === "div"
? "#ff0000"
: is === "span"
? "#00ff00"
: is === Component
? "#0000ff"
: "#999999",
}),
});
await withPage(async page => {
await renderContent(
page,
<>
<Box id="div" is="div" />
<Box id="span" is="span" />
<Box id="component" is={Component} />
</>,
);
assert.strictEqual(
hex((await queryComputedStyle(page, "#div")).backgroundColor),
"#ff0000",
);
assert.strictEqual(
hex((await queryComputedStyle(page, "#span")).backgroundColor),
"#00ff00",
);
assert.strictEqual(
hex((await queryComputedStyle(page, "#component")).backgroundColor),
"#0000ff",
);
});
});

test("simple reusable condition", async () => {
const { StyleSheet, hooks } = createHooks(["&:hover"]);
const Box = createComponent({
Expand Down