@structuralists/scaffolding 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Release & Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
release:
|
|
9
|
+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
id-token: write
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: '20'
|
|
22
|
+
registry-url: 'https://registry.npmjs.org'
|
|
23
|
+
|
|
24
|
+
- run: npm install -g npm@latest
|
|
25
|
+
|
|
26
|
+
- uses: oven-sh/setup-bun@v2
|
|
27
|
+
with:
|
|
28
|
+
bun-version: latest
|
|
29
|
+
|
|
30
|
+
- run: bun install --frozen-lockfile
|
|
31
|
+
|
|
32
|
+
- run: bun run typecheck
|
|
33
|
+
- run: bun run lint
|
|
34
|
+
- run: bun run test
|
|
35
|
+
|
|
36
|
+
- name: Configure git
|
|
37
|
+
run: |
|
|
38
|
+
git config user.name 'github-actions[bot]'
|
|
39
|
+
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
|
40
|
+
|
|
41
|
+
- name: Determine bump type from commit message
|
|
42
|
+
id: bump
|
|
43
|
+
run: |
|
|
44
|
+
MSG=$(git log -1 --pretty=%B)
|
|
45
|
+
if echo "$MSG" | grep -qE "BREAKING CHANGE|^[a-z]+(\([^)]+\))?!:"; then
|
|
46
|
+
echo "type=major" >> "$GITHUB_OUTPUT"
|
|
47
|
+
elif echo "$MSG" | grep -qE "^feat(\(|:)"; then
|
|
48
|
+
echo "type=minor" >> "$GITHUB_OUTPUT"
|
|
49
|
+
else
|
|
50
|
+
echo "type=patch" >> "$GITHUB_OUTPUT"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
- name: Bump version
|
|
54
|
+
id: version
|
|
55
|
+
run: |
|
|
56
|
+
NEW_TAG=$(npm version ${{ steps.bump.outputs.type }} -m "release: %s [skip ci]")
|
|
57
|
+
echo "tag=$NEW_TAG" >> "$GITHUB_OUTPUT"
|
|
58
|
+
|
|
59
|
+
- name: Push commit and tag
|
|
60
|
+
run: git push --follow-tags
|
|
61
|
+
|
|
62
|
+
- run: npm publish
|
|
63
|
+
|
|
64
|
+
- run: gh release create "${{ steps.version.outputs.tag }}" --generate-notes
|
|
65
|
+
env:
|
|
66
|
+
GH_TOKEN: ${{ github.token }}
|
package/README.md
CHANGED
|
@@ -1,7 +1,86 @@
|
|
|
1
1
|
# @structuralists/scaffolding
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@structuralists/scaffolding)
|
|
4
|
+
[](https://github.com/structuralists/scaffolding/actions/workflows/publish.yml)
|
|
5
|
+
[](https://bundlephobia.com/package/@structuralists/scaffolding)
|
|
6
|
+
|
|
3
7
|
`@structuralists/scaffolding` is a bundle of react components that can make scaffolding a UI quick and efficient. Unlike component libraries like a material UI, it does not target being used for production grade applications, but instead targets getting "something" up and running, where you don't care what exactly it looks like.
|
|
4
8
|
|
|
5
9
|
It is not designed to be customized. it's not pluggable. It is not designed to composed into another design system (though it is react, you can write you own components and pass them as children or whatever to your heart's content.)
|
|
6
10
|
|
|
7
11
|
It is designed to get you something working, and if you then do care what that looks like, build or import a design system and convert to that.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @structuralists/scaffolding
|
|
17
|
+
# or: bun add / pnpm add / yarn add
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Peer deps (you almost certainly already have these): `react@^19`, `react-dom@^19`, `react-router@^7`.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
Import the design tokens once, at your app entry. They define the CSS custom properties every component reads:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import '@structuralists/scaffolding/tokens.css';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That's it — no provider, no theme object. Theme switching is driven by `data-theme` on any ancestor (typically `<html>`):
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<html data-theme="dark-warm">
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Available themes: `light-warm`, `light-paper`, `light-sepia`, `dark-warm`, `dark-neutral`, `dark-dimmed`. Omit the attribute to follow system preference.
|
|
37
|
+
|
|
38
|
+
## Use it
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { Stack, Heading, Button, Input, Field } from '@structuralists/scaffolding';
|
|
42
|
+
|
|
43
|
+
export const SignupCard = () => {
|
|
44
|
+
return (
|
|
45
|
+
<Stack gap={3}>
|
|
46
|
+
<Heading level={1}>Sign up</Heading>
|
|
47
|
+
<Field label="Email">
|
|
48
|
+
<Input type="email" />
|
|
49
|
+
</Field>
|
|
50
|
+
<Button variant="primary">Continue</Button>
|
|
51
|
+
</Stack>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Browse every component (with live controls) in the Storybook: `bun run storybook`.
|
|
57
|
+
|
|
58
|
+
## Consumer notes
|
|
59
|
+
|
|
60
|
+
This package ships TypeScript source directly — `main` and `types` both point at `./index.ts`. Modern bundlers handle that out of the box:
|
|
61
|
+
|
|
62
|
+
- **Vite / Remix / Bun / Astro**: works with no config.
|
|
63
|
+
- **Next.js**: add the package to `transpilePackages`:
|
|
64
|
+
```js
|
|
65
|
+
// next.config.js
|
|
66
|
+
module.exports = {
|
|
67
|
+
transpilePackages: ['@structuralists/scaffolding'],
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
- **Plain Node / CRA**: not supported — you need a bundler that understands `.ts`/`.tsx` and CSS Modules.
|
|
71
|
+
|
|
72
|
+
## Releasing
|
|
73
|
+
|
|
74
|
+
Releases are fully automated. Open a PR, merge it, done — CI bumps the version, publishes to npm with provenance, and creates a GitHub release with auto-generated notes.
|
|
75
|
+
|
|
76
|
+
The repo is configured for **squash-only merging**, and the **PR title becomes the squash-commit title**. That title drives the version bump:
|
|
77
|
+
|
|
78
|
+
| PR title pattern | Bump |
|
|
79
|
+
| ----------------------------------------------- | --------- |
|
|
80
|
+
| `feat: ...` or `feat(scope): ...` | **minor** |
|
|
81
|
+
| `feat!: ...` or any commit with `BREAKING CHANGE` in the body | **major** |
|
|
82
|
+
| anything else (`fix:`, `chore:`, `docs:`, etc.) | **patch** |
|
|
83
|
+
|
|
84
|
+
Match the [conventional commits](https://www.conventionalcommits.org/) style when writing PR titles.
|
|
85
|
+
|
|
86
|
+
To skip a release for a specific merge, include `[skip ci]` in the PR title.
|
package/package.json
CHANGED
|
@@ -2,8 +2,6 @@ import { describe, test, expect, mock } from 'bun:test';
|
|
|
2
2
|
import { render, fireEvent, cleanup } from '@testing-library/react';
|
|
3
3
|
import { MediumModal } from './index';
|
|
4
4
|
|
|
5
|
-
// happy-dom implements showMediumModal/close but we call cleanup between tests
|
|
6
|
-
// manually (bun:test has no afterEach-by-default in this setup).
|
|
7
5
|
const setup = (props: Partial<React.ComponentProps<typeof MediumModal>> = {}) => {
|
|
8
6
|
const onClose = mock(() => {});
|
|
9
7
|
const utils = render(
|
|
@@ -11,9 +9,12 @@ const setup = (props: Partial<React.ComponentProps<typeof MediumModal>> = {}) =>
|
|
|
11
9
|
<button type="button">inside</button>
|
|
12
10
|
</MediumModal>,
|
|
13
11
|
);
|
|
14
|
-
const
|
|
12
|
+
const doc = utils.container.ownerDocument;
|
|
13
|
+
const dialog = doc.querySelector('[role="dialog"]');
|
|
15
14
|
if (!dialog) throw new Error('dialog not rendered');
|
|
16
|
-
|
|
15
|
+
const backdrop = doc.querySelector('div[aria-hidden="true"]');
|
|
16
|
+
if (!backdrop) throw new Error('backdrop not rendered');
|
|
17
|
+
return { ...utils, onClose, dialog, backdrop };
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
describe('MediumModal', () => {
|
|
@@ -24,9 +25,9 @@ describe('MediumModal', () => {
|
|
|
24
25
|
cleanup();
|
|
25
26
|
});
|
|
26
27
|
|
|
27
|
-
test('calls onClose when the backdrop
|
|
28
|
-
const { onClose,
|
|
29
|
-
fireEvent.click(
|
|
28
|
+
test('calls onClose when the backdrop is clicked', () => {
|
|
29
|
+
const { onClose, backdrop } = setup();
|
|
30
|
+
fireEvent.click(backdrop);
|
|
30
31
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
31
32
|
cleanup();
|
|
32
33
|
});
|
|
@@ -38,10 +39,9 @@ describe('MediumModal', () => {
|
|
|
38
39
|
cleanup();
|
|
39
40
|
});
|
|
40
41
|
|
|
41
|
-
test('calls onClose on
|
|
42
|
-
const { onClose
|
|
43
|
-
|
|
44
|
-
dialog.dispatchEvent(cancel);
|
|
42
|
+
test('calls onClose on Escape', () => {
|
|
43
|
+
const { onClose } = setup();
|
|
44
|
+
fireEvent.keyDown(document.body, { key: 'Escape' });
|
|
45
45
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
46
46
|
cleanup();
|
|
47
47
|
});
|