@xylabs/react-button 7.1.17 → 7.1.20
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 +6 -46
- package/package.json +30 -23
- package/src/components/ButtonEx.stories.tsx +0 -86
- package/src/components/ButtonEx.tsx +0 -18
- package/src/components/ButtonExBase.tsx +0 -70
- package/src/components/ButtonExProps.tsx +0 -49
- package/src/components/ButtonExTo.tsx +0 -25
- package/src/components/index.ts +0 -2
- package/src/index.ts +0 -1
package/README.md
CHANGED
|
@@ -1,67 +1,27 @@
|
|
|
1
|
-
[![logo][]](https://xylabs.com)
|
|
2
|
-
|
|
3
1
|
# @xylabs/react-button
|
|
4
2
|
|
|
5
|
-
[![npm-badge]
|
|
6
|
-
[![npm-downloads-badge][]][npm-link]
|
|
7
|
-
[![jsdelivr-badge][]][jsdelivr-link]
|
|
8
|
-
[![npm-license-badge][]](LICENSE)
|
|
9
|
-
|
|
10
|
-
> XY Labs generalized React library
|
|
11
|
-
|
|
12
|
-
## Table of Contents
|
|
3
|
+
[![npm][npm-badge]][npm-link]
|
|
13
4
|
|
|
14
|
-
|
|
15
|
-
- [Install](#install)
|
|
16
|
-
- [Maintainers](#maintainers)
|
|
17
|
-
- [License](#license)
|
|
18
|
-
- [Credits](#credits)
|
|
19
|
-
|
|
20
|
-
## Description
|
|
21
|
-
|
|
22
|
-
Common React code that is used throughout XYO projects that use React.
|
|
5
|
+
> Common React library for all XY Labs projects that use React
|
|
23
6
|
|
|
24
7
|
## Install
|
|
25
8
|
|
|
26
|
-
Using npm:
|
|
27
|
-
|
|
28
9
|
```sh
|
|
29
|
-
npm
|
|
10
|
+
npm install {{name}}
|
|
30
11
|
```
|
|
31
12
|
|
|
32
|
-
|
|
13
|
+
or
|
|
33
14
|
|
|
34
15
|
```sh
|
|
35
|
-
yarn add
|
|
16
|
+
yarn add {{name}}
|
|
36
17
|
```
|
|
37
18
|
|
|
38
|
-
## Documentation
|
|
39
|
-
[Developer Reference](https://xylabs.github.io/sdk-react)
|
|
40
|
-
|
|
41
|
-
[Storybook](https://xylabs.github.io/sdk-react/storybook)
|
|
42
|
-
|
|
43
|
-
## Maintainers
|
|
44
|
-
|
|
45
|
-
- [Arie Trouw](https://github.com/arietrouw) ([arietrouw.com](https://arietrouw.com))
|
|
46
|
-
- [Matt Jones](https://github.com/jonesmac)
|
|
47
|
-
- [Joel Carter](https://github.com/JoelBCarter)
|
|
48
|
-
- [Jordan Trouw](https://github.com/jordantrouw)
|
|
49
19
|
|
|
50
20
|
## License
|
|
51
21
|
|
|
52
|
-
See the [LICENSE](LICENSE) file for license
|
|
22
|
+
See the [LICENSE](LICENSE) file for license rights and limitations (LGPL-3.0-only).
|
|
53
23
|
|
|
54
|
-
## Credits
|
|
55
24
|
|
|
56
|
-
[Made with 🔥and ❄️ by XY Labs](https://xylabs.com)
|
|
57
|
-
|
|
58
|
-
[logo]: https://cdn.xy.company/img/brand/XYPersistentCompany_Logo_Icon_Colored.svg
|
|
59
25
|
|
|
60
26
|
[npm-badge]: https://img.shields.io/npm/v/@xylabs/react-button.svg
|
|
61
27
|
[npm-link]: https://www.npmjs.com/package/@xylabs/react-button
|
|
62
|
-
|
|
63
|
-
[npm-downloads-badge]: https://img.shields.io/npm/dw/@xylabs/react-button
|
|
64
|
-
[npm-license-badge]: https://img.shields.io/npm/l/@xylabs/react-button
|
|
65
|
-
|
|
66
|
-
[jsdelivr-badge]: https://data.jsdelivr.com/v1/package/npm/@xylabs/react-button/badge
|
|
67
|
-
[jsdelivr-link]: https://www.jsdelivr.com/package/npm/@xylabs/react-button
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xylabs/react-button",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.20",
|
|
4
4
|
"description": "Common React library for all XY Labs projects that use React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"utility",
|
|
@@ -27,50 +27,57 @@
|
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
29
|
"types": "./dist/browser/index.d.ts",
|
|
30
|
+
"import": "./dist/browser/index.mjs",
|
|
30
31
|
"default": "./dist/browser/index.mjs"
|
|
31
32
|
},
|
|
32
33
|
"./package.json": "./package.json"
|
|
33
34
|
},
|
|
34
|
-
"module": "./dist/browser/index.mjs",
|
|
35
35
|
"types": "dist/browser/index.d.ts",
|
|
36
36
|
"files": [
|
|
37
37
|
"dist",
|
|
38
|
-
"
|
|
38
|
+
"README.md"
|
|
39
39
|
],
|
|
40
40
|
"workspaces": [
|
|
41
41
|
"packages/*"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@
|
|
45
|
-
"@xylabs/
|
|
46
|
-
"
|
|
44
|
+
"@mui/material": "~7.3.9",
|
|
45
|
+
"@xylabs/sdk-js": "~5.0.95",
|
|
46
|
+
"react-router-dom": "~7.14.0",
|
|
47
|
+
"@xylabs/react-pixel": "~7.1.20",
|
|
48
|
+
"@xylabs/react-shared": "~7.1.20"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"@storybook/react-vite": "~10.
|
|
51
|
+
"@opentelemetry/api": "^1.9.1",
|
|
52
|
+
"@storybook/react-vite": "~10.3.4",
|
|
53
|
+
"@types/node": "~25.5.2",
|
|
51
54
|
"@types/react": "^19.2.14",
|
|
52
|
-
"@xylabs/
|
|
53
|
-
"@xylabs/
|
|
54
|
-
"@xylabs/
|
|
55
|
-
"@xylabs/tsconfig": "~7.
|
|
56
|
-
"@xylabs/tsconfig-
|
|
57
|
-
"@xylabs/
|
|
55
|
+
"@xylabs/ts-scripts-common": "~7.8.5",
|
|
56
|
+
"@xylabs/ts-scripts-pnpm": "~7.8.5",
|
|
57
|
+
"@xylabs/tsconfig": "~7.8",
|
|
58
|
+
"@xylabs/tsconfig-dom": "~7.8.5",
|
|
59
|
+
"@xylabs/tsconfig-react": "~7.8.5",
|
|
60
|
+
"@xylabs/zod": "~5.0.95",
|
|
61
|
+
"axios": "^1.14.0",
|
|
62
|
+
"esbuild": "^0.28.0",
|
|
63
|
+
"pako": "~2.1.0",
|
|
58
64
|
"react": "^19.2.4",
|
|
59
65
|
"react-dom": "^19.2.4",
|
|
60
|
-
"
|
|
61
|
-
"storybook": "~10.2.16",
|
|
66
|
+
"storybook": "~10.3.4",
|
|
62
67
|
"typescript": "^5.9.3",
|
|
63
|
-
"vite": "~
|
|
64
|
-
"zod": "^4.3.6"
|
|
68
|
+
"vite": "~8.0.5",
|
|
69
|
+
"zod": "^4.3.6",
|
|
70
|
+
"@xylabs/react-flexbox": "~7.1.20",
|
|
71
|
+
"@xylabs/react-promise": "~7.1.20",
|
|
72
|
+
"@xylabs/react-async-effect": "~7.1.20"
|
|
65
73
|
},
|
|
66
74
|
"peerDependencies": {
|
|
67
|
-
"@
|
|
75
|
+
"@xylabs/zod": "~5.0.95",
|
|
76
|
+
"pako": "~2.1.0",
|
|
68
77
|
"react": "^19",
|
|
69
|
-
"react-
|
|
70
|
-
"react-router-dom": "^7",
|
|
71
|
-
"zod": "^4"
|
|
78
|
+
"@xylabs/react-async-effect": "~7.1.20"
|
|
72
79
|
},
|
|
73
80
|
"publishConfig": {
|
|
74
81
|
"access": "public"
|
|
75
82
|
}
|
|
76
|
-
}
|
|
83
|
+
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryFn } from '@storybook/react-vite'
|
|
2
|
-
import { FlexCol, FlexRow } from '@xylabs/react-flexbox'
|
|
3
|
-
import { UserEventsProvider, XyoUserEventHandler } from '@xylabs/react-pixel'
|
|
4
|
-
import React from 'react'
|
|
5
|
-
|
|
6
|
-
import { ButtonEx } from './ButtonEx.tsx'
|
|
7
|
-
|
|
8
|
-
const StorybookEntry = {
|
|
9
|
-
argTypes: {},
|
|
10
|
-
component: ButtonEx,
|
|
11
|
-
parameters: { docs: { page: null } },
|
|
12
|
-
title: 'button/ButtonEx',
|
|
13
|
-
} as Meta<typeof ButtonEx>
|
|
14
|
-
|
|
15
|
-
const DefaultTemplate: StoryFn<typeof ButtonEx> = args => (
|
|
16
|
-
<FlexRow justifyContent="flex-start">
|
|
17
|
-
<FlexCol marginX={1}>
|
|
18
|
-
<ButtonEx {...args}>Default</ButtonEx>
|
|
19
|
-
</FlexCol>
|
|
20
|
-
<FlexCol marginX={1}>
|
|
21
|
-
<ButtonEx variant="outlined" {...args}>
|
|
22
|
-
Outlined
|
|
23
|
-
</ButtonEx>
|
|
24
|
-
</FlexCol>
|
|
25
|
-
<FlexCol marginX={1}>
|
|
26
|
-
<ButtonEx variant="contained" {...args}>
|
|
27
|
-
Contained
|
|
28
|
-
</ButtonEx>
|
|
29
|
-
</FlexCol>
|
|
30
|
-
</FlexRow>
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
const UserEventTemplate: StoryFn<typeof ButtonEx> = args => (
|
|
34
|
-
<UserEventsProvider userEvents={XyoUserEventHandler.get()}>
|
|
35
|
-
<FlexRow justifyContent="flex-start">
|
|
36
|
-
<FlexCol marginX={1}>
|
|
37
|
-
<ButtonEx {...args}>Default</ButtonEx>
|
|
38
|
-
</FlexCol>
|
|
39
|
-
<FlexCol marginX={1}>
|
|
40
|
-
<ButtonEx variant="outlined" {...args}>
|
|
41
|
-
Outlined
|
|
42
|
-
</ButtonEx>
|
|
43
|
-
</FlexCol>
|
|
44
|
-
<FlexCol marginX={1}>
|
|
45
|
-
<ButtonEx variant="contained" {...args}>
|
|
46
|
-
Contained
|
|
47
|
-
</ButtonEx>
|
|
48
|
-
</FlexCol>
|
|
49
|
-
</FlexRow>
|
|
50
|
-
</UserEventsProvider>
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const Default = DefaultTemplate.bind({})
|
|
54
|
-
Default.args = {}
|
|
55
|
-
|
|
56
|
-
const BusyCircular = DefaultTemplate.bind({})
|
|
57
|
-
BusyCircular.args = { busy: true, busyVariant: 'circular' }
|
|
58
|
-
|
|
59
|
-
const BusyLinear = DefaultTemplate.bind({})
|
|
60
|
-
BusyLinear.args = { busy: true, busyVariant: 'linear' }
|
|
61
|
-
|
|
62
|
-
const Href = DefaultTemplate.bind({})
|
|
63
|
-
Href.args = { href: 'https://xylabs.com' }
|
|
64
|
-
|
|
65
|
-
const HrefTarget = DefaultTemplate.bind({})
|
|
66
|
-
HrefTarget.args = { href: 'https://xylabs.com', target: '_blank' }
|
|
67
|
-
|
|
68
|
-
const HrefTargetOnClick = DefaultTemplate.bind({})
|
|
69
|
-
HrefTargetOnClick.args = {
|
|
70
|
-
href: 'https://xylabs.com', target: '_blank', onClick: () => console.log('Clicked'),
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const HrefTargetWithEvents = UserEventTemplate.bind({})
|
|
74
|
-
HrefTargetWithEvents.args = { href: 'https://xylabs.com', target: '_blank' }
|
|
75
|
-
|
|
76
|
-
const HrefTargetOnClickWithEvents = UserEventTemplate.bind({})
|
|
77
|
-
HrefTargetOnClickWithEvents.args = {
|
|
78
|
-
href: 'https://xylabs.com', target: '_blank', onClick: () => console.log('Clicked'),
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export {
|
|
82
|
-
BusyCircular, BusyLinear, Default, Href, HrefTarget, HrefTargetOnClick, HrefTargetOnClickWithEvents,
|
|
83
|
-
HrefTargetWithEvents,
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export default StorybookEntry
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
import { ButtonExBase } from './ButtonExBase.tsx'
|
|
4
|
-
import type { ButtonExProps } from './ButtonExProps.tsx'
|
|
5
|
-
import { ButtonToEx } from './ButtonExTo.tsx'
|
|
6
|
-
|
|
7
|
-
const ButtonEx = ({ ref, ...props }: ButtonExProps) => {
|
|
8
|
-
if (props.to === undefined) {
|
|
9
|
-
return <ButtonExBase {...props} />
|
|
10
|
-
} else {
|
|
11
|
-
const { to, ...additionalProps } = props
|
|
12
|
-
return <ButtonToEx to={to} ref={ref} {...additionalProps} />
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
ButtonEx.displayName = 'ButtonExXYLabs'
|
|
17
|
-
|
|
18
|
-
export { ButtonEx }
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Button, useTheme } from '@mui/material'
|
|
2
|
-
import { useUserEvents } from '@xylabs/react-pixel'
|
|
3
|
-
import {
|
|
4
|
-
BusyCircularProgress, BusyLinearProgress, mergeBoxlikeStyles,
|
|
5
|
-
} from '@xylabs/react-shared'
|
|
6
|
-
import { isString, toPromise } from '@xylabs/sdk-js'
|
|
7
|
-
import type { MouseEvent } from 'react'
|
|
8
|
-
import React from 'react'
|
|
9
|
-
|
|
10
|
-
import type { ButtonExProps } from './ButtonExProps.tsx'
|
|
11
|
-
|
|
12
|
-
const ButtonExBase = ({
|
|
13
|
-
ref, funnel, intent, target, placement, disableUserEvents, href, ...props
|
|
14
|
-
}: ButtonExProps) => {
|
|
15
|
-
const theme = useTheme()
|
|
16
|
-
const userEvents = useUserEvents()
|
|
17
|
-
const {
|
|
18
|
-
busy, busyVariant = 'linear', busyOpacity, onClick, children, ...rootProps
|
|
19
|
-
} = mergeBoxlikeStyles<ButtonExProps>(theme, props)
|
|
20
|
-
|
|
21
|
-
const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {
|
|
22
|
-
if (busy) {
|
|
23
|
-
// If it is busy, do not allow href clicks
|
|
24
|
-
event.preventDefault()
|
|
25
|
-
} else {
|
|
26
|
-
const elementName = props['aria-label'] ?? event.currentTarget.textContent
|
|
27
|
-
// we do this crazy navigate thing so that we can set it up outside the promise so that safari does not block it
|
|
28
|
-
const windowToNavigate = () => (isString(target) && isString(href)) ? window.open('', target) ?? globalThis : globalThis
|
|
29
|
-
const callOnClickAndFollowHref = (windowToNav = windowToNavigate()) => {
|
|
30
|
-
onClick?.(event)
|
|
31
|
-
if (isString(href)) {
|
|
32
|
-
windowToNav.location.href = href
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (!disableUserEvents && userEvents) {
|
|
36
|
-
event.preventDefault()
|
|
37
|
-
const windowToNav = windowToNavigate()
|
|
38
|
-
if (isString(href)) {
|
|
39
|
-
toPromise(userEvents.userClick({
|
|
40
|
-
elementName, intent, funnel, placement,
|
|
41
|
-
})).then(() => {
|
|
42
|
-
callOnClickAndFollowHref(windowToNav)
|
|
43
|
-
}).catch((ex) => {
|
|
44
|
-
console.error('User event failed', elementName, funnel, placement, ex)
|
|
45
|
-
callOnClickAndFollowHref(windowToNav)
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
onClick?.(event)
|
|
49
|
-
} else {
|
|
50
|
-
callOnClickAndFollowHref()
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<Button ref={ref} href={href} onClick={localOnClick} target={target} {...rootProps}>
|
|
57
|
-
{busy && busyVariant === 'linear'
|
|
58
|
-
? <BusyLinearProgress rounded opacity={busyOpacity ?? 0} />
|
|
59
|
-
: null}
|
|
60
|
-
{busy && busyVariant === 'circular'
|
|
61
|
-
? <BusyCircularProgress rounded size={24} opacity={busyOpacity ?? 0.5} />
|
|
62
|
-
: null}
|
|
63
|
-
{children}
|
|
64
|
-
</Button>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
ButtonExBase.displayName = 'ButtonExBaseXYLabs'
|
|
69
|
-
|
|
70
|
-
export { ButtonExBase }
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { ButtonProps } from '@mui/material'
|
|
2
|
-
import type { BoxlikeComponentProps, BusyProps } from '@xylabs/react-shared'
|
|
3
|
-
import { isDefined, isString } from '@xylabs/sdk-js'
|
|
4
|
-
import type { NavigateOptions, To } from 'react-router-dom'
|
|
5
|
-
|
|
6
|
-
export interface ButtonOnlyHrefProps {
|
|
7
|
-
href?: string
|
|
8
|
-
to?: never
|
|
9
|
-
toOptions?: never
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ButtonOnlyToProps {
|
|
13
|
-
href?: never
|
|
14
|
-
to?: To
|
|
15
|
-
toOptions?: NavigateOptions
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ButtonNoToOrHrefProps {
|
|
19
|
-
href?: never
|
|
20
|
-
to?: never
|
|
21
|
-
toOptions?: never
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type ButtonHrefOrToOrNoProps = ButtonOnlyHrefProps | ButtonOnlyToProps | ButtonNoToOrHrefProps
|
|
25
|
-
|
|
26
|
-
export interface ButtonHrefAndToProps {
|
|
27
|
-
href?: string
|
|
28
|
-
to?: To
|
|
29
|
-
toOptions?: NavigateOptions
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const asButtonHrefOrToProps = ({
|
|
33
|
-
href, to, toOptions,
|
|
34
|
-
}: ButtonHrefAndToProps): ButtonHrefOrToOrNoProps => {
|
|
35
|
-
if (isString(href) && (isDefined(to) || isDefined(toOptions))) {
|
|
36
|
-
throw new Error('ButtonExProps: cannot have both href and to')
|
|
37
|
-
}
|
|
38
|
-
return isString(href) ? { href } : isDefined(to) ? { to, toOptions } : {}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface ButtonBaseExProps extends Omit<ButtonProps, 'href'>, BoxlikeComponentProps, BusyProps {
|
|
42
|
-
disableUserEvents?: boolean
|
|
43
|
-
funnel?: string
|
|
44
|
-
intent?: string
|
|
45
|
-
placement?: string
|
|
46
|
-
target?: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type ButtonExProps = ButtonBaseExProps & ButtonHrefOrToOrNoProps
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { isDefined } from '@xylabs/sdk-js'
|
|
2
|
-
import type { MouseEvent } from 'react'
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { useNavigate } from 'react-router-dom'
|
|
5
|
-
|
|
6
|
-
import { ButtonExBase } from './ButtonExBase.tsx'
|
|
7
|
-
import type { ButtonExProps } from './ButtonExProps.tsx'
|
|
8
|
-
|
|
9
|
-
const ButtonToEx = ({
|
|
10
|
-
ref, to, toOptions, onClick, ...props
|
|
11
|
-
}: ButtonExProps) => {
|
|
12
|
-
const navigate = useNavigate()
|
|
13
|
-
const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {
|
|
14
|
-
onClick?.(event)
|
|
15
|
-
if (isDefined(to)) {
|
|
16
|
-
void navigate(to, toOptions)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return <ButtonExBase ref={ref} onClick={localOnClick} {...props} />
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
ButtonToEx.displayName = 'ButtonToExXYLabs'
|
|
24
|
-
|
|
25
|
-
export { ButtonToEx }
|
package/src/components/index.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './components/index.ts'
|