@xylabs/react-button 7.0.0 → 7.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.
@@ -1,14 +1,14 @@
1
1
  import type { Meta } from '@storybook/react-vite';
2
2
  import { ButtonEx } from './ButtonEx.tsx';
3
3
  declare const StorybookEntry: Meta<typeof ButtonEx>;
4
- declare const Default: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
5
- declare const BusyCircular: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
6
- declare const BusyLinear: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
7
- declare const Href: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
8
- declare const HrefTarget: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
9
- declare const HrefTargetOnClick: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
10
- declare const HrefTargetWithEvents: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
11
- declare const HrefTargetOnClickWithEvents: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
4
+ declare const Default: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
5
+ declare const BusyCircular: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
6
+ declare const BusyLinear: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
7
+ declare const Href: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
8
+ declare const HrefTarget: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
9
+ declare const HrefTargetOnClick: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
10
+ declare const HrefTargetWithEvents: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
11
+ declare const HrefTargetOnClickWithEvents: import(".store/storybook-virtual-ae2e92fa55/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, import("./ButtonExProps.tsx").ButtonExProps>;
12
12
  export { BusyCircular, BusyLinear, Default, Href, HrefTarget, HrefTargetOnClick, HrefTargetOnClickWithEvents, HrefTargetWithEvents, };
13
13
  export default StorybookEntry;
14
14
  //# sourceMappingURL=ButtonEx.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonEx.stories.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonEx.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,uBAAuB,CAAA;AAK1D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,QAAA,MAAM,cAAc,EAKf,IAAI,CAAC,OAAO,QAAQ,CAAC,CAAA;AAwC1B,QAAA,MAAM,OAAO,+IAA2B,CAAA;AAGxC,QAAA,MAAM,YAAY,+IAA2B,CAAA;AAG7C,QAAA,MAAM,UAAU,+IAA2B,CAAA;AAG3C,QAAA,MAAM,IAAI,+IAA2B,CAAA;AAGrC,QAAA,MAAM,UAAU,+IAA2B,CAAA;AAG3C,QAAA,MAAM,iBAAiB,+IAA2B,CAAA;AAKlD,QAAA,MAAM,oBAAoB,+IAA6B,CAAA;AAGvD,QAAA,MAAM,2BAA2B,+IAA6B,CAAA;AAK9D,OAAO,EACL,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,2BAA2B,EACnG,oBAAoB,GACrB,CAAA;AAED,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"ButtonEx.stories.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonEx.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,uBAAuB,CAAA;AAK1D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,QAAA,MAAM,cAAc,EAKf,IAAI,CAAC,OAAO,QAAQ,CAAC,CAAA;AAwC1B,QAAA,MAAM,OAAO,iLAA2B,CAAA;AAGxC,QAAA,MAAM,YAAY,iLAA2B,CAAA;AAG7C,QAAA,MAAM,UAAU,iLAA2B,CAAA;AAG3C,QAAA,MAAM,IAAI,iLAA2B,CAAA;AAGrC,QAAA,MAAM,UAAU,iLAA2B,CAAA;AAG3C,QAAA,MAAM,iBAAiB,iLAA2B,CAAA;AAKlD,QAAA,MAAM,oBAAoB,iLAA6B,CAAA;AAGvD,QAAA,MAAM,2BAA2B,iLAA6B,CAAA;AAK9D,OAAO,EACL,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,2BAA2B,EACnG,oBAAoB,GACrB,CAAA;AAED,eAAe,cAAc,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonExBase.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExBase.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,QAAA,MAAM,YAAY;oFAEf,aAAa;;CAoDf,CAAA;AAID,OAAO,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"ButtonExBase.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExBase.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,QAAA,MAAM,YAAY;oFAEf,aAAa;;CAoDf,CAAA;AAID,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -22,7 +22,7 @@ export interface ButtonHrefAndToProps {
22
22
  to?: To;
23
23
  toOptions?: NavigateOptions;
24
24
  }
