Skip to content

Commit 9c8ca44

Browse files
authored
Merge branch 'develop' into develop
2 parents fce3114 + 758b6ec commit 9c8ca44

File tree

192 files changed

+4467
-2050
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+4467
-2050
lines changed

.eslintrc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"tsx": "never"
3030
}
3131
],
32+
"import/prefer-default-export": "off",
3233
"react/jsx-filename-extension": [1, { "extensions": [".jsx", ".tsx"] }],
3334
"comma-dangle": 0, // not sure why airbnb turned this on. gross!
3435
"default-param-last": 0,
@@ -41,6 +42,7 @@
4142
"no-restricted-exports": 1,
4243
"no-underscore-dangle": 0,
4344
"no-useless-catch": 2,
45+
"no-plusplus": "off",
4446
"prefer-object-spread": 0,
4547
"max-len": [1, 120, 2, {"ignoreComments": true, "ignoreTemplateLiterals": true}],
4648
"max-classes-per-file": 0,
@@ -131,7 +133,12 @@
131133
"rules": {
132134
"no-use-before-define": "off",
133135
"import/no-extraneous-dependencies": "off",
134-
"no-unused-vars": "off"
136+
"no-unused-vars": "off",
137+
"import/no-default-export": "warn",
138+
"no-underscore-dangle": "warn",
139+
"react/require-default-props": "off",
140+
"no-shadow": "off",
141+
"@typescript-eslint/no-shadow": "error"
135142
}
136143
},
137144
{

.prettierrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"insertPragma": false,
66
"jsxBracketSameLine": false,
77
"jsxSingleQuote": false,
8-
"parser": "babel",
98
"printWidth": 80,
109
"proseWrap": "never",
1110
"requirePragma": false,

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ ENV NODE_ENV=production
2828
COPY package.json package-lock.json index.js ./
2929
RUN npm install --production
3030
COPY --from=build $APP_HOME/dist ./dist
31-
CMD ["npm", "run", "start:prod"]
31+
CMD ["npm", "run", "start:prod"]

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ We are a community of, and in solidarity with, people from every gender identity
1010

1111
Learn more about [our community](https://p5js.org/community/) and read our [Community Statement and Code of Conduct](./.github/CODE_OF_CONDUCT.md). You can directly support our work with p5.js by [donating to the Processing Foundation](https://processingfoundation.org/support).
1212

13+
Stay in touch with Processing Foundation across other platforms:
14+
- [Instagram](https://www.instagram.com/p5xjs)
15+
- [Youtube](https://www.youtube.com/@ProcessingFoundation)
16+
- [X](https://x.com/p5xjs)
17+
- [Discord](https://discord.com/invite/esmGA6H6wm)
18+
- [Forum](https://discourse.processing.org)
19+
20+
1321
## Using the p5.js Editor 🤔
1422

1523
Make your first sketch in the [p5.js Editor](https://editor.p5js.org/)! Learn more about sketching with p5.js on the [Get Started](https://p5js.org/tutorials/get-started/) and find everything you can do in the [Reference](https://p5js.org/reference/). You can also look at [examples](https://editor.p5js.org/p5/sketches) and remix them in the p5.js Editor.
@@ -26,6 +34,13 @@ The p5.js Editor is a collaborative project created by many individuals, mostly
2634

2735
3. [All Contributors list on the p5.js repository](https://github.com/processing/p5.js?tab=readme-ov-file#contributors) - Explore the All Contributors list to see the wide range of contributions by our amazing community!
2836

37+
> **TypeScript Migration:**
38+
> As of July 2025, we are working on migrating the repo to TypeScript as part of the **[p5.js Web Editor pr05 Grant](https://github.com/processing/pr05-grant/wiki/2025-pr05-Program-Page)**.
39+
> This migration will occur in two phases:
40+
> 1. **Grant Work (July – October 31, 2025)** – Setting up TypeScript configuration, tooling, and starting partial migration. Contributions will be **closed** during this period.
41+
> 2. **Open Contribution (After October 31, 2025)** – TypeScript migration tasks will **open** to all contributors, with guidelines and tutorials available.
42+
>
43+
> For full details, see [TypeScript Migration Plan](./contributor_docs/typescript-migration.md).
2944
3045
## Acknowledgements 🙏
3146

client/common/Button.stories.jsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { action } from '@storybook/addon-actions';
33

4-
import Button from './Button';
4+
import { Button, ButtonDisplays, ButtonKinds, ButtonTypes } from './Button';
55
import { GithubIcon, DropdownArrowIcon, PlusIcon } from './icons';
66

77
export default {
@@ -15,13 +15,13 @@ export default {
1515
};
1616

1717
export const AllFeatures = (args) => (
18-
<Button disabled={args.disabled} type="submit" label={args.label}>
18+
<Button disabled={args.disabled} type={ButtonTypes.SUBMIT} label={args.label}>
1919
{args.children}
2020
</Button>
2121
);
2222

2323
export const SubmitButton = () => (
24-
<Button type="submit" label="submit">
24+
<Button type={ButtonTypes.SUBMIT} label="submit">
2525
This is a submit button
2626
</Button>
2727
);
@@ -59,7 +59,7 @@ export const ButtonWithIconAfter = () => (
5959
);
6060

6161
export const InlineButtonWithIconAfter = () => (
62-
<Button iconAfter={<DropdownArrowIcon />} display={Button.displays.inline}>
62+
<Button iconAfter={<DropdownArrowIcon />} display={ButtonDisplays.INLINE}>
6363
File name
6464
</Button>
6565
);
@@ -68,6 +68,6 @@ export const InlineIconOnlyButton = () => (
6868
<Button
6969
aria-label="Add to collection"
7070
iconBefore={<PlusIcon />}
71-
display={Button.displays.inline}
71+
display={ButtonDisplays.INLINE}
7272
/>
7373
);

client/common/Button.test.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import { render, screen, fireEvent } from '../test-utils';
3+
import { Button } from './Button';
4+
5+
const MockIcon = (props: React.SVGProps<SVGSVGElement>) => (
6+
<svg data-testid="mock-icon" {...props} />
7+
);
8+
9+
describe('Button', () => {
10+
// Tag
11+
it('renders as an anchor when href is provided', () => {
12+
render(<Button href="https://example.com">Link</Button>);
13+
const anchor = screen.getByRole('link');
14+
expect(anchor.tagName.toLowerCase()).toBe('a');
15+
expect(anchor).toHaveAttribute('href', 'https://example.com');
16+
});
17+
18+
it('renders as a React Router <Link> when `to` is provided', () => {
19+
render(<Button to="/dashboard">Go</Button>);
20+
const link = screen.getByRole('link');
21+
expect(link.tagName.toLowerCase()).toBe('a'); // Link renders as <a>
22+
expect(link).toHaveAttribute('href', '/dashboard');
23+
});
24+
25+
it('renders as a <button> with a type of "button" by default', () => {
26+
render(<Button>Click Me</Button>);
27+
const el = screen.getByRole('button');
28+
expect(el.tagName.toLowerCase()).toBe('button');
29+
expect(el).toHaveAttribute('type', 'button');
30+
});
31+
32+
// Children & Icons
33+
it('renders children', () => {
34+
render(<Button>Click Me</Button>);
35+
expect(screen.getByText('Click Me')).toBeInTheDocument();
36+
});
37+
38+
it('renders an iconBefore and button text', () => {
39+
render(
40+
<Button iconBefore={<MockIcon aria-label="iconbefore" />}>
41+
This has a before icon
42+
</Button>
43+
);
44+
expect(screen.getByLabelText('iconbefore')).toBeInTheDocument();
45+
expect(screen.getByRole('button')).toHaveTextContent(
46+
'This has a before icon'
47+
);
48+
});
49+
50+
it('renders with iconAfter', () => {
51+
render(
52+
<Button iconAfter={<MockIcon aria-label="iconafter" />}>
53+
This has an after icon
54+
</Button>
55+
);
56+
expect(screen.getByLabelText('iconafter')).toBeInTheDocument();
57+
expect(screen.getByRole('button')).toHaveTextContent(
58+
'This has an after icon'
59+
);
60+
});
61+
62+
it('renders only the icon if iconOnly', () => {
63+
render(
64+
<Button iconAfter={<MockIcon aria-label="iconafter" />} iconOnly>
65+
This has an after icon
66+
</Button>
67+
);
68+
expect(screen.getByLabelText('iconafter')).toBeInTheDocument();
69+
expect(screen.getByRole('button')).not.toHaveTextContent(
70+
'This has an after icon'
71+
);
72+
});
73+
74+
// HTML attributes
75+
it('calls onClick handler when clicked', () => {
76+
const handleClick = jest.fn();
77+
render(<Button onClick={handleClick}>Click</Button>);
78+
fireEvent.click(screen.getByText('Click'));
79+
expect(handleClick).toHaveBeenCalledTimes(1);
80+
});
81+
82+
it('renders disabled state', () => {
83+
render(<Button disabled>Disabled</Button>);
84+
expect(screen.getByRole('button')).toBeDisabled();
85+
});
86+
87+
it('uses aria-label when provided', () => {
88+
render(<Button aria-label="Upload" iconOnly />);
89+
expect(screen.getByLabelText('Upload')).toBeInTheDocument();
90+
});
91+
});

0 commit comments

Comments
 (0)