webadwaita 0.2.0 → 0.2.1
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.
- package/README.md +25 -32
- package/dist/native/Box/index.js +120 -0
- package/{src/Button/index.tsx → dist/native/Button/index.js} +32 -50
- package/{src/Card/index.tsx → dist/native/Card/index.js} +25 -25
- package/{src/Checkbox/index.tsx → dist/native/Checkbox/index.js} +41 -48
- package/{src/Entry/index.tsx → dist/native/Entry/index.js} +24 -42
- package/{src/HeaderBar/index.tsx → dist/native/HeaderBar/index.js} +31 -30
- package/{src/Switch/index.tsx → dist/native/Switch/index.js} +31 -37
- package/dist/native/index.js +8 -0
- package/{src/theme.ts → dist/native/theme.js} +4 -7
- package/{src/tokens.css.ts → dist/native/tokens.css.js} +3 -17
- package/dist/types/Box/index.d.ts +23 -0
- package/dist/types/Box/index.d.ts.map +1 -0
- package/dist/types/Button/index.d.ts +22 -0
- package/dist/types/Button/index.d.ts.map +1 -0
- package/dist/types/Card/index.d.ts +14 -0
- package/dist/types/Card/index.d.ts.map +1 -0
- package/dist/types/Checkbox/index.d.ts +13 -0
- package/dist/types/Checkbox/index.d.ts.map +1 -0
- package/dist/types/Entry/index.d.ts +17 -0
- package/dist/types/Entry/index.d.ts.map +1 -0
- package/dist/types/HeaderBar/index.d.ts +16 -0
- package/dist/types/HeaderBar/index.d.ts.map +1 -0
- package/dist/types/Switch/index.d.ts +13 -0
- package/dist/types/Switch/index.d.ts.map +1 -0
- package/{src/index.ts → dist/types/index.d.ts} +1 -7
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/theme.d.ts +77 -0
- package/dist/types/theme.d.ts.map +1 -0
- package/dist/types/tokens.css.d.ts +76 -0
- package/dist/types/tokens.css.d.ts.map +1 -0
- package/dist/web/Box/index.js +150 -0
- package/dist/web/Box/styles.css +39 -0
- package/dist/web/Button/index.js +132 -0
- package/dist/web/Button/styles.css +81 -0
- package/dist/web/Card/index.js +75 -0
- package/dist/web/Card/styles.css +91 -0
- package/dist/web/Checkbox/index.js +116 -0
- package/dist/web/Checkbox/styles.css +99 -0
- package/dist/web/Entry/index.js +74 -0
- package/dist/web/Entry/styles.css +113 -0
- package/dist/web/HeaderBar/index.js +87 -0
- package/dist/web/HeaderBar/styles.css +117 -0
- package/dist/web/Switch/index.js +86 -0
- package/dist/web/Switch/styles.css +134 -0
- package/dist/web/_tokens/styles.css +32 -0
- package/dist/web/index.js +8 -0
- package/dist/web/theme.js +16 -0
- package/dist/web/tokens.css.js +79 -0
- package/package.json +28 -9
- package/babel.config.cjs +0 -23
- package/src/Box/index.tsx +0 -105
package/README.md
CHANGED
|
@@ -18,10 +18,6 @@ react-strict-dom is Meta's strict subset of `<html.*>` primitives plus a `css.cr
|
|
|
18
18
|
| `Card` | Surface with optional title; `boxed` and `flat` variants. |
|
|
19
19
|
| `HeaderBar` | Top bar with leading / centered title / trailing slots. |
|
|
20
20
|
|
|
21
|
-
All design tokens live in [`src/tokens.css.ts`](./src/tokens.css.ts) — palette, radius, spacing, typography, motion. The `.css.ts` filename is required: react-strict-dom's Babel preset configures StyleX to treat `.css` as the token-file extension, so any file holding `css.defineConsts` / `css.defineVars` calls must be named `<name>.css.ts`.
|
|
22
|
-
|
|
23
|
-
[`src/theme.ts`](./src/theme.ts) re-exports the same tokens for runtime use (e.g. computed inline styles in app code).
|
|
24
|
-
|
|
25
21
|
## Install
|
|
26
22
|
|
|
27
23
|
```sh
|
|
@@ -32,37 +28,37 @@ Peer deps: `react ^19`, plus `react-dom` (web) or `react-native >= 0.79` (native
|
|
|
32
28
|
|
|
33
29
|
## Setup
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
WebAdwaita ships precompiled JS plus per-component CSS — no special bundler config required. Install, import, render:
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
```sh
|
|
34
|
+
npm install webadwaita react-strict-dom
|
|
35
|
+
```
|
|
40
36
|
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
plugins: [
|
|
44
|
-
react({
|
|
45
|
-
babel: { configFile: true },
|
|
46
|
-
include: [/\.[jt]sx?$/, '<...>/node_modules/webadwaita/src/**']
|
|
47
|
-
}),
|
|
48
|
-
babel({ filter: /\.[jt]sx?$/ })
|
|
49
|
-
]
|
|
37
|
+
```tsx
|
|
38
|
+
import { Button, Card } from 'webadwaita';
|
|
50
39
|
```
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
'react-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
That's it. Each component side-effect-imports its own CSS chunk, so your bundler ships only the styles for the components you actually use (works in Next.js, Vite, CRA, anywhere with a modern bundler honoring `package.json#sideEffects`).
|
|
42
|
+
|
|
43
|
+
**Native (Expo / Metro):** the package's `react-native` exports condition routes Metro to a precompiled native build that uses RN `StyleSheet` at runtime. No Babel preset to wire up in your app — just `import { Button } from 'webadwaita'`.
|
|
44
|
+
|
|
45
|
+
### How the build works
|
|
46
|
+
|
|
47
|
+
The library has a build step (`npm run build`) that produces:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
dist/
|
|
51
|
+
web/<Component>/index.js ← starts with `import './styles.css'`
|
|
52
|
+
web/<Component>/styles.css ← only that component's atomic rules
|
|
53
|
+
web/_tokens/styles.css ← shared baseline (loaded once)
|
|
54
|
+
native/<Component>/index.js ← RN StyleSheet output, no CSS
|
|
55
|
+
types/<Component>/index.d.ts
|
|
61
56
|
```
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
Two design-token notes carry over to consumer code:
|
|
64
59
|
|
|
65
|
-
|
|
60
|
+
- Tokens still live in [`src/tokens.css.ts`](./src/tokens.css.ts). The `.css.ts` filename is required: react-strict-dom's StyleX config treats `.css` as the token-file extension, so any file calling `css.defineConsts` / `css.defineVars` must follow that convention.
|
|
61
|
+
- [`src/theme.ts`](./src/theme.ts) re-exports the same tokens for runtime use.
|
|
66
62
|
|
|
67
63
|
## Use
|
|
68
64
|
|
|
@@ -90,13 +86,10 @@ export function Settings() {
|
|
|
90
86
|
|
|
91
87
|
## Develop
|
|
92
88
|
|
|
93
|
-
There is no library build step — consumers transform the TypeScript source directly. `npm run typecheck` is the only "build-like" command for the lib itself.
|
|
94
|
-
|
|
95
|
-
Two demo apps live under `apps/`:
|
|
96
|
-
|
|
97
89
|
```sh
|
|
98
90
|
# library
|
|
99
91
|
npm install
|
|
92
|
+
npm run build # produces dist/{web,native,types}
|
|
100
93
|
npm run typecheck
|
|
101
94
|
|
|
102
95
|
# web Storybook (Vite-powered)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { css, html } from 'react-strict-dom';
|
|
3
|
+
import { spacing } from '../tokens.css';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
/**
|
|
6
|
+
* Layout primitive — a flex container, the building block for everything else.
|
|
7
|
+
* Adwaita-inspired apps lean heavily on simple horizontal/vertical stacks.
|
|
8
|
+
*/
|
|
9
|
+
export function Box(props) {
|
|
10
|
+
const {
|
|
11
|
+
children,
|
|
12
|
+
direction = 'column',
|
|
13
|
+
gap,
|
|
14
|
+
padding,
|
|
15
|
+
align,
|
|
16
|
+
justify,
|
|
17
|
+
grow,
|
|
18
|
+
wrap,
|
|
19
|
+
style
|
|
20
|
+
} = props;
|
|
21
|
+
return /*#__PURE__*/_jsx(html.div, {
|
|
22
|
+
style: [styles.base, direction === 'row' ? styles.row : styles.column, wrap && styles.wrap, grow && styles.grow, align != null && alignStyles[align], justify != null && justifyStyles[justify], gap != null && gapStyles[gap], padding != null && paddingStyles[padding], style],
|
|
23
|
+
children: children
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const styles = css.create({
|
|
27
|
+
base: {
|
|
28
|
+
display: 'flex',
|
|
29
|
+
minWidth: 0
|
|
30
|
+
},
|
|
31
|
+
row: {
|
|
32
|
+
flexDirection: 'row'
|
|
33
|
+
},
|
|
34
|
+
column: {
|
|
35
|
+
flexDirection: 'column'
|
|
36
|
+
},
|
|
37
|
+
wrap: {
|
|
38
|
+
flexWrap: 'wrap'
|
|
39
|
+
},
|
|
40
|
+
grow: {
|
|
41
|
+
flexGrow: 1
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const alignStyles = css.create({
|
|
45
|
+
'flex-start': {
|
|
46
|
+
alignItems: 'flex-start'
|
|
47
|
+
},
|
|
48
|
+
center: {
|
|
49
|
+
alignItems: 'center'
|
|
50
|
+
},
|
|
51
|
+
'flex-end': {
|
|
52
|
+
alignItems: 'flex-end'
|
|
53
|
+
},
|
|
54
|
+
stretch: {
|
|
55
|
+
alignItems: 'stretch'
|
|
56
|
+
},
|
|
57
|
+
baseline: {
|
|
58
|
+
alignItems: 'baseline'
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const justifyStyles = css.create({
|
|
62
|
+
'flex-start': {
|
|
63
|
+
justifyContent: 'flex-start'
|
|
64
|
+
},
|
|
65
|
+
center: {
|
|
66
|
+
justifyContent: 'center'
|
|
67
|
+
},
|
|
68
|
+
'flex-end': {
|
|
69
|
+
justifyContent: 'flex-end'
|
|
70
|
+
},
|
|
71
|
+
'space-between': {
|
|
72
|
+
justifyContent: 'space-between'
|
|
73
|
+
},
|
|
74
|
+
'space-around': {
|
|
75
|
+
justifyContent: 'space-around'
|
|
76
|
+
},
|
|
77
|
+
'space-evenly': {
|
|
78
|
+
justifyContent: 'space-evenly'
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const gapStyles = css.create({
|
|
82
|
+
xs: {
|
|
83
|
+
gap: spacing.xs
|
|
84
|
+
},
|
|
85
|
+
sm: {
|
|
86
|
+
gap: spacing.sm
|
|
87
|
+
},
|
|
88
|
+
md: {
|
|
89
|
+
gap: spacing.md
|
|
90
|
+
},
|
|
91
|
+
lg: {
|
|
92
|
+
gap: spacing.lg
|
|
93
|
+
},
|
|
94
|
+
xl: {
|
|
95
|
+
gap: spacing.xl
|
|
96
|
+
},
|
|
97
|
+
xxl: {
|
|
98
|
+
gap: spacing.xxl
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const paddingStyles = css.create({
|
|
102
|
+
xs: {
|
|
103
|
+
padding: spacing.xs
|
|
104
|
+
},
|
|
105
|
+
sm: {
|
|
106
|
+
padding: spacing.sm
|
|
107
|
+
},
|
|
108
|
+
md: {
|
|
109
|
+
padding: spacing.md
|
|
110
|
+
},
|
|
111
|
+
lg: {
|
|
112
|
+
padding: spacing.lg
|
|
113
|
+
},
|
|
114
|
+
xl: {
|
|
115
|
+
padding: spacing.xl
|
|
116
|
+
},
|
|
117
|
+
xxl: {
|
|
118
|
+
padding: spacing.xxl
|
|
119
|
+
}
|
|
120
|
+
});
|
|
@@ -1,26 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { css, html } from 'react-strict-dom';
|
|
3
3
|
import { palette, radius, spacing, typography, motion } from '../tokens.css';
|
|
4
|
-
|
|
5
|
-
export type ButtonVariant =
|
|
6
|
-
| 'default'
|
|
7
|
-
| 'suggested'
|
|
8
|
-
| 'destructive'
|
|
9
|
-
| 'flat'
|
|
10
|
-
| 'pill';
|
|
11
|
-
|
|
12
|
-
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
13
|
-
|
|
14
|
-
export type ButtonProps = {
|
|
15
|
-
children?: React.ReactNode;
|
|
16
|
-
variant?: ButtonVariant;
|
|
17
|
-
size?: ButtonSize;
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
fullWidth?: boolean;
|
|
20
|
-
onPress?: () => void;
|
|
21
|
-
type?: 'button' | 'submit';
|
|
22
|
-
};
|
|
23
|
-
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
5
|
/**
|
|
25
6
|
* Adwaita-style button. Variants follow libadwaita conventions:
|
|
26
7
|
* - default: flat-ish neutral surface
|
|
@@ -29,7 +10,7 @@ export type ButtonProps = {
|
|
|
29
10
|
* - flat: no background, only on hover
|
|
30
11
|
* - pill: fully rounded (Adwaita "circular" buttons)
|
|
31
12
|
*/
|
|
32
|
-
export function Button(props
|
|
13
|
+
export function Button(props) {
|
|
33
14
|
const {
|
|
34
15
|
children,
|
|
35
16
|
variant = 'default',
|
|
@@ -39,27 +20,17 @@ export function Button(props: ButtonProps) {
|
|
|
39
20
|
onPress,
|
|
40
21
|
type = 'button'
|
|
41
22
|
} = props;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
style
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
fullWidth && styles.fullWidth,
|
|
53
|
-
disabled && styles.disabled
|
|
54
|
-
]}
|
|
55
|
-
>
|
|
56
|
-
<html.span style={[styles.label, labelSizeStyles[size]]}>
|
|
57
|
-
{children}
|
|
58
|
-
</html.span>
|
|
59
|
-
</html.button>
|
|
60
|
-
);
|
|
23
|
+
return /*#__PURE__*/_jsx(html.button, {
|
|
24
|
+
type: type,
|
|
25
|
+
disabled: disabled,
|
|
26
|
+
onClick: onPress,
|
|
27
|
+
style: [styles.base, sizeStyles[size], variantStyles[variant], fullWidth && styles.fullWidth, disabled && styles.disabled],
|
|
28
|
+
children: /*#__PURE__*/_jsx(html.span, {
|
|
29
|
+
style: [styles.label, labelSizeStyles[size]],
|
|
30
|
+
children: children
|
|
31
|
+
})
|
|
32
|
+
});
|
|
61
33
|
}
|
|
62
|
-
|
|
63
34
|
const styles = css.create({
|
|
64
35
|
base: {
|
|
65
36
|
display: 'flex',
|
|
@@ -79,10 +50,14 @@ const styles = css.create({
|
|
|
79
50
|
fontWeight: typography.weightStrong,
|
|
80
51
|
textAlign: 'center'
|
|
81
52
|
},
|
|
82
|
-
fullWidth: {
|
|
83
|
-
|
|
53
|
+
fullWidth: {
|
|
54
|
+
alignSelf: 'stretch'
|
|
55
|
+
},
|
|
56
|
+
disabled: {
|
|
57
|
+
opacity: 0.5,
|
|
58
|
+
cursor: 'not-allowed'
|
|
59
|
+
}
|
|
84
60
|
});
|
|
85
|
-
|
|
86
61
|
const sizeStyles = css.create({
|
|
87
62
|
sm: {
|
|
88
63
|
paddingInline: spacing.md,
|
|
@@ -100,13 +75,20 @@ const sizeStyles = css.create({
|
|
|
100
75
|
height: 44
|
|
101
76
|
}
|
|
102
77
|
});
|
|
103
|
-
|
|
104
78
|
const labelSizeStyles = css.create({
|
|
105
|
-
sm: {
|
|
106
|
-
|
|
107
|
-
|
|
79
|
+
sm: {
|
|
80
|
+
fontSize: typography.captionSize,
|
|
81
|
+
lineHeight: typography.captionLineHeight
|
|
82
|
+
},
|
|
83
|
+
md: {
|
|
84
|
+
fontSize: typography.bodySize,
|
|
85
|
+
lineHeight: typography.bodyLineHeight
|
|
86
|
+
},
|
|
87
|
+
lg: {
|
|
88
|
+
fontSize: typography.title4Size,
|
|
89
|
+
lineHeight: typography.title4LineHeight
|
|
90
|
+
}
|
|
108
91
|
});
|
|
109
|
-
|
|
110
92
|
const variantStyles = css.create({
|
|
111
93
|
default: {
|
|
112
94
|
backgroundColor: {
|
|
@@ -150,4 +132,4 @@ const variantStyles = css.create({
|
|
|
150
132
|
borderRadius: radius.pill,
|
|
151
133
|
paddingInline: spacing.xl
|
|
152
134
|
}
|
|
153
|
-
});
|
|
135
|
+
});
|
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { css, html } from 'react-strict-dom';
|
|
3
3
|
import { palette, radius, spacing, typography } from '../tokens.css';
|
|
4
|
-
|
|
5
|
-
export type CardProps = {
|
|
6
|
-
children?: React.ReactNode;
|
|
7
|
-
title?: React.ReactNode;
|
|
8
|
-
/** "boxed" matches AdwBoxedList — solid surface w/ visible border. */
|
|
9
|
-
variant?: 'boxed' | 'flat';
|
|
10
|
-
padding?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
5
|
/**
|
|
14
6
|
* Adwaita-style card surface. Default has a soft shadow + rounded corners;
|
|
15
7
|
* "flat" drops the shadow for use inside other surfaces.
|
|
16
8
|
*/
|
|
17
|
-
export function Card(props
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
9
|
+
export function Card(props) {
|
|
10
|
+
const {
|
|
11
|
+
children,
|
|
12
|
+
title,
|
|
13
|
+
variant = 'boxed',
|
|
14
|
+
padding = true
|
|
15
|
+
} = props;
|
|
16
|
+
return /*#__PURE__*/_jsxs(html.div, {
|
|
17
|
+
style: [styles.card, variant === 'boxed' ? styles.boxed : styles.flat],
|
|
18
|
+
children: [title != null && /*#__PURE__*/_jsx(html.div, {
|
|
19
|
+
style: styles.header,
|
|
20
|
+
children: /*#__PURE__*/_jsx(html.h3, {
|
|
21
|
+
style: styles.titleText,
|
|
22
|
+
children: title
|
|
23
|
+
})
|
|
24
|
+
}), /*#__PURE__*/_jsx(html.div, {
|
|
25
|
+
style: padding ? styles.body : null,
|
|
26
|
+
children: children
|
|
27
|
+
})]
|
|
28
|
+
});
|
|
30
29
|
}
|
|
31
|
-
|
|
32
30
|
const styles = css.create({
|
|
33
31
|
card: {
|
|
34
32
|
backgroundColor: palette.cardBg,
|
|
@@ -63,5 +61,7 @@ const styles = css.create({
|
|
|
63
61
|
fontWeight: typography.weightBold,
|
|
64
62
|
color: palette.fg
|
|
65
63
|
},
|
|
66
|
-
body: {
|
|
67
|
-
|
|
64
|
+
body: {
|
|
65
|
+
padding: spacing.lg
|
|
66
|
+
}
|
|
67
|
+
});
|
|
@@ -1,63 +1,53 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { css, html } from 'react-strict-dom';
|
|
3
3
|
import { palette, radius, motion, typography, spacing } from '../tokens.css';
|
|
4
|
-
|
|
5
|
-
export type CheckboxProps = {
|
|
6
|
-
checked: boolean;
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
onChange?: (checked: boolean) => void;
|
|
9
|
-
label?: React.ReactNode;
|
|
10
|
-
};
|
|
11
|
-
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
5
|
/**
|
|
13
6
|
* Adwaita-style checkbox. Solid blue square with a unicode check when on,
|
|
14
7
|
* subtle outlined square when off.
|
|
15
8
|
*/
|
|
16
|
-
export function Checkbox(props
|
|
17
|
-
const {
|
|
18
|
-
|
|
9
|
+
export function Checkbox(props) {
|
|
10
|
+
const {
|
|
11
|
+
checked,
|
|
12
|
+
disabled = false,
|
|
13
|
+
onChange,
|
|
14
|
+
label
|
|
15
|
+
} = props;
|
|
19
16
|
const toggle = () => {
|
|
20
17
|
if (!disabled) onChange?.(!checked);
|
|
21
18
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
const box = /*#__PURE__*/_jsx(html.span, {
|
|
20
|
+
style: [styles.box, checked ? styles.boxOn : styles.boxOff],
|
|
21
|
+
children: checked && /*#__PURE__*/_jsx(html.span, {
|
|
22
|
+
style: styles.check,
|
|
23
|
+
children: '✓'
|
|
24
|
+
})
|
|
25
|
+
});
|
|
29
26
|
if (label == null) {
|
|
30
|
-
return (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{box}
|
|
40
|
-
</html.button>
|
|
41
|
-
);
|
|
27
|
+
return /*#__PURE__*/_jsx(html.button, {
|
|
28
|
+
type: "button",
|
|
29
|
+
role: "checkbox",
|
|
30
|
+
"aria-checked": checked,
|
|
31
|
+
disabled: disabled,
|
|
32
|
+
onClick: toggle,
|
|
33
|
+
style: [styles.bareButton, disabled && styles.disabled],
|
|
34
|
+
children: box
|
|
35
|
+
});
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
style
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
</html.button>
|
|
56
|
-
);
|
|
37
|
+
return /*#__PURE__*/_jsxs(html.button, {
|
|
38
|
+
type: "button",
|
|
39
|
+
role: "checkbox",
|
|
40
|
+
"aria-checked": checked,
|
|
41
|
+
disabled: disabled,
|
|
42
|
+
onClick: toggle,
|
|
43
|
+
style: [styles.row, disabled && styles.disabled],
|
|
44
|
+
children: [box, /*#__PURE__*/_jsx(html.span, {
|
|
45
|
+
style: styles.label,
|
|
46
|
+
children: label
|
|
47
|
+
})]
|
|
48
|
+
});
|
|
57
49
|
}
|
|
58
|
-
|
|
59
50
|
const SIZE = 18;
|
|
60
|
-
|
|
61
51
|
const styles = css.create({
|
|
62
52
|
bareButton: {
|
|
63
53
|
backgroundColor: 'transparent',
|
|
@@ -115,5 +105,8 @@ const styles = css.create({
|
|
|
115
105
|
fontSize: typography.bodySize,
|
|
116
106
|
lineHeight: typography.bodyLineHeight
|
|
117
107
|
},
|
|
118
|
-
disabled: {
|
|
119
|
-
|
|
108
|
+
disabled: {
|
|
109
|
+
opacity: 0.5,
|
|
110
|
+
cursor: 'not-allowed'
|
|
111
|
+
}
|
|
112
|
+
});
|
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { css, html } from 'react-strict-dom';
|
|
3
3
|
import { palette, radius, spacing, typography, motion } from '../tokens.css';
|
|
4
|
-
|
|
5
|
-
export type EntryProps = {
|
|
6
|
-
value?: string;
|
|
7
|
-
defaultValue?: string;
|
|
8
|
-
placeholder?: string;
|
|
9
|
-
disabled?: boolean;
|
|
10
|
-
readOnly?: boolean;
|
|
11
|
-
invalid?: boolean;
|
|
12
|
-
type?: 'text' | 'password' | 'email' | 'search' | 'tel' | 'url' | 'number';
|
|
13
|
-
onChange?: (value: string) => void;
|
|
14
|
-
onSubmit?: (value: string) => void;
|
|
15
|
-
};
|
|
16
|
-
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
5
|
/**
|
|
18
6
|
* Adwaita-style text entry. Underline focus indicator + subtle filled surface,
|
|
19
7
|
* like libadwaita's `AdwEntry`.
|
|
20
8
|
*/
|
|
21
|
-
export function Entry(props
|
|
9
|
+
export function Entry(props) {
|
|
22
10
|
const {
|
|
23
11
|
value,
|
|
24
12
|
defaultValue,
|
|
@@ -30,33 +18,24 @@ export function Entry(props: EntryProps) {
|
|
|
30
18
|
onChange,
|
|
31
19
|
onSubmit
|
|
32
20
|
} = props;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}}
|
|
51
|
-
style={[
|
|
52
|
-
styles.input,
|
|
53
|
-
invalid && styles.invalid,
|
|
54
|
-
disabled && styles.disabled
|
|
55
|
-
]}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
21
|
+
const latestValueRef = React.useRef(value ?? defaultValue ?? '');
|
|
22
|
+
return /*#__PURE__*/_jsx(html.input, {
|
|
23
|
+
type: type,
|
|
24
|
+
value: value,
|
|
25
|
+
defaultValue: defaultValue,
|
|
26
|
+
placeholder: placeholder,
|
|
27
|
+
disabled: disabled,
|
|
28
|
+
readOnly: readOnly,
|
|
29
|
+
onChange: e => {
|
|
30
|
+
latestValueRef.current = e.target.value;
|
|
31
|
+
onChange?.(e.target.value);
|
|
32
|
+
},
|
|
33
|
+
onKeyDown: e => {
|
|
34
|
+
if (e.key === 'Enter') onSubmit?.(latestValueRef.current);
|
|
35
|
+
},
|
|
36
|
+
style: [styles.input, invalid && styles.invalid, disabled && styles.disabled]
|
|
37
|
+
});
|
|
58
38
|
}
|
|
59
|
-
|
|
60
39
|
const styles = css.create({
|
|
61
40
|
input: {
|
|
62
41
|
backgroundColor: palette.subtleBg,
|
|
@@ -90,5 +69,8 @@ const styles = css.create({
|
|
|
90
69
|
':focus': palette.destructiveBg
|
|
91
70
|
}
|
|
92
71
|
},
|
|
93
|
-
disabled: {
|
|
94
|
-
|
|
72
|
+
disabled: {
|
|
73
|
+
opacity: 0.5,
|
|
74
|
+
cursor: 'not-allowed'
|
|
75
|
+
}
|
|
76
|
+
});
|
|
@@ -1,40 +1,39 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { css, html } from 'react-strict-dom';
|
|
3
3
|
import { palette, spacing, typography } from '../tokens.css';
|
|
4
|
-
|
|
5
|
-
export type HeaderBarProps = {
|
|
6
|
-
title?: React.ReactNode;
|
|
7
|
-
subtitle?: React.ReactNode;
|
|
8
|
-
/** Buttons / actions to place at the start (left) of the bar. */
|
|
9
|
-
start?: React.ReactNode;
|
|
10
|
-
/** Buttons / actions to place at the end (right) of the bar. */
|
|
11
|
-
end?: React.ReactNode;
|
|
12
|
-
};
|
|
13
|
-
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
5
|
/**
|
|
15
6
|
* Top-level header bar matching libadwaita's AdwHeaderBar — a thin titled
|
|
16
7
|
* strip that sits at the top of a window. Centered title with optional
|
|
17
8
|
* leading/trailing slots.
|
|
18
9
|
*/
|
|
19
|
-
export function HeaderBar(props
|
|
20
|
-
const {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
10
|
+
export function HeaderBar(props) {
|
|
11
|
+
const {
|
|
12
|
+
title,
|
|
13
|
+
subtitle,
|
|
14
|
+
start,
|
|
15
|
+
end
|
|
16
|
+
} = props;
|
|
17
|
+
return /*#__PURE__*/_jsxs(html.header, {
|
|
18
|
+
style: styles.bar,
|
|
19
|
+
children: [/*#__PURE__*/_jsx(html.div, {
|
|
20
|
+
style: styles.side,
|
|
21
|
+
children: start
|
|
22
|
+
}), /*#__PURE__*/_jsxs(html.div, {
|
|
23
|
+
style: styles.titleBlock,
|
|
24
|
+
children: [title != null && /*#__PURE__*/_jsx(html.span, {
|
|
25
|
+
style: styles.title,
|
|
26
|
+
children: title
|
|
27
|
+
}), subtitle != null && /*#__PURE__*/_jsx(html.span, {
|
|
28
|
+
style: styles.subtitle,
|
|
29
|
+
children: subtitle
|
|
30
|
+
})]
|
|
31
|
+
}), /*#__PURE__*/_jsx(html.div, {
|
|
32
|
+
style: [styles.side, styles.sideEnd],
|
|
33
|
+
children: end
|
|
34
|
+
})]
|
|
35
|
+
});
|
|
36
36
|
}
|
|
37
|
-
|
|
38
37
|
const styles = css.create({
|
|
39
38
|
bar: {
|
|
40
39
|
display: 'flex',
|
|
@@ -57,7 +56,9 @@ const styles = css.create({
|
|
|
57
56
|
flexBasis: 0,
|
|
58
57
|
flexGrow: 1
|
|
59
58
|
},
|
|
60
|
-
sideEnd: {
|
|
59
|
+
sideEnd: {
|
|
60
|
+
justifyContent: 'flex-end'
|
|
61
|
+
},
|
|
61
62
|
titleBlock: {
|
|
62
63
|
display: 'flex',
|
|
63
64
|
flexDirection: 'column',
|
|
@@ -75,4 +76,4 @@ const styles = css.create({
|
|
|
75
76
|
fontSize: typography.captionSize,
|
|
76
77
|
color: palette.fgMuted
|
|
77
78
|
}
|
|
78
|
-
});
|
|
79
|
+
});
|