25
- export declare const asButtonHrefOrToProps: (props: ButtonHrefAndToProps) => ButtonHrefOrToOrNoProps;
25
+ export declare const asButtonHrefOrToProps: ({ href, to, toOptions, }: ButtonHrefAndToProps) => ButtonHrefOrToOrNoProps;
26
26
  export interface ButtonBaseExProps extends Omit<ButtonProps, 'href'>, BoxlikeComponentProps, BusyProps {
27
27
  disableUserEvents?: boolean;
28
28
  funnel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonExProps.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAE3D,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,SAAS,CAAC,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,EAAE,CAAC,EAAE,EAAE,CAAA;IACP,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,SAAS,CAAC,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,MAAM,uBAAuB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,qBAAqB,CAAA;AAErG,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,EAAE,CAAA;IACP,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED,eAAO,MAAM,qBAAqB,GAAI,OAAO,oBAAoB,KAAG,uBAKnE,CAAA;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,qBAAqB,EAAE,SAAS;IACpG,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,uBAAuB,CAAA"}
1
+ {"version":3,"file":"ButtonExProps.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAE3D,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,SAAS,CAAC,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,EAAE,CAAC,EAAE,EAAE,CAAA;IACP,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,SAAS,CAAC,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,MAAM,uBAAuB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,qBAAqB,CAAA;AAErG,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,EAAE,CAAA;IACP,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED,eAAO,MAAM,qBAAqB,GAAI,0BAEnC,oBAAoB,KAAG,uBAKzB,CAAA;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,qBAAqB,EAAE,SAAS;IACpG,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,uBAAuB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonExTo.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExTo.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,QAAA,MAAM,UAAU;gDAEb,aAAa;;CAUf,CAAA;AAID,OAAO,EAAE,UAAU,EAAE,CAAA"}
1
+ {"version":3,"file":"ButtonExTo.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonExTo.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,QAAA,MAAM,UAAU;gDAEb,aAAa;;CAUf,CAAA;AAID,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -1,35 +1,50 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/components/ButtonEx.tsx
5
- import React3 from "react";
6
-
7
1
  // src/components/ButtonExBase.tsx
8
2
  import { Button, useTheme } from "@mui/material";
9
3
  import { toPromise } from "@xylabs/promise";
10
4
  import { useUserEvents } from "@xylabs/react-pixel";
11
- import { BusyCircularProgress, BusyLinearProgress, mergeBoxlikeStyles } from "@xylabs/react-shared";
12
- import React from "react";
13
- var ButtonExBase = /* @__PURE__ */ __name(({ ref, funnel, intent, target, placement, disableUserEvents, href, ...props }) => {
5
+ import {
6
+ BusyCircularProgress,
7
+ BusyLinearProgress,
8
+ mergeBoxlikeStyles
9
+ } from "@xylabs/react-shared";
10
+ import { isString } from "@xylabs/typeof";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ var ButtonExBase = ({
13
+ ref,
14
+ funnel,
15
+ intent,
16
+ target,
17
+ placement,
18
+ disableUserEvents,
19
+ href,
20
+ ...props
21
+ }) => {
14
22
  const theme = useTheme();
15
23
  const userEvents = useUserEvents();
16
- const { busy, busyVariant = "linear", busyOpacity, onClick, children, ...rootProps } = mergeBoxlikeStyles(theme, props);
17
- const localOnClick = /* @__PURE__ */ __name((event) => {
24
+ const {
25
+ busy,
26
+ busyVariant = "linear",
27
+ busyOpacity,
28
+ onClick,
29
+ children,
30
+ ...rootProps
31
+ } = mergeBoxlikeStyles(theme, props);
32
+ const localOnClick = (event) => {
18
33
  if (busy) {
19
34
  event.preventDefault();
20
35
  } else {
21
36
  const elementName = props["aria-label"] ?? event.currentTarget.textContent;
22
- const windowToNavigate = /* @__PURE__ */ __name(() => target && href ? window.open("", target) ?? globalThis : globalThis, "windowToNavigate");
23
- const callOnClickAndFollowHref = /* @__PURE__ */ __name((windowToNav = windowToNavigate()) => {
37
+ const windowToNavigate = () => isString(target) && isString(href) ? window.open("", target) ?? globalThis : globalThis;
38
+ const callOnClickAndFollowHref = (windowToNav = windowToNavigate()) => {
24
39
  onClick?.(event);
25
- if (href) {
40
+ if (isString(href)) {
26
41
  windowToNav.location.href = href;
27
42
  }
28
- }, "callOnClickAndFollowHref");
43
+ };
29
44
  if (!disableUserEvents && userEvents) {
30
45
  event.preventDefault();
31
46
  const windowToNav = windowToNavigate();
32
- if (href) {
47
+ if (isString(href)) {
33
48
  toPromise(userEvents.userClick({
34
49
  elementName,
35
50
  intent,
@@ -47,70 +62,61 @@ var ButtonExBase = /* @__PURE__ */ __name(({ ref, funnel, intent, target, placem
47
62
  callOnClickAndFollowHref();
48
63
  }
49
64
  }
50
- }, "localOnClick");
51
- return /* @__PURE__ */ React.createElement(Button, {
52
- ref,
53
- href,
54
- onClick: localOnClick,
55
- target,
56
- ...rootProps
57
- }, busy && busyVariant === "linear" ? /* @__PURE__ */ React.createElement(BusyLinearProgress, {
58
- rounded: true,
59
- opacity: busyOpacity ?? 0
60
- }) : null, busy && busyVariant === "circular" ? /* @__PURE__ */ React.createElement(BusyCircularProgress, {
61
- rounded: true,
62
- size: 24,
63
- opacity: busyOpacity ?? 0.5
64
- }) : null, children);
65
- }, "ButtonExBase");
65
+ };
66
+ return /* @__PURE__ */ jsxs(Button, { ref, href, onClick: localOnClick, target, ...rootProps, children: [
67
+ busy && busyVariant === "linear" ? /* @__PURE__ */ jsx(BusyLinearProgress, { rounded: true, opacity: busyOpacity ?? 0 }) : null,
68
+ busy && busyVariant === "circular" ? /* @__PURE__ */ jsx(BusyCircularProgress, { rounded: true, size: 24, opacity: busyOpacity ?? 0.5 }) : null,
69
+ children
70
+ ] });
71
+ };
66
72
  ButtonExBase.displayName = "ButtonExBaseXYLabs";
67
73
 
68
74
  // src/components/ButtonExTo.tsx
69
- import React2 from "react";
75
+ import { isDefined } from "@xylabs/typeof";
70
76
  import { useNavigate } from "react-router-dom";
71
- var ButtonToEx = /* @__PURE__ */ __name(({ ref, to, toOptions, onClick, ...props }) => {
77
+ import { jsx as jsx2 } from "react/jsx-runtime";
78
+ var ButtonToEx = ({
79
+ ref,
80
+ to,
81
+ toOptions,
82
+ onClick,
83
+ ...props
84
+ }) => {
72
85
  const navigate = useNavigate();
73
- const localOnClick = /* @__PURE__ */ __name((event) => {
86
+ const localOnClick = (event) => {
74
87
  onClick?.(event);
75
- if (to) {
88
+ if (isDefined(to)) {
76
89
  void navigate(to, toOptions);
77
90
  }
78
- }, "localOnClick");
79
- return /* @__PURE__ */ React2.createElement(ButtonExBase, {
80
- ref,
81
- onClick: localOnClick,
82
- ...props
83
- });
84
- }, "ButtonToEx");
91
+ };
92
+ return /* @__PURE__ */ jsx2(ButtonExBase, { ref, onClick: localOnClick, ...props });
93
+ };
85
94
  ButtonToEx.displayName = "ButtonToExXYLabs";
86
95
 
87
96
  // src/components/ButtonEx.tsx
88
- var ButtonEx = /* @__PURE__ */ __name(({ ref, ...props }) => {
89
- if (props.to) {
90
- const { to, ...additionalProps } = props;
91
- return /* @__PURE__ */ React3.createElement(ButtonToEx, {
92
- to,
93
- ref,
94
- ...additionalProps
95
- });
97
+ import { jsx as jsx3 } from "react/jsx-runtime";
98
+ var ButtonEx = ({ ref, ...props }) => {
99
+ if (props.to === void 0) {
100
+ return /* @__PURE__ */ jsx3(ButtonExBase, { ...props });
96
101
  } else {
97
- return /* @__PURE__ */ React3.createElement(ButtonExBase, props);
102
+ const { to, ...additionalProps } = props;
103
+ return /* @__PURE__ */ jsx3(ButtonToEx, { to, ref, ...additionalProps });
98
104
  }
99
- }, "ButtonEx");
105
+ };
100
106
  ButtonEx.displayName = "ButtonExXYLabs";
101
107
 
102
108
  // src/components/ButtonExProps.tsx
103
- var asButtonHrefOrToProps = /* @__PURE__ */ __name((props) => {
104
- if (props.href && (props.to || props.toOptions)) {
109
+ import { isDefined as isDefined2, isString as isString2 } from "@xylabs/typeof";
110
+ var asButtonHrefOrToProps = ({
111
+ href,
112
+ to,
113
+ toOptions
114
+ }) => {
115
+ if (isString2(href) && (isDefined2(to) || isDefined2(toOptions))) {
105
116
  throw new Error("ButtonExProps: cannot have both href and to");
106
117
  }
107
- return props.href ? {
108
- href: props.href
109
- } : props.to ? {
110
- to: props.to,
111
- toOptions: props.toOptions
112
- } : {};
113
- }, "asButtonHrefOrToProps");
118
+ return isString2(href) ? { href } : isDefined2(to) ? { to, toOptions } : {};
119
+ };
114
120
  export {
115
121
  ButtonEx,
116
122
  asButtonHrefOrToProps
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/ButtonEx.tsx","../../src/components/ButtonExBase.tsx","../../src/components/ButtonExTo.tsx","../../src/components/ButtonExProps.tsx"],"sourcesContent":["import React from 'react'\n\nimport { ButtonExBase } from './ButtonExBase.tsx'\nimport type { ButtonExProps } from './ButtonExProps.tsx'\nimport { ButtonToEx } from './ButtonExTo.tsx'\n\nconst ButtonEx = ({ ref, ...props }: ButtonExProps) => {\n if (props.to) {\n const { to, ...additionalProps } = props\n return <ButtonToEx to={to} ref={ref} {...additionalProps} />\n } else {\n return <ButtonExBase {...props} />\n }\n}\n\nButtonEx.displayName = 'ButtonExXYLabs'\n\nexport { ButtonEx }\n","import { Button, useTheme } from '@mui/material'\nimport { toPromise } from '@xylabs/promise'\nimport { useUserEvents } from '@xylabs/react-pixel'\nimport {\n BusyCircularProgress, BusyLinearProgress, mergeBoxlikeStyles,\n} from '@xylabs/react-shared'\nimport type { MouseEvent } from 'react'\nimport React from 'react'\n\nimport type { ButtonExProps } from './ButtonExProps.tsx'\n\nconst ButtonExBase = ({\n ref, funnel, intent, target, placement, disableUserEvents, href, ...props\n}: ButtonExProps) => {\n const theme = useTheme()\n const userEvents = useUserEvents()\n const {\n busy, busyVariant = 'linear', busyOpacity, onClick, children, ...rootProps\n } = mergeBoxlikeStyles<ButtonExProps>(theme, props)\n\n const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (busy) {\n // If it is busy, do not allow href clicks\n event.preventDefault()\n } else {\n const elementName = props['aria-label'] ?? event.currentTarget.textContent\n // we do this crazy navigate thing so that we can set it up outside the promise so that safari does not block it\n const windowToNavigate = () => (target && href) ? window.open('', target) ?? globalThis : globalThis\n const callOnClickAndFollowHref = (windowToNav = windowToNavigate()) => {\n onClick?.(event)\n if (href) {\n windowToNav.location.href = href\n }\n }\n if (!disableUserEvents && userEvents) {\n event.preventDefault()\n const windowToNav = windowToNavigate()\n if (href) {\n toPromise(userEvents.userClick({\n elementName, intent, funnel, placement,\n })).then(() => {\n callOnClickAndFollowHref(windowToNav)\n }).catch((ex) => {\n console.error('User event failed', elementName, funnel, placement, ex)\n callOnClickAndFollowHref(windowToNav)\n })\n }\n onClick?.(event)\n } else {\n callOnClickAndFollowHref()\n }\n }\n }\n\n return (\n <Button ref={ref} href={href} onClick={localOnClick} target={target} {...rootProps}>\n {busy && busyVariant === 'linear'\n ? <BusyLinearProgress rounded opacity={busyOpacity ?? 0} />\n : null}\n {busy && busyVariant === 'circular'\n ? <BusyCircularProgress rounded size={24} opacity={busyOpacity ?? 0.5} />\n : null}\n {children}\n </Button>\n )\n}\n\nButtonExBase.displayName = 'ButtonExBaseXYLabs'\n\nexport { ButtonExBase }\n","import type { MouseEvent } from 'react'\nimport React from 'react'\nimport { useNavigate } from 'react-router-dom'\n\nimport { ButtonExBase } from './ButtonExBase.tsx'\nimport type { ButtonExProps } from './ButtonExProps.tsx'\n\nconst ButtonToEx = ({\n ref, to, toOptions, onClick, ...props\n}: ButtonExProps) => {\n const navigate = useNavigate()\n const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event)\n if (to) {\n void navigate(to, toOptions)\n }\n }\n\n return <ButtonExBase ref={ref} onClick={localOnClick} {...props} />\n}\n\nButtonToEx.displayName = 'ButtonToExXYLabs'\n\nexport { ButtonToEx }\n","import type { ButtonProps } from '@mui/material'\nimport type { BoxlikeComponentProps, BusyProps } from '@xylabs/react-shared'\nimport type { NavigateOptions, To } from 'react-router-dom'\n\nexport interface ButtonOnlyHrefProps {\n href?: string\n to?: never\n toOptions?: never\n}\n\nexport interface ButtonOnlyToProps {\n href?: never\n to?: To\n toOptions?: NavigateOptions\n}\n\nexport interface ButtonNoToOrHrefProps {\n href?: never\n to?: never\n toOptions?: never\n}\n\nexport type ButtonHrefOrToOrNoProps = ButtonOnlyHrefProps | ButtonOnlyToProps | ButtonNoToOrHrefProps\n\nexport interface ButtonHrefAndToProps {\n href?: string\n to?: To\n toOptions?: NavigateOptions\n}\n\nexport const asButtonHrefOrToProps = (props: ButtonHrefAndToProps): ButtonHrefOrToOrNoProps => {\n if (props.href && (props.to || props.toOptions)) {\n throw new Error('ButtonExProps: cannot have both href and to')\n }\n return props.href ? { href: props.href } : props.to ? { to: props.to, toOptions: props.toOptions } : {}\n}\n\nexport interface ButtonBaseExProps extends Omit<ButtonProps, 'href'>, BoxlikeComponentProps, BusyProps {\n disableUserEvents?: boolean\n funnel?: string\n intent?: string\n placement?: string\n target?: string\n}\n\nexport type ButtonExProps = ButtonBaseExProps & ButtonHrefOrToOrNoProps\n"],"mappings":"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","names":["React","Button","useTheme","toPromise","useUserEvents","BusyCircularProgress","BusyLinearProgress","mergeBoxlikeStyles","React","ButtonExBase","ref","funnel","intent","target","placement","disableUserEvents","href","props","theme","useTheme","userEvents","useUserEvents","busy","busyVariant","busyOpacity","onClick","children","rootProps","mergeBoxlikeStyles","localOnClick","event","preventDefault","elementName","currentTarget","textContent","windowToNavigate","window","open","globalThis","callOnClickAndFollowHref","windowToNav","location","toPromise","userClick","then","catch","ex","console","error","Button","BusyLinearProgress","rounded","opacity","BusyCircularProgress","size","displayName","React","useNavigate","ButtonToEx","ref","to","toOptions","onClick","props","navigate","useNavigate","localOnClick","event","React","ButtonExBase","displayName","ButtonEx","ref","props","to","additionalProps","React","ButtonToEx","ButtonExBase","displayName","asButtonHrefOrToProps","props","href","to","toOptions","Error"]}
1
+ {"version":3,"sources":["../../src/components/ButtonExBase.tsx","../../src/components/ButtonExTo.tsx","../../src/components/ButtonEx.tsx","../../src/components/ButtonExProps.tsx"],"sourcesContent":["import { Button, useTheme } from '@mui/material'\nimport { toPromise } from '@xylabs/promise'\nimport { useUserEvents } from '@xylabs/react-pixel'\nimport {\n BusyCircularProgress, BusyLinearProgress, mergeBoxlikeStyles,\n} from '@xylabs/react-shared'\nimport { isString } from '@xylabs/typeof'\nimport type { MouseEvent } from 'react'\nimport React from 'react'\n\nimport type { ButtonExProps } from './ButtonExProps.tsx'\n\nconst ButtonExBase = ({\n ref, funnel, intent, target, placement, disableUserEvents, href, ...props\n}: ButtonExProps) => {\n const theme = useTheme()\n const userEvents = useUserEvents()\n const {\n busy, busyVariant = 'linear', busyOpacity, onClick, children, ...rootProps\n } = mergeBoxlikeStyles<ButtonExProps>(theme, props)\n\n const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (busy) {\n // If it is busy, do not allow href clicks\n event.preventDefault()\n } else {\n const elementName = props['aria-label'] ?? event.currentTarget.textContent\n // we do this crazy navigate thing so that we can set it up outside the promise so that safari does not block it\n const windowToNavigate = () => (isString(target) && isString(href)) ? window.open('', target) ?? globalThis : globalThis\n const callOnClickAndFollowHref = (windowToNav = windowToNavigate()) => {\n onClick?.(event)\n if (isString(href)) {\n windowToNav.location.href = href\n }\n }\n if (!disableUserEvents && userEvents) {\n event.preventDefault()\n const windowToNav = windowToNavigate()\n if (isString(href)) {\n toPromise(userEvents.userClick({\n elementName, intent, funnel, placement,\n })).then(() => {\n callOnClickAndFollowHref(windowToNav)\n }).catch((ex) => {\n console.error('User event failed', elementName, funnel, placement, ex)\n callOnClickAndFollowHref(windowToNav)\n })\n }\n onClick?.(event)\n } else {\n callOnClickAndFollowHref()\n }\n }\n }\n\n return (\n <Button ref={ref} href={href} onClick={localOnClick} target={target} {...rootProps}>\n {busy && busyVariant === 'linear'\n ? <BusyLinearProgress rounded opacity={busyOpacity ?? 0} />\n : null}\n {busy && busyVariant === 'circular'\n ? <BusyCircularProgress rounded size={24} opacity={busyOpacity ?? 0.5} />\n : null}\n {children}\n </Button>\n )\n}\n\nButtonExBase.displayName = 'ButtonExBaseXYLabs'\n\nexport { ButtonExBase }\n","import { isDefined } from '@xylabs/typeof'\nimport type { MouseEvent } from 'react'\nimport React from 'react'\nimport { useNavigate } from 'react-router-dom'\n\nimport { ButtonExBase } from './ButtonExBase.tsx'\nimport type { ButtonExProps } from './ButtonExProps.tsx'\n\nconst ButtonToEx = ({\n ref, to, toOptions, onClick, ...props\n}: ButtonExProps) => {\n const navigate = useNavigate()\n const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event)\n if (isDefined(to)) {\n void navigate(to, toOptions)\n }\n }\n\n return <ButtonExBase ref={ref} onClick={localOnClick} {...props} />\n}\n\nButtonToEx.displayName = 'ButtonToExXYLabs'\n\nexport { ButtonToEx }\n","import React from 'react'\n\nimport { ButtonExBase } from './ButtonExBase.tsx'\nimport type { ButtonExProps } from './ButtonExProps.tsx'\nimport { ButtonToEx } from './ButtonExTo.tsx'\n\nconst ButtonEx = ({ ref, ...props }: ButtonExProps) => {\n if (props.to === undefined) {\n return <ButtonExBase {...props} />\n } else {\n const { to, ...additionalProps } = props\n return <ButtonToEx to={to} ref={ref} {...additionalProps} />\n }\n}\n\nButtonEx.displayName = 'ButtonExXYLabs'\n\nexport { ButtonEx }\n","import type { ButtonProps } from '@mui/material'\nimport type { BoxlikeComponentProps, BusyProps } from '@xylabs/react-shared'\nimport { isDefined, isString } from '@xylabs/typeof'\nimport type { NavigateOptions, To } from 'react-router-dom'\n\nexport interface ButtonOnlyHrefProps {\n href?: string\n to?: never\n toOptions?: never\n}\n\nexport interface ButtonOnlyToProps {\n href?: never\n to?: To\n toOptions?: NavigateOptions\n}\n\nexport interface ButtonNoToOrHrefProps {\n href?: never\n to?: never\n toOptions?: never\n}\n\nexport type ButtonHrefOrToOrNoProps = ButtonOnlyHrefProps | ButtonOnlyToProps | ButtonNoToOrHrefProps\n\nexport interface ButtonHrefAndToProps {\n href?: string\n to?: To\n toOptions?: NavigateOptions\n}\n\nexport const asButtonHrefOrToProps = ({\n href, to, toOptions,\n}: ButtonHrefAndToProps): ButtonHrefOrToOrNoProps => {\n if (isString(href) && (isDefined(to) || isDefined(toOptions))) {\n throw new Error('ButtonExProps: cannot have both href and to')\n }\n return isString(href) ? { href } : isDefined(to) ? { to, toOptions } : {}\n}\n\nexport interface ButtonBaseExProps extends Omit<ButtonProps, 'href'>, BoxlikeComponentProps, BusyProps {\n disableUserEvents?: boolean\n funnel?: string\n intent?: string\n placement?: string\n target?: string\n}\n\nexport type ButtonExProps = ButtonBaseExProps & ButtonHrefOrToOrNoProps\n"],"mappings":"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","names":["jsx","jsx","isDefined","isString"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/react-button",
3
- "version": "7.0.0",
3
+ "version": "7.0.2",
4
4
  "description": "Common React library for all XY Labs projects that use React",
5
5
  "keywords": [
6
6
  "utility",
@@ -41,29 +41,32 @@
41
41
  "packages/*"
42
42
  ],
43
43
  "dependencies": {
44
- "@xylabs/promise": "^5.0.0",
45
- "@xylabs/react-pixel": "^7.0.0",
46
- "@xylabs/react-shared": "^7.0.0",
47
- "react-router-dom": "^7.7.1"
44
+ "@xylabs/promise": "~5.0.8",
45
+ "@xylabs/react-pixel": "~7.0.2",
46
+ "@xylabs/react-shared": "~7.0.2",
47
+ "@xylabs/typeof": "~5.0.8",
48
+ "react-router-dom": "~7.8.0"
48
49
  },
49
50
  "devDependencies": {
50
- "@mui/material": "^7.2.0",
51
- "@storybook/react-vite": "^9.0.18",
52
- "@types/react": "^19.1.9",
53
- "@xylabs/react-flexbox": "^7.0.0",
54
- "@xylabs/react-pixel": "^7.0.0",
55
- "@xylabs/ts-scripts-yarn3": "^7.0.2",
56
- "@xylabs/tsconfig-react": "^7.0.2",
57
- "react": "^19.1.1",
58
- "react-dom": "^19.1.1",
59
- "storybook": "^9.0.18",
60
- "typescript": "^5.8.3",
61
- "vite": "^7.0.6"
51
+ "@mui/material": "~7.3.1",
52
+ "@storybook/react-vite": "~9.1.2",
53
+ "@types/react": "~19.1.10",
54
+ "@xylabs/react-flexbox": "~7.0.2",
55
+ "@xylabs/react-pixel": "~7.0.2",
56
+ "@xylabs/ts-scripts-yarn3": "~7.1.1",
57
+ "@xylabs/tsconfig": "~7.1.1",
58
+ "@xylabs/tsconfig-dom": "~7.1.1",
59
+ "@xylabs/tsconfig-react": "~7.1.1",
60
+ "react": "~19.1.1",
61
+ "react-dom": "~19.1.1",
62
+ "storybook": "~9.1.2",
63
+ "typescript": "~5.9.2",
64
+ "vite": "~7.1.2"
62
65
  },
63
66
  "peerDependencies": {
64
67
  "@mui/material": ">=6 <8",
65
- "react": "^19",
66
- "react-dom": "^19"
68
+ "react": "~19",
69
+ "react-dom": "~19"
67
70
  },
68
71
  "publishConfig": {
69
72
  "access": "public"
@@ -5,11 +5,11 @@ import type { ButtonExProps } from './ButtonExProps.tsx'
5
5
  import { ButtonToEx } from './ButtonExTo.tsx'
6
6
 
7
7
  const ButtonEx = ({ ref, ...props }: ButtonExProps) => {
8
- if (props.to) {
8
+ if (props.to === undefined) {
9
+ return <ButtonExBase {...props} />
10
+ } else {
9
11
  const { to, ...additionalProps } = props
10
12
  return <ButtonToEx to={to} ref={ref} {...additionalProps} />
11
- } else {
12
- return <ButtonExBase {...props} />
13
13
  }
14
14
  }
15
15
 
@@ -4,6 +4,7 @@ import { useUserEvents } from '@xylabs/react-pixel'
4
4
  import {
5
5
  BusyCircularProgress, BusyLinearProgress, mergeBoxlikeStyles,
6
6
  } from '@xylabs/react-shared'
7
+ import { isString } from '@xylabs/typeof'
7
8
  import type { MouseEvent } from 'react'
8
9
  import React from 'react'
9
10
 
@@ -25,17 +26,17 @@ const ButtonExBase = ({
25
26
  } else {
26
27
  const elementName = props['aria-label'] ?? event.currentTarget.textContent
27
28
  // 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 = () => (target && href) ? window.open('', target) ?? globalThis : globalThis
29
+ const windowToNavigate = () => (isString(target) && isString(href)) ? window.open('', target) ?? globalThis : globalThis
29
30
  const callOnClickAndFollowHref = (windowToNav = windowToNavigate()) => {
30
31
  onClick?.(event)
31
- if (href) {
32
+ if (isString(href)) {
32
33
  windowToNav.location.href = href
33
34
  }
34
35
  }
35
36
  if (!disableUserEvents && userEvents) {
36
37
  event.preventDefault()
37
38
  const windowToNav = windowToNavigate()
38
- if (href) {
39
+ if (isString(href)) {
39
40
  toPromise(userEvents.userClick({
40
41
  elementName, intent, funnel, placement,
41
42
  })).then(() => {
@@ -1,5 +1,6 @@
1
1
  import type { ButtonProps } from '@mui/material'
2
2
  import type { BoxlikeComponentProps, BusyProps } from '@xylabs/react-shared'
3
+ import { isDefined, isString } from '@xylabs/typeof'
3
4
  import type { NavigateOptions, To } from 'react-router-dom'
4
5
 
5
6
  export interface ButtonOnlyHrefProps {
@@ -28,11 +29,13 @@ export interface ButtonHrefAndToProps {
28
29
  toOptions?: NavigateOptions
29
30
  }
30
31
 
31
- export const asButtonHrefOrToProps = (props: ButtonHrefAndToProps): ButtonHrefOrToOrNoProps => {
32
- if (props.href && (props.to || props.toOptions)) {
32
+ export const asButtonHrefOrToProps = ({
33
+ href, to, toOptions,
34
+ }: ButtonHrefAndToProps): ButtonHrefOrToOrNoProps => {
35
+ if (isString(href) && (isDefined(to) || isDefined(toOptions))) {
33
36
  throw new Error('ButtonExProps: cannot have both href and to')
34
37
  }
35
- return props.href ? { href: props.href } : props.to ? { to: props.to, toOptions: props.toOptions } : {}
38
+ return isString(href) ? { href } : isDefined(to) ? { to, toOptions } : {}
36
39
  }
37
40
 
38
41
  export interface ButtonBaseExProps extends Omit<ButtonProps, 'href'>, BoxlikeComponentProps, BusyProps {
@@ -1,3 +1,4 @@
1
+ import { isDefined } from '@xylabs/typeof'
1
2
  import type { MouseEvent } from 'react'
2
3
  import React from 'react'
3
4
  import { useNavigate } from 'react-router-dom'
@@ -11,7 +12,7 @@ const ButtonToEx = ({
11
12
  const navigate = useNavigate()
12
13
  const localOnClick = (event: MouseEvent<HTMLButtonElement>) => {
13
14
  onClick?.(event)
14
- if (to) {
15
+ if (isDefined(to)) {
15
16
  void navigate(to, toOptions)
16
17
  }
17
18
  }