@sublimee/auth-ui 0.1.1 → 0.1.13
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/AI_INDEX.md +64 -0
- package/README.md +80 -120
- package/dist/animations.css +52 -0
- package/dist/index.d.mts +59 -42
- package/dist/index.d.ts +59 -42
- package/dist/index.js +443 -56
- package/dist/index.mjs +441 -54
- package/package.json +9 -6
- package/src/animations.css +52 -0
- package/src/base-button.stories.tsx +96 -0
- package/src/base-button.tsx +124 -0
- package/src/button-loading-indicator.tsx +33 -0
- package/src/icons.tsx +17 -24
- package/src/index.ts +25 -19
- package/src/oauth-button.stories.tsx +72 -333
- package/src/oauth-button.tsx +34 -79
- package/src/runtime-styles.ts +225 -0
- package/src/types.ts +66 -10
- package/src/use-button-animation.ts +114 -0
package/AI_INDEX.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @sublimee/auth-ui AI Index
|
|
2
|
+
|
|
3
|
+
Token-efficient entry point for AI agents reading the installed npm package.
|
|
4
|
+
|
|
5
|
+
## Use This Package For
|
|
6
|
+
|
|
7
|
+
- ready-to-use OAuth buttons,
|
|
8
|
+
- built-in button motion and loading,
|
|
9
|
+
- token-driven button customization without rebuilding base styling.
|
|
10
|
+
|
|
11
|
+
## First Move
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import "@sublimee/tokens/tokens.css";
|
|
15
|
+
import { OAuthButton } from "@sublimee/auth-ui";
|
|
16
|
+
|
|
17
|
+
<OAuthButton provider="google" />
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Current Public Surface
|
|
21
|
+
|
|
22
|
+
- `OAuthButton`
|
|
23
|
+
- `GoogleIcon`
|
|
24
|
+
- `DiscordIcon`
|
|
25
|
+
- `useButtonAnimation`
|
|
26
|
+
|
|
27
|
+
Current providers:
|
|
28
|
+
- `google`
|
|
29
|
+
- `discord`
|
|
30
|
+
|
|
31
|
+
## Important Defaults
|
|
32
|
+
|
|
33
|
+
- built on `@base-ui/react/button`
|
|
34
|
+
- default variant: `secondary`
|
|
35
|
+
- default animation: `press`
|
|
36
|
+
- loading is built in
|
|
37
|
+
- default loading animation: `spinner`
|
|
38
|
+
- runtime button styles are included automatically
|
|
39
|
+
|
|
40
|
+
## Key Props
|
|
41
|
+
|
|
42
|
+
- `provider`
|
|
43
|
+
- `variant`
|
|
44
|
+
- `animation`
|
|
45
|
+
- `loading`
|
|
46
|
+
- `loadingAnimation`
|
|
47
|
+
- `disabled`
|
|
48
|
+
- `className`
|
|
49
|
+
- `children`
|
|
50
|
+
|
|
51
|
+
## Read Next
|
|
52
|
+
|
|
53
|
+
1. [README.md](./README.md)
|
|
54
|
+
2. [src/types.ts](./src/types.ts)
|
|
55
|
+
3. [src/oauth-button.tsx](./src/oauth-button.tsx)
|
|
56
|
+
4. [src/base-button.tsx](./src/base-button.tsx)
|
|
57
|
+
5. [src/runtime-styles.ts](./src/runtime-styles.ts)
|
|
58
|
+
|
|
59
|
+
## Non-Goals
|
|
60
|
+
|
|
61
|
+
Do not assume:
|
|
62
|
+
- this package is headless,
|
|
63
|
+
- the consumer must import extra component CSS for the normal path,
|
|
64
|
+
- the consumer should rebuild spacing, border, or focus behavior from scratch.
|
package/README.md
CHANGED
|
@@ -1,169 +1,129 @@
|
|
|
1
1
|
# @sublimee/auth-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI-first package doc for Sublime auth components.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
If you are an AI agent reading the installed npm package directly, start with [AI_INDEX.md](./AI_INDEX.md).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Use This Package When
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- you need a ready-to-use OAuth button,
|
|
10
|
+
- you want built-in structure, motion, loading, and accessibility defaults,
|
|
11
|
+
- you want token-driven customization instead of rebuilding button styles from scratch.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
- ✅ **We DON'T impose visual opinions** — you control 100% of styling via Tailwind `className`
|
|
13
|
-
- ✅ **You get a solid, accessible foundation** that looks exactly how you want
|
|
13
|
+
## First Move
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
```tsx
|
|
16
|
+
import "@sublimee/tokens/tokens.css";
|
|
17
|
+
import { OAuthButton } from "@sublimee/auth-ui";
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
pnpm add @sublimee/auth-ui
|
|
19
|
+
<OAuthButton provider="google" />
|
|
21
20
|
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
The package injects its runtime button styles automatically. No extra component stylesheet import is required for the normal path.
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
- `react` ^19.0.0
|
|
27
|
-
- `react-dom` ^19.0.0
|
|
24
|
+
## Current Public Surface
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
### Components
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
- `OAuthButton`
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
### Other exports
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
- `GoogleIcon`
|
|
33
|
+
- `DiscordIcon`
|
|
34
|
+
- `useButtonAnimation`
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
<OAuthButton
|
|
40
|
-
provider="google"
|
|
41
|
-
onClick={signInWithGoogle}
|
|
42
|
-
className="flex items-center gap-3 px-6 py-3 bg-white text-gray-900 rounded-lg font-medium"
|
|
43
|
-
/>
|
|
36
|
+
### Current providers
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
provider="discord"
|
|
48
|
-
onClick={signInWithDiscord}
|
|
49
|
-
className="flex items-center gap-3 px-6 py-3 border border-white/20 text-white rounded-lg hover:bg-white/5"
|
|
50
|
-
/>
|
|
38
|
+
- `google`
|
|
39
|
+
- `discord`
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
<OAuthButton
|
|
54
|
-
provider="google"
|
|
55
|
-
onClick={signInWithGoogle}
|
|
56
|
-
className="p-3 rounded-full bg-white/10 hover:bg-white/20 transition-colors"
|
|
57
|
-
>
|
|
58
|
-
{null}
|
|
59
|
-
</OAuthButton>
|
|
41
|
+
## Important Defaults
|
|
60
42
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
43
|
+
- built on `@base-ui/react/button`
|
|
44
|
+
- default variant: `secondary`
|
|
45
|
+
- default interaction motion: `press`
|
|
46
|
+
- loading is built in
|
|
47
|
+
- default loading animation: `spinner`
|
|
48
|
+
- focus styling is semantic-token driven
|
|
67
49
|
|
|
68
|
-
|
|
50
|
+
## Primary API
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
69
53
|
<OAuthButton
|
|
70
54
|
provider="google"
|
|
71
|
-
|
|
72
|
-
|
|
55
|
+
variant="secondary"
|
|
56
|
+
loading={false}
|
|
57
|
+
disabled={false}
|
|
73
58
|
>
|
|
74
|
-
|
|
59
|
+
Continuar con Google
|
|
75
60
|
</OAuthButton>
|
|
76
61
|
```
|
|
77
62
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
|
81
|
-
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `disabled` | `boolean` | `false` |
|
|
86
|
-
| `className` | `string` | - |
|
|
87
|
-
| `children` | `ReactNode` | provider
|
|
88
|
-
|
|
89
|
-
#### Sensible defaults we provide
|
|
63
|
+
| Prop | Type | Default | Meaning |
|
|
64
|
+
|------|------|---------|---------|
|
|
65
|
+
| `provider` | `'google' \| 'discord'` | required | OAuth provider |
|
|
66
|
+
| `variant` | `'primary' \| 'secondary'` | `'secondary'` | emphasis level |
|
|
67
|
+
| `animation` | `'press'` | `'press'` | interaction motion |
|
|
68
|
+
| `loading` | `boolean` | `false` | shows loading UI and disables interaction |
|
|
69
|
+
| `loadingAnimation` | `'spinner'` | `'spinner'` | loading indicator |
|
|
70
|
+
| `disabled` | `boolean` | `false` | disables interaction |
|
|
71
|
+
| `className` | `string` | - | later override hook |
|
|
72
|
+
| `children` | `ReactNode` | provider label | custom content; pass `{null}` for icon-only |
|
|
90
73
|
|
|
91
|
-
|
|
74
|
+
## Task Routing
|
|
92
75
|
|
|
93
|
-
|
|
94
|
-
|----------|------------|
|
|
95
|
-
| `cursor: pointer` on hover | ✅ |
|
|
96
|
-
| `cursor: not-allowed` when disabled/loading | ✅ |
|
|
97
|
-
| **Focus visible states** via base-ui | ✅ |
|
|
98
|
-
| **Keyboard navigation** via base-ui | ✅ |
|
|
99
|
-
| **ARIA attributes** via base-ui | ✅ |
|
|
100
|
-
| **Disabled state handling** via base-ui | ✅ |
|
|
101
|
-
|
|
102
|
-
You don't need to add `cursor-pointer` to your className — it's automatic. Your `className` is merged with our sensible defaults, with your styles taking precedence.
|
|
103
|
-
|
|
104
|
-
### Icons
|
|
105
|
-
|
|
106
|
-
Individual icons are also exported if you need them separately:
|
|
76
|
+
### Google auth button
|
|
107
77
|
|
|
108
78
|
```tsx
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<GoogleIcon size={24} className="text-red-500" />
|
|
112
|
-
<DiscordIcon size={20} />
|
|
113
|
-
<SpinnerIcon size={16} className="animate-spin" />
|
|
79
|
+
<OAuthButton provider="google" />
|
|
114
80
|
```
|
|
115
81
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Since components are headless, you provide all styles via `className`. Here are recommended patterns:
|
|
119
|
-
|
|
120
|
-
### Common Patterns
|
|
82
|
+
### Primary call to action
|
|
121
83
|
|
|
122
84
|
```tsx
|
|
123
|
-
|
|
124
|
-
className="w-full flex items-center justify-center gap-3 px-6 py-3 bg-white text-gray-900 rounded-lg"
|
|
125
|
-
|
|
126
|
-
// Minimal icon button
|
|
127
|
-
className="p-2 rounded-full hover:bg-white/10 transition-colors"
|
|
128
|
-
|
|
129
|
-
// Outline variant
|
|
130
|
-
className="flex items-center gap-2 px-4 py-2 border border-current rounded-md hover:bg-white/5"
|
|
131
|
-
|
|
132
|
-
// Loading state
|
|
133
|
-
className="opacity-50 cursor-wait"
|
|
85
|
+
<OAuthButton provider="google" variant="primary" />
|
|
134
86
|
```
|
|
135
87
|
|
|
136
|
-
###
|
|
137
|
-
|
|
138
|
-
The component accepts a `disabled` prop and renders in a loading state when `loading={true}`. These states automatically get `cursor: not-allowed` from base-ui, but you may want to add visual indicators:
|
|
88
|
+
### Loading state
|
|
139
89
|
|
|
140
90
|
```tsx
|
|
141
|
-
<OAuthButton
|
|
142
|
-
provider="google"
|
|
143
|
-
loading={isLoading}
|
|
144
|
-
disabled={isLoading}
|
|
145
|
-
className={`flex items-center gap-3 px-6 py-3 rounded-lg ${
|
|
146
|
-
isLoading ? 'opacity-50' : 'hover:bg-gray-50'
|
|
147
|
-
}`}
|
|
148
|
-
/>
|
|
91
|
+
<OAuthButton provider="google" loading />
|
|
149
92
|
```
|
|
150
93
|
|
|
151
|
-
##
|
|
94
|
+
## Customization Order
|
|
152
95
|
|
|
153
|
-
|
|
96
|
+
Use this order:
|
|
97
|
+
1. import tokens
|
|
98
|
+
2. override semantic CSS custom properties
|
|
99
|
+
3. use props like `variant`, `loading`, and `disabled`
|
|
100
|
+
4. use `className` only for edge-case local adjustments
|
|
154
101
|
|
|
155
|
-
|
|
156
|
-
|
|
102
|
+
Example:
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
@import "@sublimee/tokens/tokens.css";
|
|
106
|
+
|
|
107
|
+
:root {
|
|
108
|
+
--sublime-color-interactive-primary: #ec4899;
|
|
109
|
+
--sublime-color-interactive-primary-hover: #db2777;
|
|
110
|
+
--sublime-color-focus-ring: #ec4899;
|
|
111
|
+
--sublime-radius-button: 9999px;
|
|
112
|
+
}
|
|
157
113
|
```
|
|
158
114
|
|
|
159
|
-
##
|
|
115
|
+
## Zero-Setup Contract
|
|
116
|
+
|
|
117
|
+
For this package, zero-setup means:
|
|
118
|
+
- the button should look like a button on first render,
|
|
119
|
+
- provider icon and layout should be built in,
|
|
120
|
+
- the consumer should not rebuild spacing, border, focus, or interaction states,
|
|
121
|
+
- customization should extend the component rather than complete it.
|
|
160
122
|
|
|
161
|
-
|
|
123
|
+
## Notes
|
|
162
124
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
3. **Headless by design** — Complete control over styling
|
|
166
|
-
4. **Production-tested** — Built by the MUI team, battle-tested at scale
|
|
125
|
+
- `@sublimee/auth-ui/animations.css` still exists as a legacy optional export, but the normal path should not require it.
|
|
126
|
+
- Public-facing default copy is currently Spanish.
|
|
167
127
|
|
|
168
128
|
## License
|
|
169
129
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sublimee/auth-ui runtime animations
|
|
3
|
+
*
|
|
4
|
+
* Optional legacy export.
|
|
5
|
+
* Most consumers should not need to import this file because auth-ui now
|
|
6
|
+
* injects its runtime button styles automatically.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@keyframes sublime-button-press-release {
|
|
10
|
+
0% {
|
|
11
|
+
transform: translateY(1px) scale(0.985);
|
|
12
|
+
box-shadow: var(--sublime-button-shadow-active);
|
|
13
|
+
}
|
|
14
|
+
100% {
|
|
15
|
+
transform: translateY(0) scale(1);
|
|
16
|
+
box-shadow: var(--sublime-button-shadow);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@keyframes sublime-button-spinner {
|
|
21
|
+
from {
|
|
22
|
+
transform: rotate(0deg);
|
|
23
|
+
}
|
|
24
|
+
to {
|
|
25
|
+
transform: rotate(360deg);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.sublime-button-pressed {
|
|
30
|
+
transform: translateY(1px) scale(0.985);
|
|
31
|
+
box-shadow: var(--sublime-button-shadow-active);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.animate-sublime-button-press-release {
|
|
35
|
+
animation: sublime-button-press-release 180ms var(--sublime-ease-out, cubic-bezier(0, 0, 0.2, 1));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sublime-button__spinner {
|
|
39
|
+
animation: sublime-button-spinner 720ms linear infinite;
|
|
40
|
+
transform-origin: center;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (prefers-reduced-motion: reduce) {
|
|
44
|
+
.animate-sublime-button-press-release {
|
|
45
|
+
animation-duration: 0.01ms !important;
|
|
46
|
+
animation-iteration-count: 1 !important;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sublime-button__spinner {
|
|
50
|
+
animation-duration: 1.6s !important;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,88 +1,105 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, MouseEventHandler, ReactNode } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
type OAuthProvider = 'google' | 'discord';
|
|
6
|
+
type ButtonVariant = 'primary' | 'secondary';
|
|
7
|
+
type ButtonAnimation = 'press';
|
|
8
|
+
type ButtonLoadingAnimation = 'spinner';
|
|
6
9
|
interface OAuthButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
7
10
|
/**
|
|
8
|
-
* The OAuth provider to authenticate with
|
|
11
|
+
* The OAuth provider to authenticate with.
|
|
9
12
|
*/
|
|
10
13
|
provider: OAuthProvider;
|
|
11
14
|
/**
|
|
12
|
-
* Click handler - typically calls supabase.auth.signInWithOAuth
|
|
15
|
+
* Click handler - typically calls supabase.auth.signInWithOAuth.
|
|
13
16
|
*/
|
|
14
|
-
onClick?:
|
|
17
|
+
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
15
18
|
/**
|
|
16
|
-
* Loading state - shows
|
|
19
|
+
* Loading state - shows the configured loading animation and disables interaction.
|
|
17
20
|
*/
|
|
18
21
|
loading?: boolean;
|
|
19
22
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
23
|
+
* Loading animation shown while `loading` is true.
|
|
24
|
+
* @default 'spinner'
|
|
25
|
+
*/
|
|
26
|
+
loadingAnimation?: ButtonLoadingAnimation;
|
|
27
|
+
/**
|
|
28
|
+
* Visual variant of the button.
|
|
29
|
+
* - primary: High emphasis, filled background
|
|
30
|
+
* - secondary: Medium emphasis, bordered (default)
|
|
31
|
+
* @default 'secondary'
|
|
32
|
+
*/
|
|
33
|
+
variant?: ButtonVariant;
|
|
34
|
+
/**
|
|
35
|
+
* Interaction motion applied on press.
|
|
36
|
+
* @default 'press'
|
|
37
|
+
*/
|
|
38
|
+
animation?: ButtonAnimation;
|
|
39
|
+
/**
|
|
40
|
+
* Custom className appended after the built-in runtime classes.
|
|
22
41
|
*/
|
|
23
42
|
className?: string;
|
|
24
43
|
/**
|
|
25
|
-
* Button children - defaults to provider name
|
|
26
|
-
* Pass `null` for icon-only mode
|
|
44
|
+
* Button children - defaults to provider name in Spanish.
|
|
45
|
+
* Pass `null` for icon-only mode.
|
|
27
46
|
*/
|
|
28
47
|
children?: ReactNode;
|
|
29
48
|
}
|
|
30
49
|
interface OAuthIconsProps {
|
|
31
50
|
/**
|
|
32
|
-
* Icon size in pixels (min: 1)
|
|
51
|
+
* Icon size in pixels (min: 1).
|
|
33
52
|
* @default 24
|
|
34
53
|
*/
|
|
35
54
|
size?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Optional className for icon-specific styling.
|
|
57
|
+
*/
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
interface UseButtonAnimationResult {
|
|
61
|
+
/**
|
|
62
|
+
* CSS classes to apply for the current animation state.
|
|
63
|
+
*/
|
|
64
|
+
animationClassName: string;
|
|
65
|
+
/**
|
|
66
|
+
* Event handlers to attach to the button.
|
|
67
|
+
*/
|
|
68
|
+
eventHandlers: Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'onBlur' | 'onKeyDown' | 'onKeyUp' | 'onMouseDown' | 'onMouseLeave' | 'onMouseUp' | 'onTouchEnd' | 'onTouchStart'>;
|
|
36
69
|
}
|
|
37
70
|
|
|
38
71
|
/**
|
|
39
72
|
* OAuthButton component
|
|
40
73
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* Design Philosophy:
|
|
46
|
-
* - We add sensible UX defaults (cursor-pointer, proper disabled states)
|
|
47
|
-
* - We don't impose visual opinions - you control all styling via className
|
|
48
|
-
* - The result is a solid, accessible foundation that looks exactly how you want
|
|
74
|
+
* Built on top of the shared Sublime button foundation so it inherits
|
|
75
|
+
* runtime styling, semantic variants, curated press motion, and loading
|
|
76
|
+
* behavior by default.
|
|
49
77
|
*
|
|
50
78
|
* @example
|
|
51
79
|
* ```tsx
|
|
52
|
-
*
|
|
53
|
-
* <OAuthButton
|
|
54
|
-
* provider="google"
|
|
55
|
-
* onClick={signInWithGoogle}
|
|
56
|
-
* className="flex items-center gap-3 px-6 py-3 bg-white text-gray-900 rounded-lg font-medium"
|
|
57
|
-
* />
|
|
58
|
-
*
|
|
59
|
-
* // Icon only - pass {null} as children
|
|
60
|
-
* <OAuthButton
|
|
61
|
-
* provider="google"
|
|
62
|
-
* className="p-3 rounded-full hover:bg-white/10"
|
|
63
|
-
* >
|
|
64
|
-
* {null}
|
|
65
|
-
* </OAuthButton>
|
|
66
|
-
*
|
|
67
|
-
* // Loading state - cursor-not-allowed is automatic
|
|
68
|
-
* <OAuthButton provider="google" loading className="opacity-50" />
|
|
80
|
+
* <OAuthButton provider="google" />
|
|
81
|
+
* <OAuthButton provider="discord" variant="primary" loading />
|
|
69
82
|
* ```
|
|
70
83
|
*/
|
|
71
84
|
declare const OAuthButton: react.ForwardRefExoticComponent<OAuthButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
72
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Hook to provide the curated button press animation.
|
|
88
|
+
*
|
|
89
|
+
* Handles mouse, touch, and keyboard interaction so motion feedback stays
|
|
90
|
+
* consistent across the different ways users can activate a button.
|
|
91
|
+
*/
|
|
92
|
+
declare function useButtonAnimation(animation?: ButtonAnimation | null): UseButtonAnimationResult;
|
|
93
|
+
|
|
73
94
|
/**
|
|
74
95
|
* Google Logo Icon
|
|
75
96
|
* Official Google "G" logo for OAuth authentication
|
|
76
97
|
*/
|
|
77
|
-
declare function GoogleIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare function GoogleIcon({ size, className }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
78
99
|
/**
|
|
79
100
|
* Discord Logo Icon
|
|
80
101
|
* Official Discord logo for OAuth authentication
|
|
81
102
|
*/
|
|
82
|
-
declare function DiscordIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
83
|
-
/**
|
|
84
|
-
* Spinner Icon for loading state
|
|
85
|
-
*/
|
|
86
|
-
declare function SpinnerIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
103
|
+
declare function DiscordIcon({ size, className }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
87
104
|
|
|
88
|
-
export { DiscordIcon, GoogleIcon, OAuthButton, type OAuthButtonProps, type OAuthIconsProps, type OAuthProvider,
|
|
105
|
+
export { type ButtonAnimation, type ButtonLoadingAnimation, type ButtonVariant, DiscordIcon, GoogleIcon, OAuthButton, type OAuthButtonProps, type OAuthIconsProps, type OAuthProvider, type UseButtonAnimationResult, useButtonAnimation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,88 +1,105 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, MouseEventHandler, ReactNode } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
type OAuthProvider = 'google' | 'discord';
|
|
6
|
+
type ButtonVariant = 'primary' | 'secondary';
|
|
7
|
+
type ButtonAnimation = 'press';
|
|
8
|
+
type ButtonLoadingAnimation = 'spinner';
|
|
6
9
|
interface OAuthButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
7
10
|
/**
|
|
8
|
-
* The OAuth provider to authenticate with
|
|
11
|
+
* The OAuth provider to authenticate with.
|
|
9
12
|
*/
|
|
10
13
|
provider: OAuthProvider;
|
|
11
14
|
/**
|
|
12
|
-
* Click handler - typically calls supabase.auth.signInWithOAuth
|
|
15
|
+
* Click handler - typically calls supabase.auth.signInWithOAuth.
|
|
13
16
|
*/
|
|
14
|
-
onClick?:
|
|
17
|
+
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
15
18
|
/**
|
|
16
|
-
* Loading state - shows
|
|
19
|
+
* Loading state - shows the configured loading animation and disables interaction.
|
|
17
20
|
*/
|
|
18
21
|
loading?: boolean;
|
|
19
22
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
23
|
+
* Loading animation shown while `loading` is true.
|
|
24
|
+
* @default 'spinner'
|
|
25
|
+
*/
|
|
26
|
+
loadingAnimation?: ButtonLoadingAnimation;
|
|
27
|
+
/**
|
|
28
|
+
* Visual variant of the button.
|
|
29
|
+
* - primary: High emphasis, filled background
|
|
30
|
+
* - secondary: Medium emphasis, bordered (default)
|
|
31
|
+
* @default 'secondary'
|
|
32
|
+
*/
|
|
33
|
+
variant?: ButtonVariant;
|
|
34
|
+
/**
|
|
35
|
+
* Interaction motion applied on press.
|
|
36
|
+
* @default 'press'
|
|
37
|
+
*/
|
|
38
|
+
animation?: ButtonAnimation;
|
|
39
|
+
/**
|
|
40
|
+
* Custom className appended after the built-in runtime classes.
|
|
22
41
|
*/
|
|
23
42
|
className?: string;
|
|
24
43
|
/**
|
|
25
|
-
* Button children - defaults to provider name
|
|
26
|
-
* Pass `null` for icon-only mode
|
|
44
|
+
* Button children - defaults to provider name in Spanish.
|
|
45
|
+
* Pass `null` for icon-only mode.
|
|
27
46
|
*/
|
|
28
47
|
children?: ReactNode;
|
|
29
48
|
}
|
|
30
49
|
interface OAuthIconsProps {
|
|
31
50
|
/**
|
|
32
|
-
* Icon size in pixels (min: 1)
|
|
51
|
+
* Icon size in pixels (min: 1).
|
|
33
52
|
* @default 24
|
|
34
53
|
*/
|
|
35
54
|
size?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Optional className for icon-specific styling.
|
|
57
|
+
*/
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
interface UseButtonAnimationResult {
|
|
61
|
+
/**
|
|
62
|
+
* CSS classes to apply for the current animation state.
|
|
63
|
+
*/
|
|
64
|
+
animationClassName: string;
|
|
65
|
+
/**
|
|
66
|
+
* Event handlers to attach to the button.
|
|
67
|
+
*/
|
|
68
|
+
eventHandlers: Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'onBlur' | 'onKeyDown' | 'onKeyUp' | 'onMouseDown' | 'onMouseLeave' | 'onMouseUp' | 'onTouchEnd' | 'onTouchStart'>;
|
|
36
69
|
}
|
|
37
70
|
|
|
38
71
|
/**
|
|
39
72
|
* OAuthButton component
|
|
40
73
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* Design Philosophy:
|
|
46
|
-
* - We add sensible UX defaults (cursor-pointer, proper disabled states)
|
|
47
|
-
* - We don't impose visual opinions - you control all styling via className
|
|
48
|
-
* - The result is a solid, accessible foundation that looks exactly how you want
|
|
74
|
+
* Built on top of the shared Sublime button foundation so it inherits
|
|
75
|
+
* runtime styling, semantic variants, curated press motion, and loading
|
|
76
|
+
* behavior by default.
|
|
49
77
|
*
|
|
50
78
|
* @example
|
|
51
79
|
* ```tsx
|
|
52
|
-
*
|
|
53
|
-
* <OAuthButton
|
|
54
|
-
* provider="google"
|
|
55
|
-
* onClick={signInWithGoogle}
|
|
56
|
-
* className="flex items-center gap-3 px-6 py-3 bg-white text-gray-900 rounded-lg font-medium"
|
|
57
|
-
* />
|
|
58
|
-
*
|
|
59
|
-
* // Icon only - pass {null} as children
|
|
60
|
-
* <OAuthButton
|
|
61
|
-
* provider="google"
|
|
62
|
-
* className="p-3 rounded-full hover:bg-white/10"
|
|
63
|
-
* >
|
|
64
|
-
* {null}
|
|
65
|
-
* </OAuthButton>
|
|
66
|
-
*
|
|
67
|
-
* // Loading state - cursor-not-allowed is automatic
|
|
68
|
-
* <OAuthButton provider="google" loading className="opacity-50" />
|
|
80
|
+
* <OAuthButton provider="google" />
|
|
81
|
+
* <OAuthButton provider="discord" variant="primary" loading />
|
|
69
82
|
* ```
|
|
70
83
|
*/
|
|
71
84
|
declare const OAuthButton: react.ForwardRefExoticComponent<OAuthButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
72
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Hook to provide the curated button press animation.
|
|
88
|
+
*
|
|
89
|
+
* Handles mouse, touch, and keyboard interaction so motion feedback stays
|
|
90
|
+
* consistent across the different ways users can activate a button.
|
|
91
|
+
*/
|
|
92
|
+
declare function useButtonAnimation(animation?: ButtonAnimation | null): UseButtonAnimationResult;
|
|
93
|
+
|
|
73
94
|
/**
|
|
74
95
|
* Google Logo Icon
|
|
75
96
|
* Official Google "G" logo for OAuth authentication
|
|
76
97
|
*/
|
|
77
|
-
declare function GoogleIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare function GoogleIcon({ size, className }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
78
99
|
/**
|
|
79
100
|
* Discord Logo Icon
|
|
80
101
|
* Official Discord logo for OAuth authentication
|
|
81
102
|
*/
|
|
82
|
-
declare function DiscordIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
83
|
-
/**
|
|
84
|
-
* Spinner Icon for loading state
|
|
85
|
-
*/
|
|
86
|
-
declare function SpinnerIcon({ size }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
103
|
+
declare function DiscordIcon({ size, className }: OAuthIconsProps): react_jsx_runtime.JSX.Element;
|
|
87
104
|
|
|
88
|
-
export { DiscordIcon, GoogleIcon, OAuthButton, type OAuthButtonProps, type OAuthIconsProps, type OAuthProvider,
|
|
105
|
+
export { type ButtonAnimation, type ButtonLoadingAnimation, type ButtonVariant, DiscordIcon, GoogleIcon, OAuthButton, type OAuthButtonProps, type OAuthIconsProps, type OAuthProvider, type UseButtonAnimationResult, useButtonAnimation };
|