@consumidor-positivo/aurora 0.12.0 → 1.1.0

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.
Files changed (78) hide show
  1. package/dist/components/Alert/index.d.ts +6 -1
  2. package/dist/components/Alert/index.es.js +10 -1
  3. package/dist/components/Alert/index.es.js.map +1 -1
  4. package/dist/components/Alert/styles.css +1 -1
  5. package/dist/components/BadgeInfo/index.d.ts +0 -4
  6. package/dist/components/BadgeInfo/index.es.js +2 -1
  7. package/dist/components/BadgeInfo/index.es.js.map +1 -1
  8. package/dist/components/BadgeState/index.es.js +2 -1
  9. package/dist/components/BadgeState/index.es.js.map +1 -1
  10. package/dist/components/Button/index.d.ts +9 -0
  11. package/dist/components/Button/index.es.js.map +1 -1
  12. package/dist/components/Button/styles.css +1 -1
  13. package/dist/components/Calendar/index.es.js +2 -2
  14. package/dist/components/CalendarHeader/index.es.js +3 -2
  15. package/dist/components/CalendarHeader/index.es.js.map +1 -1
  16. package/dist/components/Checkbox/index.es.js +1 -1
  17. package/dist/components/Chip/index.es.js +1 -0
  18. package/dist/components/Chip/index.es.js.map +1 -1
  19. package/dist/components/Datepicker/index.es.js +4 -4
  20. package/dist/components/Drawer/index.d.ts +7 -1
  21. package/dist/components/Drawer/index.es.js +4 -1
  22. package/dist/components/Drawer/index.es.js.map +1 -1
  23. package/dist/components/Drawer/styles.css +1 -1
  24. package/dist/components/Footer/index.es.js +1 -0
  25. package/dist/components/Footer/index.es.js.map +1 -1
  26. package/dist/components/Header/index.es.js +1 -1
  27. package/dist/components/Icon/index.es.js +14 -2
  28. package/dist/components/Icon/index.es.js.map +1 -1
  29. package/dist/components/Image/index.es.js +1 -1
  30. package/dist/components/Label/index.es.js +2 -1
  31. package/dist/components/Label/index.es.js.map +1 -1
  32. package/dist/components/LinkButton/index.d.ts +27 -0
  33. package/dist/components/LinkButton/index.es.js +56 -0
  34. package/dist/components/LinkButton/index.es.js.map +1 -0
  35. package/dist/components/LinkButton/styles.css +1 -0
  36. package/dist/components/Modal/index.d.ts +3 -1
  37. package/dist/components/Modal/index.es.js +8 -0
  38. package/dist/components/Modal/index.es.js.map +1 -1
  39. package/dist/components/PortalHolder/index.es.js +1 -1
  40. package/dist/components/Segment/index.es.js +2 -1
  41. package/dist/components/Segment/index.es.js.map +1 -1
  42. package/dist/components/SelectField/index.es.js +1 -1
  43. package/dist/components/SpecialButton/SpecialButton.test.d.ts +1 -0
  44. package/dist/components/SpecialButton/index.d.ts +44 -0
  45. package/dist/components/SpecialButton/index.es.js +229 -0
  46. package/dist/components/SpecialButton/index.es.js.map +1 -0
  47. package/dist/components/SpecialButton/styles.css +1 -0
  48. package/dist/components/Spinner/index.d.ts +9 -5
  49. package/dist/components/Spinner/index.es.js +25 -15
  50. package/dist/components/Spinner/index.es.js.map +1 -1
  51. package/dist/components/SubHeader/index.es.js +1 -0
  52. package/dist/components/SubHeader/index.es.js.map +1 -1
  53. package/dist/components/Tabs/index.d.ts +3 -4
  54. package/dist/components/Tabs/index.es.js +80 -84
  55. package/dist/components/Tabs/index.es.js.map +1 -1
  56. package/dist/components/Tabs/styles.css +1 -1
  57. package/dist/components/Tag/index.es.js +8 -86
  58. package/dist/components/Tag/index.es.js.map +1 -1
  59. package/dist/components/TextareaField/index.es.js.map +1 -1
  60. package/dist/components/form/SelectField/types.d.ts +1 -0
  61. package/dist/components/form/TextareaField/index.d.ts +1 -0
  62. package/dist/components/icons/Icon.test/index.es.js +23 -5
  63. package/dist/components/icons/Icon.test/index.es.js.map +1 -1
  64. package/dist/{index-Dws33tXs.js → index-BgBOcVUP.js} +3 -3
  65. package/dist/{index-Dws33tXs.js.map → index-BgBOcVUP.js.map} +1 -1
  66. package/dist/{index-CnXw6SB7.js → index-DHwXRotU.js} +3 -3
  67. package/dist/{index-CnXw6SB7.js.map → index-DHwXRotU.js.map} +1 -1
  68. package/dist/{index-fyDB87KK.js → index-DnQGzfVW.js} +3 -3
  69. package/dist/{index-fyDB87KK.js.map → index-DnQGzfVW.js.map} +1 -1
  70. package/dist/main.d.ts +4 -2
  71. package/dist/main.es.js +21 -33
  72. package/dist/main.es.js.map +1 -1
  73. package/dist/{tokens-CKZdIZ5O.js → tokens-C4yCunfz.js} +15 -15
  74. package/dist/{tokens-CKZdIZ5O.js.map → tokens-C4yCunfz.js.map} +1 -1
  75. package/package.json +3 -3
  76. package/dist/components/Tag/index.d.ts +0 -22
  77. package/dist/components/Tag/styles.css +0 -1
  78. /package/dist/components/{Tag/Tag.test.d.ts → LinkButton/LinkButton.test.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { B as BREAKPOINT_MD, a as BREAKPOINT_LG } from "../../tokens-CKZdIZ5O.js";
2
+ import { B as BREAKPOINT_MD, a as BREAKPOINT_LG } from "../../tokens-C4yCunfz.js";
3
3
  const Image = ({ srcMob, srcTablet, srcDesk, ...props }) => {
4
4
  return /* @__PURE__ */ jsxs("picture", { children: [
5
5
  /* @__PURE__ */ jsx("source", { media: `(max-width: ${BREAKPOINT_MD})`, srcSet: srcMob }),
@@ -1,10 +1,11 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import "../../index-C6Q03EyZ.js";
3
+ import "react";
3
4
  import "../Icon/index.es.js";
4
5
  import { IconAlertOctagon } from "../icons/IconAlertOctagon/index.es.js";
5
6
  import { IconCheck } from "../icons/IconCheck/index.es.js";
6
7
  import { IconSlash } from "../icons/IconSlash/index.es.js";
7
- import { C as COLOR_SUCCESS_50, b as COLOR_ERROR_50, c as COLOR_NEUTRAL_40 } from "../../tokens-CKZdIZ5O.js";
8
+ import { C as COLOR_SUCCESS_50, b as COLOR_ERROR_50, c as COLOR_NEUTRAL_40 } from "../../tokens-C4yCunfz.js";
8
9
  const FieldLabel = ({
9
10
  id,
10
11
  labelId,
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../../../lib/components/form/Field/Label/index.tsx"],"sourcesContent":["import { IconAlertOctagon, IconCheck, IconSlash } from '@components/icons'\nimport {\n COLOR_ERROR_50,\n COLOR_NEUTRAL_40,\n COLOR_SUCCESS_50,\n} from '@core/tokens'\n\ntype FieldLabelProps = {\n id?: string\n labelId?: string\n text?: string | React.ReactNode\n required?: boolean\n success?: boolean\n error?: boolean\n disabled?: boolean\n showOptionalLabel?: boolean\n}\n\nexport const FieldLabel = ({\n id,\n labelId,\n text,\n required,\n success,\n error,\n disabled,\n showOptionalLabel = true,\n}: FieldLabelProps) => {\n if (!text) return null\n\n const states = [\n {\n state: 'success',\n value: !!success,\n icon: <IconCheck rawColor={COLOR_SUCCESS_50} />,\n },\n {\n state: 'error',\n value: !!error,\n icon: <IconAlertOctagon rawColor={COLOR_ERROR_50} />,\n },\n {\n state: 'disabled',\n value: !!disabled,\n icon: <IconSlash rawColor={COLOR_NEUTRAL_40} />,\n },\n ]\n\n const currentState = states.find(({ value }) => !!value)\n\n return (\n <div className=\"au-field__header\">\n <label id={labelId} htmlFor={id} className=\"au-field__header-label\">\n {text}{' '}\n {showOptionalLabel && !required && (\n <span className=\"au-field__header-label--optional\">(Opcional)</span>\n )}\n {!showOptionalLabel && required && (\n <>\n <strong className=\"au-field__header-label--required\" aria-hidden=\"true\">*</strong>\n <span className=\"au-sr-only\">obrigatório</span>\n </>\n )}\n </label>\n <div className=\"au-field__header-icon\" aria-hidden=\"true\">{currentState?.icon}</div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;AAkBO,MAAM,aAAa,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AACtB,MAAuB;AACrB,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,SAAS;AAAA,IACb;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,WAAA,EAAU,UAAU,iBAAA,CAAkB;AAAA,IAAA;AAAA,IAE/C;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,kBAAA,EAAiB,UAAU,eAAA,CAAgB;AAAA,IAAA;AAAA,IAEpD;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,WAAA,EAAU,UAAU,iBAAA,CAAkB;AAAA,IAAA;AAAA,EAC/C;AAGF,QAAM,eAAe,OAAO,KAAK,CAAC,EAAE,MAAA,MAAY,CAAC,CAAC,KAAK;AAEvD,SACE,qBAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,IAAA,qBAAC,WAAM,IAAI,SAAS,SAAS,IAAI,WAAU,0BACxC,UAAA;AAAA,MAAA;AAAA,MAAM;AAAA,MACN,qBAAqB,CAAC,gCACpB,QAAA,EAAK,WAAU,oCAAmC,UAAA,cAAU;AAAA,MAE9D,CAAC,qBAAqB,YACrB,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAO,WAAU,oCAAmC,eAAY,QAAO,UAAA,KAAC;AAAA,QACzE,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,cAAA,CAAW;AAAA,MAAA,EAAA,CAC1C;AAAA,IAAA,GAEJ;AAAA,wBACC,OAAA,EAAI,WAAU,yBAAwB,eAAY,QAAQ,uDAAc,KAAA,CAAK;AAAA,EAAA,GAChF;AAEJ;"}
1
+ {"version":3,"file":"index.es.js","sources":["../../../lib/components/form/Field/Label/index.tsx"],"sourcesContent":["import { IconAlertOctagon, IconCheck, IconSlash } from '@components/icons'\nimport {\n COLOR_ERROR_50,\n COLOR_NEUTRAL_40,\n COLOR_SUCCESS_50,\n} from '@core/tokens'\n\ntype FieldLabelProps = {\n id?: string\n labelId?: string\n text?: string | React.ReactNode\n required?: boolean\n success?: boolean\n error?: boolean\n disabled?: boolean\n showOptionalLabel?: boolean\n}\n\nexport const FieldLabel = ({\n id,\n labelId,\n text,\n required,\n success,\n error,\n disabled,\n showOptionalLabel = true,\n}: FieldLabelProps) => {\n if (!text) return null\n\n const states = [\n {\n state: 'success',\n value: !!success,\n icon: <IconCheck rawColor={COLOR_SUCCESS_50} />,\n },\n {\n state: 'error',\n value: !!error,\n icon: <IconAlertOctagon rawColor={COLOR_ERROR_50} />,\n },\n {\n state: 'disabled',\n value: !!disabled,\n icon: <IconSlash rawColor={COLOR_NEUTRAL_40} />,\n },\n ]\n\n const currentState = states.find(({ value }) => !!value)\n\n return (\n <div className=\"au-field__header\">\n <label id={labelId} htmlFor={id} className=\"au-field__header-label\">\n {text}{' '}\n {showOptionalLabel && !required && (\n <span className=\"au-field__header-label--optional\">(Opcional)</span>\n )}\n {!showOptionalLabel && required && (\n <>\n <strong className=\"au-field__header-label--required\" aria-hidden=\"true\">*</strong>\n <span className=\"au-sr-only\">obrigatório</span>\n </>\n )}\n </label>\n <div className=\"au-field__header-icon\" aria-hidden=\"true\">{currentState?.icon}</div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;;AAkBO,MAAM,aAAa,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AACtB,MAAuB;AACrB,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,SAAS;AAAA,IACb;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,WAAA,EAAU,UAAU,iBAAA,CAAkB;AAAA,IAAA;AAAA,IAE/C;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,kBAAA,EAAiB,UAAU,eAAA,CAAgB;AAAA,IAAA;AAAA,IAEpD;AAAA,MACE,OAAO;AAAA,MACP,OAAO,CAAC,CAAC;AAAA,MACT,MAAM,oBAAC,WAAA,EAAU,UAAU,iBAAA,CAAkB;AAAA,IAAA;AAAA,EAC/C;AAGF,QAAM,eAAe,OAAO,KAAK,CAAC,EAAE,MAAA,MAAY,CAAC,CAAC,KAAK;AAEvD,SACE,qBAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,IAAA,qBAAC,WAAM,IAAI,SAAS,SAAS,IAAI,WAAU,0BACxC,UAAA;AAAA,MAAA;AAAA,MAAM;AAAA,MACN,qBAAqB,CAAC,gCACpB,QAAA,EAAK,WAAU,oCAAmC,UAAA,cAAU;AAAA,MAE9D,CAAC,qBAAqB,YACrB,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAO,WAAU,oCAAmC,eAAY,QAAO,UAAA,KAAC;AAAA,QACzE,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,cAAA,CAAW;AAAA,MAAA,EAAA,CAC1C;AAAA,IAAA,GAEJ;AAAA,wBACC,OAAA,EAAI,WAAU,yBAAwB,eAAY,QAAQ,uDAAc,KAAA,CAAK;AAAA,EAAA,GAChF;AAEJ;"}
@@ -0,0 +1,27 @@
1
+ import { default as React, ReactNode } from 'react';
2
+ export type LinkButtonProps = ({
3
+ as: 'a';
4
+ href: string;
5
+ target?: string;
6
+ } | {
7
+ as?: 'button';
8
+ href?: never;
9
+ target?: never;
10
+ }) & {
11
+ children?: ReactNode;
12
+ /**
13
+ * Token size (Figma: Link Button, Size). small = 14px text / 16px icons,
14
+ * medium = 16px / 20px, large = 20px / 20px.
15
+ * @default 'medium'
16
+ */
17
+ size?: 'small' | 'medium' | 'large';
18
+ /** Icon rendered before the label (Figma: Left Icon + Switch Icon Left). */
19
+ iconLeft?: ReactNode;
20
+ /** Icon rendered after the label (Figma: Right Icon + Switch Icon Right). */
21
+ iconRight?: ReactNode;
22
+ onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
23
+ disabled?: boolean;
24
+ className?: string;
25
+ 'data-testid'?: string;
26
+ };
27
+ export declare const LinkButton: ({ as, href, target, children, size, iconLeft, iconRight, onClick, disabled, className, "data-testid": dataTestId, }: LinkButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,56 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { c as classNames } from "../../index-C6Q03EyZ.js";
3
+ import './styles.css';const LinkButton = ({
4
+ as,
5
+ href,
6
+ target,
7
+ children = "Link",
8
+ size = "medium",
9
+ iconLeft,
10
+ iconRight,
11
+ onClick,
12
+ disabled = false,
13
+ className,
14
+ "data-testid": dataTestId
15
+ }) => {
16
+ const classes = classNames(
17
+ "au-link-button",
18
+ {
19
+ [`au-link-button--size-${size}`]: !!size,
20
+ "au-link-button--disabled": disabled
21
+ },
22
+ className
23
+ );
24
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
25
+ iconLeft && /* @__PURE__ */ jsx("span", { className: "au-link-button__icon", "aria-hidden": "true", children: iconLeft }),
26
+ children,
27
+ iconRight && /* @__PURE__ */ jsx("span", { className: "au-link-button__icon", "aria-hidden": "true", children: iconRight })
28
+ ] });
29
+ if (as === "a") {
30
+ return /* @__PURE__ */ jsx(
31
+ "a",
32
+ {
33
+ className: classes,
34
+ href,
35
+ target,
36
+ "data-testid": dataTestId,
37
+ children: content
38
+ }
39
+ );
40
+ }
41
+ return /* @__PURE__ */ jsx(
42
+ "button",
43
+ {
44
+ type: "button",
45
+ className: classes,
46
+ onClick,
47
+ disabled,
48
+ "data-testid": dataTestId,
49
+ children: content
50
+ }
51
+ );
52
+ };
53
+ export {
54
+ LinkButton
55
+ };
56
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../../../lib/components/LinkButton/index.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React, { ReactNode } from 'react'\nimport './styles.scss'\n\nexport type LinkButtonProps = (\n | {\n as: 'a'\n href: string\n target?: string\n }\n | {\n as?: 'button'\n href?: never\n target?: never\n }\n) & {\n children?: ReactNode\n /**\n * Token size (Figma: Link Button, Size). small = 14px text / 16px icons,\n * medium = 16px / 20px, large = 20px / 20px.\n * @default 'medium'\n */\n size?: 'small' | 'medium' | 'large'\n /** Icon rendered before the label (Figma: Left Icon + Switch Icon Left). */\n iconLeft?: ReactNode\n /** Icon rendered after the label (Figma: Right Icon + Switch Icon Right). */\n iconRight?: ReactNode\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void\n disabled?: boolean\n className?: string\n 'data-testid'?: string\n}\n\nexport const LinkButton = ({\n as,\n href,\n target,\n children = 'Link',\n size = 'medium',\n iconLeft,\n iconRight,\n onClick,\n disabled = false,\n className,\n 'data-testid': dataTestId,\n}: LinkButtonProps) => {\n const classes = classNames(\n 'au-link-button',\n {\n [`au-link-button--size-${size}`]: !!size,\n 'au-link-button--disabled': disabled,\n },\n className,\n )\n\n const content = (\n <>\n {iconLeft && (\n <span className=\"au-link-button__icon\" aria-hidden=\"true\">\n {iconLeft}\n </span>\n )}\n {children}\n {iconRight && (\n <span className=\"au-link-button__icon\" aria-hidden=\"true\">\n {iconRight}\n </span>\n )}\n </>\n )\n\n if (as === 'a') {\n return (\n <a\n className={classes}\n href={href}\n target={target}\n data-testid={dataTestId}>\n {content}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n className={classes}\n onClick={onClick}\n disabled={disabled}\n data-testid={dataTestId}>\n {content}\n </button>\n )\n}\n"],"names":[],"mappings":";;AAiCO,MAAM,aAAa,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA,eAAe;AACjB,MAAuB;AACrB,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,MACE,CAAC,wBAAwB,IAAI,EAAE,GAAG,CAAC,CAAC;AAAA,MACpC,4BAA4B;AAAA,IAAA;AAAA,IAE9B;AAAA,EAAA;AAGF,QAAM,UACJ,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA,gCACE,QAAA,EAAK,WAAU,wBAAuB,eAAY,QAChD,UAAA,UACH;AAAA,IAED;AAAA,IACA,aACC,oBAAC,QAAA,EAAK,WAAU,wBAAuB,eAAY,QAChD,UAAA,UAAA,CACH;AAAA,EAAA,GAEJ;AAGF,MAAI,OAAO,KAAK;AACd,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,eAAa;AAAA,QACZ,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,eAAa;AAAA,MACZ,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -0,0 +1 @@
1
+ .au-link-button{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0;border:none;background:transparent;color:#0048db;font-family:"Source Sans 3",sans-serif;font-weight:600;text-decoration:none;cursor:pointer}.au-link-button:hover,.au-link-button:focus,.au-link-button:active{color:#1737a4}.au-link-button .au-icon,.au-link-button .au-icon>svg{color:currentColor}.au-link-button__icon{display:inline-flex}.au-link-button--size-small{font-size:14px;line-height:22px}.au-link-button--size-small .au-icon,.au-link-button--size-small .au-icon>svg{width:16px;height:16px}.au-link-button--size-medium{font-size:16px;line-height:24px}.au-link-button--size-medium .au-icon,.au-link-button--size-medium .au-icon>svg{width:20px;height:20px}.au-link-button--size-large{font-size:20px;line-height:28px}.au-link-button--size-large .au-icon,.au-link-button--size-large .au-icon>svg{width:20px;height:20px}.au-link-button--disabled{color:#c4c9d4;cursor:not-allowed}.au-link-button--disabled:hover,.au-link-button--disabled:focus,.au-link-button--disabled:active{color:#c4c9d4}
@@ -3,6 +3,8 @@ type ModalLayoutMobile = 'default' | 'centralized' | 'full-screen';
3
3
  export type ModalProps = {
4
4
  isOpen: boolean;
5
5
  onClose?: () => void;
6
+ /** Calls onClose when the backdrop (area outside the container) is clicked */
7
+ closeOnBackdropClick?: boolean;
6
8
  headerContent?: React.ReactNode | string | JSX.Element | JSX.Element[];
7
9
  content?: React.ReactNode | string | JSX.Element | JSX.Element[];
8
10
  layoutMobile?: ModalLayoutMobile;
@@ -12,5 +14,5 @@ export type ModalProps = {
12
14
  ariaLabel?: string;
13
15
  'data-testid'?: string;
14
16
  };
15
- export declare const Modal: ({ isOpen, onClose, headerContent, content, layoutMobile, layoutDesktop, mobileModalTitle, handleHelpInfo, ariaLabel, "data-testid": dataTestId, }: ModalProps) => import("react/jsx-runtime").JSX.Element | null;
17
+ export declare const Modal: ({ isOpen, onClose, closeOnBackdropClick, headerContent, content, layoutMobile, layoutDesktop, mobileModalTitle, handleHelpInfo, ariaLabel, "data-testid": dataTestId, }: ModalProps) => import("react/jsx-runtime").JSX.Element | null;
16
18
  export {};
@@ -1,5 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { c as classNames } from "../../index-C6Q03EyZ.js";
3
+ import "react";
3
4
  import "../Icon/index.es.js";
4
5
  import { IconX } from "../icons/IconX/index.es.js";
5
6
  import { SubHeader } from "../SubHeader/index.es.js";
@@ -8,6 +9,7 @@ import { i as isMobile } from "../../isMobile-RyKhTreE.js";
8
9
  import './styles.css';const Modal = ({
9
10
  isOpen,
10
11
  onClose,
12
+ closeOnBackdropClick = false,
11
13
  headerContent,
12
14
  content,
13
15
  layoutMobile = "default",
@@ -24,6 +26,11 @@ import './styles.css';const Modal = ({
24
26
  "au-modal--mobile-centralized": layoutMobile === "centralized",
25
27
  "au-modal--desktop-centralized": layoutDesktop === "centralized"
26
28
  });
29
+ function handleBackdropClick(e) {
30
+ if (closeOnBackdropClick && e.target === e.currentTarget && onClose) {
31
+ onClose();
32
+ }
33
+ }
27
34
  return /* @__PURE__ */ jsx(
28
35
  "div",
29
36
  {
@@ -31,6 +38,7 @@ import './styles.css';const Modal = ({
31
38
  role: "dialog",
32
39
  "aria-modal": "true",
33
40
  "aria-label": ariaLabel ?? mobileModalTitle,
41
+ onClick: handleBackdropClick,
34
42
  "data-testid": dataTestId,
35
43
  children: /* @__PURE__ */ jsxs("div", { className: "au-modal__container", children: [
36
44
  /* @__PURE__ */ jsx("div", { className: "au-modal__header", children: /* @__PURE__ */ jsxs(If, { condition: layoutMobile !== "full-screen" || !isMobile(), children: [
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../../../lib/components/Modal/index.tsx"],"sourcesContent":["import { IconX } from '@components/icons'\nimport { SubHeader } from '@components/SubHeader'\nimport classNames from 'classnames'\nimport { If, IfElse, Then, Else } from '../misc'\n\nimport { isMobile } from '@core/utils/isMobile'\n\nimport './styles.scss'\n\ntype ModalLayout = 'default' | 'centralized'\ntype ModalLayoutMobile = 'default' | 'centralized' | 'full-screen'\n\nexport type ModalProps = {\n isOpen: boolean\n onClose?: () => void\n headerContent?: React.ReactNode | string | JSX.Element | JSX.Element[]\n content?: React.ReactNode | string | JSX.Element | JSX.Element[]\n layoutMobile?: ModalLayoutMobile\n layoutDesktop?: ModalLayout\n mobileModalTitle?: string\n handleHelpInfo?: () => void\n ariaLabel?: string\n 'data-testid'?: string\n}\n\nexport const Modal = ({\n isOpen,\n onClose,\n headerContent,\n content,\n layoutMobile = 'default',\n layoutDesktop = 'default',\n mobileModalTitle = 'Título',\n handleHelpInfo,\n ariaLabel,\n 'data-testid': dataTestId,\n}: ModalProps) => {\n if (!isOpen) return null\n\n const modalClasses = classNames('au-modal', {\n 'au-modal--is-open': isOpen,\n 'au-modal--mobile-full-screen': layoutMobile === 'full-screen',\n 'au-modal--mobile-centralized': layoutMobile === 'centralized',\n 'au-modal--desktop-centralized': layoutDesktop === 'centralized',\n })\n\n return (\n <div\n className={modalClasses}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel ?? mobileModalTitle}\n data-testid={dataTestId}>\n <div className=\"au-modal__container\">\n <div className=\"au-modal__header\">\n <IfElse condition={layoutMobile !== 'full-screen' || !isMobile()}>\n <Then>\n <If condition={!!onClose}>\n <button className=\"au-modal__header-close\" onClick={onClose} aria-label=\"Fechar\">\n <IconX className=\"au-modal__header-close-icon\" aria-hidden=\"true\" />\n </button>\n </If>\n {headerContent}\n </Then>\n <Else>\n <If condition={!!onClose}>\n <SubHeader\n title={mobileModalTitle}\n handleReturn={onClose!}\n handleHelpInfo={handleHelpInfo}\n />\n </If>\n </Else>\n </IfElse>\n </div>\n <div className=\"au-modal__content\">{content}</div>\n </div>\n </div>\n )\n}\n"],"names":["IfElse","If"],"mappings":";;;;;;;AAyBO,MAAM,QAAQ,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,eAAe;AACjB,MAAkB;AAChB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,eAAe,WAAW,YAAY;AAAA,IAC1C,qBAAqB;AAAA,IACrB,gCAAgC,iBAAiB;AAAA,IACjD,gCAAgC,iBAAiB;AAAA,IACjD,iCAAiC,kBAAkB;AAAA,EAAA,CACpD;AAED,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,MACX,MAAK;AAAA,MACL,cAAW;AAAA,MACX,cAAY,aAAa;AAAA,MACzB,eAAa;AAAA,MACb,UAAA,qBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAI,WAAU,oBACb,UAAA,qBAACA,IAAA,EAAO,WAAW,iBAAiB,iBAAiB,CAAC,SAAA,GACpD,UAAA;AAAA,UAAA,qBAAC,MAAA,EACC,UAAA;AAAA,YAAA,oBAACC,MAAA,EAAG,WAAW,CAAC,CAAC,SACf,UAAA,oBAAC,UAAA,EAAO,WAAU,0BAAyB,SAAS,SAAS,cAAW,UACtE,8BAAC,OAAA,EAAM,WAAU,+BAA8B,eAAY,QAAO,GACpE,EAAA,CACF;AAAA,YACC;AAAA,UAAA,GACH;AAAA,8BACC,MAAA,EACC,UAAA,oBAACA,QAAG,WAAW,CAAC,CAAC,SACf,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,cACP,cAAc;AAAA,cACd;AAAA,YAAA;AAAA,UAAA,GAEJ,EAAA,CACF;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,QACA,oBAAC,OAAA,EAAI,WAAU,qBAAqB,UAAA,QAAA,CAAQ;AAAA,MAAA,EAAA,CAC9C;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"index.es.js","sources":["../../../lib/components/Modal/index.tsx"],"sourcesContent":["import { IconX } from '@components/icons'\nimport { SubHeader } from '@components/SubHeader'\nimport classNames from 'classnames'\nimport { If, IfElse, Then, Else } from '../misc'\n\nimport { isMobile } from '@core/utils/isMobile'\n\nimport './styles.scss'\n\ntype ModalLayout = 'default' | 'centralized'\ntype ModalLayoutMobile = 'default' | 'centralized' | 'full-screen'\n\nexport type ModalProps = {\n isOpen: boolean\n onClose?: () => void\n /** Calls onClose when the backdrop (area outside the container) is clicked */\n closeOnBackdropClick?: boolean\n headerContent?: React.ReactNode | string | JSX.Element | JSX.Element[]\n content?: React.ReactNode | string | JSX.Element | JSX.Element[]\n layoutMobile?: ModalLayoutMobile\n layoutDesktop?: ModalLayout\n mobileModalTitle?: string\n handleHelpInfo?: () => void\n ariaLabel?: string\n 'data-testid'?: string\n}\n\nexport const Modal = ({\n isOpen,\n onClose,\n closeOnBackdropClick = false,\n headerContent,\n content,\n layoutMobile = 'default',\n layoutDesktop = 'default',\n mobileModalTitle = 'Título',\n handleHelpInfo,\n ariaLabel,\n 'data-testid': dataTestId,\n}: ModalProps) => {\n if (!isOpen) return null\n\n const modalClasses = classNames('au-modal', {\n 'au-modal--is-open': isOpen,\n 'au-modal--mobile-full-screen': layoutMobile === 'full-screen',\n 'au-modal--mobile-centralized': layoutMobile === 'centralized',\n 'au-modal--desktop-centralized': layoutDesktop === 'centralized',\n })\n\n function handleBackdropClick(e: React.MouseEvent<HTMLDivElement>) {\n if (closeOnBackdropClick && e.target === e.currentTarget && onClose) {\n onClose()\n }\n }\n\n return (\n <div\n className={modalClasses}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel ?? mobileModalTitle}\n onClick={handleBackdropClick}\n data-testid={dataTestId}>\n <div className=\"au-modal__container\">\n <div className=\"au-modal__header\">\n <IfElse condition={layoutMobile !== 'full-screen' || !isMobile()}>\n <Then>\n <If condition={!!onClose}>\n <button className=\"au-modal__header-close\" onClick={onClose} aria-label=\"Fechar\">\n <IconX className=\"au-modal__header-close-icon\" aria-hidden=\"true\" />\n </button>\n </If>\n {headerContent}\n </Then>\n <Else>\n <If condition={!!onClose}>\n <SubHeader\n title={mobileModalTitle}\n handleReturn={onClose!}\n handleHelpInfo={handleHelpInfo}\n />\n </If>\n </Else>\n </IfElse>\n </div>\n <div className=\"au-modal__content\">{content}</div>\n </div>\n </div>\n )\n}\n"],"names":["IfElse","If"],"mappings":";;;;;;;;AA2BO,MAAM,QAAQ,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,eAAe;AACjB,MAAkB;AAChB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,eAAe,WAAW,YAAY;AAAA,IAC1C,qBAAqB;AAAA,IACrB,gCAAgC,iBAAiB;AAAA,IACjD,gCAAgC,iBAAiB;AAAA,IACjD,iCAAiC,kBAAkB;AAAA,EAAA,CACpD;AAED,WAAS,oBAAoB,GAAqC;AAChE,QAAI,wBAAwB,EAAE,WAAW,EAAE,iBAAiB,SAAS;AACnE,cAAA;AAAA,IACF;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,MACX,MAAK;AAAA,MACL,cAAW;AAAA,MACX,cAAY,aAAa;AAAA,MACzB,SAAS;AAAA,MACT,eAAa;AAAA,MACb,UAAA,qBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAI,WAAU,oBACb,UAAA,qBAACA,IAAA,EAAO,WAAW,iBAAiB,iBAAiB,CAAC,SAAA,GACpD,UAAA;AAAA,UAAA,qBAAC,MAAA,EACC,UAAA;AAAA,YAAA,oBAACC,MAAA,EAAG,WAAW,CAAC,CAAC,SACf,UAAA,oBAAC,UAAA,EAAO,WAAU,0BAAyB,SAAS,SAAS,cAAW,UACtE,8BAAC,OAAA,EAAM,WAAU,+BAA8B,eAAY,QAAO,GACpE,EAAA,CACF;AAAA,YACC;AAAA,UAAA,GACH;AAAA,8BACC,MAAA,EACC,UAAA,oBAACA,QAAG,WAAW,CAAC,CAAC,SACf,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,cACP,cAAc;AAAA,cACd;AAAA,YAAA;AAAA,UAAA,GAEJ,EAAA,CACF;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,QACA,oBAAC,OAAA,EAAI,WAAU,qBAAqB,UAAA,QAAA,CAAQ;AAAA,MAAA,EAAA,CAC9C;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, Fragment } from "react/jsx-runtime";
2
2
  import { a as above } from "../../screen-DfYo7XQ_.js";
3
+ import { B as BREAKPOINT_MD } from "../../tokens-C4yCunfz.js";
3
4
  import { Portal } from "../Portal/index.es.js";
4
- import { B as BREAKPOINT_MD } from "../../tokens-CKZdIZ5O.js";
5
5
  const PortalHolder = ({ withPortal, children }) => {
6
6
  const shouldUsePortal = !above(BREAKPOINT_MD) && withPortal;
7
7
  if (shouldUsePortal) return /* @__PURE__ */ jsx(Portal, { children });
@@ -1,10 +1,11 @@
1
1
  import "react/jsx-runtime";
2
2
  import "../../index-C6Q03EyZ.js";
3
+ import "react";
3
4
  import "../Icon/index.es.js";
4
5
  import "../icons/IconChevronDown/index.es.js";
5
6
  import "../icons/IconChevronLeft/index.es.js";
6
7
  import "../icons/IconX/index.es.js";
7
- import { S } from "../../index-fyDB87KK.js";
8
+ import { S } from "../../index-DnQGzfVW.js";
8
9
  export {
9
10
  S as Segment
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -10,9 +10,9 @@ import { IconSlash } from "../icons/IconSlash/index.es.js";
10
10
  import { Modal } from "../Modal/index.es.js";
11
11
  import { Text } from "../Text/index.es.js";
12
12
  import { Conditional } from "../Conditional/index.es.js";
13
+ import { c as COLOR_NEUTRAL_40 } from "../../tokens-C4yCunfz.js";
13
14
  import { i as isMobile } from "../../isMobile-RyKhTreE.js";
14
15
  import { F as Field } from "../../index-ZE6zszxw.js";
15
- import { c as COLOR_NEUTRAL_40 } from "../../tokens-CKZdIZ5O.js";
16
16
  import './styles.css';const useSelectField = (options, initialValue, onChange, onBlur, disabled, register, autocomplete = false, fullScreenOptions = false) => {
17
17
  var _a;
18
18
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@@ -0,0 +1,44 @@
1
+ import { ReactNode } from 'react';
2
+ export type SpecialButtonProps = {
3
+ /**
4
+ * Interaction mode: 'press' is hold-to-confirm (Figma: Press Button),
5
+ * 'slider' is swipe-to-confirm (Figma: Swipe Button).
6
+ * @default 'press'
7
+ */
8
+ type?: 'press' | 'slider';
9
+ children?: ReactNode;
10
+ /** Called once when the interaction completes (hold finished / knob dragged to the end). */
11
+ onConfirm?: () => void;
12
+ disabled?: boolean;
13
+ loading?: boolean;
14
+ /**
15
+ * Controlled success state. The component also enters success on its own
16
+ * right after a completed interaction.
17
+ */
18
+ success?: boolean;
19
+ /**
20
+ * Press only — time in milliseconds the user must keep pressing to confirm.
21
+ * @default 1500
22
+ */
23
+ holdDuration?: number;
24
+ /** Press only — stretches the button to fill the container width. */
25
+ expand?: 'x';
26
+ /** Slider only — visual variant (Figma: Swipe Button, ◇ Type Primary | Secondary). */
27
+ variant?: 'primary' | 'secondary';
28
+ /** Slider only — renders an empty skeleton placeholder. */
29
+ skeleton?: boolean;
30
+ /**
31
+ * Slider only — accessible label for the draggable knob. Pressing Enter or
32
+ * Space on the focused knob confirms directly (keyboard alternative to the
33
+ * swipe gesture).
34
+ */
35
+ knobAriaLabel?: string;
36
+ /**
37
+ * Slider only — helper text shown below the button after an incomplete
38
+ * drag, guiding the user to slide all the way to the end.
39
+ * @default 'Arraste até o final para confirmar ação'
40
+ */
41
+ incompleteHint?: ReactNode;
42
+ 'data-testid'?: string;
43
+ };
44
+ export declare const SpecialButton: ({ type, ...props }: SpecialButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,229 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { c as classNames } from "../../index-C6Q03EyZ.js";
3
+ import { useRef, useState, useEffect } from "react";
4
+ import "../Icon/index.es.js";
5
+ import { IconArrowRight } from "../icons/IconArrowRight/index.es.js";
6
+ import { IconCheck } from "../icons/IconCheck/index.es.js";
7
+ import { IconLoader } from "../icons/IconLoader/index.es.js";
8
+ import { IconSlash } from "../icons/IconSlash/index.es.js";
9
+ import { Conditional } from "../Conditional/index.es.js";
10
+ import './styles.css';const KNOB_SIZE = 40;
11
+ const TRACK_PADDING = 4;
12
+ const CONFIRM_THRESHOLD = 0.7;
13
+ const COMPLETE_ANIMATION_MS = 400;
14
+ const _PressButton = ({
15
+ children = "Hold to confirm",
16
+ onConfirm,
17
+ holdDuration = 1500,
18
+ disabled = false,
19
+ loading = false,
20
+ success = false,
21
+ expand,
22
+ "data-testid": dataTestId
23
+ }) => {
24
+ const [holding, setHolding] = useState(false);
25
+ const [confirmed, setConfirmed] = useState(false);
26
+ const timerRef = useRef();
27
+ const isSuccess = success || confirmed;
28
+ const isInteractive = !disabled && !loading && !isSuccess;
29
+ useEffect(() => () => window.clearTimeout(timerRef.current), []);
30
+ function _startHold() {
31
+ if (!isInteractive || holding) return;
32
+ setHolding(true);
33
+ timerRef.current = window.setTimeout(() => {
34
+ setHolding(false);
35
+ setConfirmed(true);
36
+ if (onConfirm) onConfirm();
37
+ }, holdDuration);
38
+ }
39
+ function _cancelHold() {
40
+ if (!holding) return;
41
+ window.clearTimeout(timerRef.current);
42
+ setHolding(false);
43
+ }
44
+ function handleKeyDown(event) {
45
+ if ((event.key === "Enter" || event.key === " ") && !event.repeat) {
46
+ event.preventDefault();
47
+ _startHold();
48
+ }
49
+ }
50
+ function handleKeyUp(event) {
51
+ if (event.key === "Enter" || event.key === " ") _cancelHold();
52
+ }
53
+ const classes = classNames("au-special-button", "au-special-button--type-press", {
54
+ "au-special-button--holding": holding,
55
+ "au-special-button--disabled": disabled,
56
+ "au-special-button--loading": loading,
57
+ "au-special-button--success": isSuccess,
58
+ [`au-special-button--expand-${expand}`]: !!expand
59
+ });
60
+ return /* @__PURE__ */ jsxs(
61
+ "button",
62
+ {
63
+ type: "button",
64
+ className: classes,
65
+ style: {
66
+ "--au-special-button-duration": `${holdDuration}ms`
67
+ },
68
+ disabled: disabled || loading,
69
+ "aria-busy": loading,
70
+ onPointerDown: _startHold,
71
+ onPointerUp: _cancelHold,
72
+ onPointerLeave: _cancelHold,
73
+ onPointerCancel: _cancelHold,
74
+ onKeyDown: handleKeyDown,
75
+ onKeyUp: handleKeyUp,
76
+ "data-testid": dataTestId,
77
+ children: [
78
+ /* @__PURE__ */ jsx("span", { className: "au-special-button__fill", "aria-hidden": "true" }),
79
+ /* @__PURE__ */ jsx(
80
+ Conditional,
81
+ {
82
+ condition: loading,
83
+ renderIf: /* @__PURE__ */ jsx(IconLoader, {}),
84
+ renderElse: /* @__PURE__ */ jsxs("span", { className: "au-special-button__label", children: [
85
+ disabled && /* @__PURE__ */ jsx(IconSlash, { "aria-hidden": "true" }),
86
+ children
87
+ ] })
88
+ }
89
+ )
90
+ ]
91
+ }
92
+ );
93
+ };
94
+ const _SliderButton = ({
95
+ children = "Slide to action",
96
+ onConfirm,
97
+ variant = "primary",
98
+ disabled = false,
99
+ loading = false,
100
+ success = false,
101
+ skeleton = false,
102
+ knobAriaLabel = "Arraste para confirmar",
103
+ incompleteHint = "Arraste até o final para confirmar ação",
104
+ "data-testid": dataTestId
105
+ }) => {
106
+ const containerRef = useRef(null);
107
+ const startXRef = useRef(0);
108
+ const completeTimerRef = useRef();
109
+ const [dragging, setDragging] = useState(false);
110
+ const [dragX, setDragX] = useState(0);
111
+ const [completing, setCompleting] = useState(false);
112
+ const [showHint, setShowHint] = useState(false);
113
+ const [confirmed, setConfirmed] = useState(false);
114
+ const isSuccess = success || confirmed;
115
+ const isInteractive = !disabled && !loading && !isSuccess && !skeleton && !completing;
116
+ useEffect(() => () => window.clearTimeout(completeTimerRef.current), []);
117
+ function _maxDrag() {
118
+ const container = containerRef.current;
119
+ if (!container) return 0;
120
+ return container.clientWidth - KNOB_SIZE - TRACK_PADDING * 2;
121
+ }
122
+ function _confirm() {
123
+ setConfirmed(true);
124
+ if (onConfirm) onConfirm();
125
+ }
126
+ function _complete() {
127
+ setDragging(false);
128
+ setCompleting(true);
129
+ setShowHint(false);
130
+ setDragX(_maxDrag());
131
+ completeTimerRef.current = window.setTimeout(() => {
132
+ setCompleting(false);
133
+ setDragX(0);
134
+ _confirm();
135
+ }, COMPLETE_ANIMATION_MS);
136
+ }
137
+ function handlePointerDown(event) {
138
+ var _a, _b;
139
+ if (!isInteractive) return;
140
+ setDragging(true);
141
+ startXRef.current = event.clientX;
142
+ (_b = (_a = event.currentTarget).setPointerCapture) == null ? void 0 : _b.call(_a, event.pointerId);
143
+ }
144
+ function handlePointerMove(event) {
145
+ if (!dragging) return;
146
+ const max = _maxDrag();
147
+ const delta = event.clientX - startXRef.current;
148
+ const next = Math.min(Math.max(delta, 0), max);
149
+ setDragX(next);
150
+ if (max > 0 && next >= max * CONFIRM_THRESHOLD) _complete();
151
+ }
152
+ function handlePointerEnd() {
153
+ if (!dragging) return;
154
+ setDragging(false);
155
+ if (dragX > 0) setShowHint(true);
156
+ setDragX(0);
157
+ }
158
+ function handleKeyDown(event) {
159
+ if (!isInteractive) return;
160
+ if (event.key === "Enter" || event.key === " ") {
161
+ event.preventDefault();
162
+ _confirm();
163
+ }
164
+ }
165
+ const classes = classNames(
166
+ "au-special-button",
167
+ "au-special-button--type-slider",
168
+ {
169
+ [`au-special-button--variant-${variant}`]: !!variant,
170
+ "au-special-button--dragging": dragging,
171
+ "au-special-button--completing": completing,
172
+ "au-special-button--disabled": disabled,
173
+ "au-special-button--loading": loading,
174
+ "au-special-button--success": isSuccess,
175
+ "au-special-button--skeleton": skeleton
176
+ }
177
+ );
178
+ function _renderKnobIcon() {
179
+ if (isSuccess) return /* @__PURE__ */ jsx(IconCheck, { "aria-hidden": "true" });
180
+ if (disabled) return /* @__PURE__ */ jsx(IconSlash, { "aria-hidden": "true" });
181
+ return /* @__PURE__ */ jsx(IconArrowRight, { "aria-hidden": "true" });
182
+ }
183
+ const maxDrag = _maxDrag();
184
+ const dragProgress = maxDrag > 0 ? dragX / maxDrag : 0;
185
+ return /* @__PURE__ */ jsxs("div", { className: "au-special-button-wrapper", children: [
186
+ /* @__PURE__ */ jsxs(
187
+ "div",
188
+ {
189
+ ref: containerRef,
190
+ className: classes,
191
+ style: {
192
+ "--au-special-button-progress": dragProgress
193
+ },
194
+ "data-testid": dataTestId,
195
+ children: [
196
+ loading && /* @__PURE__ */ jsx(IconLoader, {}),
197
+ !loading && !skeleton && /* @__PURE__ */ jsxs(Fragment, { children: [
198
+ /* @__PURE__ */ jsx("span", { className: "au-special-button__label", children }),
199
+ /* @__PURE__ */ jsx(
200
+ "button",
201
+ {
202
+ type: "button",
203
+ className: "au-special-button__knob",
204
+ "aria-label": knobAriaLabel,
205
+ disabled,
206
+ style: dragX > 0 ? { transform: `translateX(${dragX}px)` } : void 0,
207
+ onPointerDown: handlePointerDown,
208
+ onPointerMove: handlePointerMove,
209
+ onPointerUp: handlePointerEnd,
210
+ onPointerCancel: handlePointerEnd,
211
+ onKeyDown: handleKeyDown,
212
+ children: _renderKnobIcon()
213
+ }
214
+ )
215
+ ] })
216
+ ]
217
+ }
218
+ ),
219
+ showHint && !isSuccess && /* @__PURE__ */ jsx("span", { className: "au-special-button__hint", role: "status", children: incompleteHint })
220
+ ] });
221
+ };
222
+ const SpecialButton = ({ type = "press", ...props }) => {
223
+ if (type === "slider") return /* @__PURE__ */ jsx(_SliderButton, { ...props });
224
+ return /* @__PURE__ */ jsx(_PressButton, { ...props });
225
+ };
226
+ export {
227
+ SpecialButton
228
+ };
229
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../../../lib/components/SpecialButton/index.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React, { ReactNode, useEffect, useRef, useState } from 'react'\nimport {\n IconArrowRight,\n IconCheck,\n IconLoader,\n IconSlash,\n} from '../icons/default'\nimport { Conditional } from '../misc/Conditional'\nimport './styles.scss'\n\nconst KNOB_SIZE = 40\nconst TRACK_PADDING = 4\n// Figma (Behavior): a partir de ~70% do trajeto a ação já conta como\n// confirmada e o botão se completa sozinho.\nconst CONFIRM_THRESHOLD = 0.7\nconst COMPLETE_ANIMATION_MS = 400\n\nexport type SpecialButtonProps = {\n /**\n * Interaction mode: 'press' is hold-to-confirm (Figma: Press Button),\n * 'slider' is swipe-to-confirm (Figma: Swipe Button).\n * @default 'press'\n */\n type?: 'press' | 'slider'\n children?: ReactNode\n /** Called once when the interaction completes (hold finished / knob dragged to the end). */\n onConfirm?: () => void\n disabled?: boolean\n loading?: boolean\n /**\n * Controlled success state. The component also enters success on its own\n * right after a completed interaction.\n */\n success?: boolean\n /**\n * Press only — time in milliseconds the user must keep pressing to confirm.\n * @default 1500\n */\n holdDuration?: number\n /** Press only — stretches the button to fill the container width. */\n expand?: 'x'\n /** Slider only — visual variant (Figma: Swipe Button, ◇ Type Primary | Secondary). */\n variant?: 'primary' | 'secondary'\n /** Slider only — renders an empty skeleton placeholder. */\n skeleton?: boolean\n /**\n * Slider only — accessible label for the draggable knob. Pressing Enter or\n * Space on the focused knob confirms directly (keyboard alternative to the\n * swipe gesture).\n */\n knobAriaLabel?: string\n /**\n * Slider only — helper text shown below the button after an incomplete\n * drag, guiding the user to slide all the way to the end.\n * @default 'Arraste até o final para confirmar ação'\n */\n incompleteHint?: ReactNode\n 'data-testid'?: string\n}\n\nconst _PressButton = ({\n children = 'Hold to confirm',\n onConfirm,\n holdDuration = 1500,\n disabled = false,\n loading = false,\n success = false,\n expand,\n 'data-testid': dataTestId,\n}: SpecialButtonProps) => {\n const [holding, setHolding] = useState(false)\n const [confirmed, setConfirmed] = useState(false)\n const timerRef = useRef<number>()\n\n const isSuccess = success || confirmed\n const isInteractive = !disabled && !loading && !isSuccess\n\n useEffect(() => () => window.clearTimeout(timerRef.current), [])\n\n function _startHold() {\n if (!isInteractive || holding) return\n setHolding(true)\n timerRef.current = window.setTimeout(() => {\n setHolding(false)\n setConfirmed(true)\n if (onConfirm) onConfirm()\n }, holdDuration)\n }\n\n function _cancelHold() {\n if (!holding) return\n window.clearTimeout(timerRef.current)\n setHolding(false)\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {\n if ((event.key === 'Enter' || event.key === ' ') && !event.repeat) {\n event.preventDefault()\n _startHold()\n }\n }\n\n function handleKeyUp(event: React.KeyboardEvent<HTMLButtonElement>) {\n if (event.key === 'Enter' || event.key === ' ') _cancelHold()\n }\n\n const classes = classNames('au-special-button', 'au-special-button--type-press', {\n 'au-special-button--holding': holding,\n 'au-special-button--disabled': disabled,\n 'au-special-button--loading': loading,\n 'au-special-button--success': isSuccess,\n [`au-special-button--expand-${expand}`]: !!expand,\n })\n\n return (\n <button\n type=\"button\"\n className={classes}\n style={\n {\n '--au-special-button-duration': `${holdDuration}ms`,\n } as React.CSSProperties\n }\n disabled={disabled || loading}\n aria-busy={loading}\n onPointerDown={_startHold}\n onPointerUp={_cancelHold}\n onPointerLeave={_cancelHold}\n onPointerCancel={_cancelHold}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n data-testid={dataTestId}>\n <span className=\"au-special-button__fill\" aria-hidden=\"true\" />\n <Conditional\n condition={loading}\n renderIf={<IconLoader />}\n renderElse={\n <span className=\"au-special-button__label\">\n {disabled && <IconSlash aria-hidden=\"true\" />}\n {children}\n </span>\n }\n />\n </button>\n )\n}\n\nconst _SliderButton = ({\n children = 'Slide to action',\n onConfirm,\n variant = 'primary',\n disabled = false,\n loading = false,\n success = false,\n skeleton = false,\n knobAriaLabel = 'Arraste para confirmar',\n incompleteHint = 'Arraste até o final para confirmar ação',\n 'data-testid': dataTestId,\n}: SpecialButtonProps) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const startXRef = useRef(0)\n const completeTimerRef = useRef<number>()\n const [dragging, setDragging] = useState(false)\n const [dragX, setDragX] = useState(0)\n const [completing, setCompleting] = useState(false)\n const [showHint, setShowHint] = useState(false)\n const [confirmed, setConfirmed] = useState(false)\n\n const isSuccess = success || confirmed\n const isInteractive =\n !disabled && !loading && !isSuccess && !skeleton && !completing\n\n useEffect(() => () => window.clearTimeout(completeTimerRef.current), [])\n\n function _maxDrag() {\n const container = containerRef.current\n if (!container) return 0\n return container.clientWidth - KNOB_SIZE - TRACK_PADDING * 2\n }\n\n function _confirm() {\n setConfirmed(true)\n if (onConfirm) onConfirm()\n }\n\n function _complete() {\n setDragging(false)\n setCompleting(true)\n setShowHint(false)\n setDragX(_maxDrag())\n completeTimerRef.current = window.setTimeout(() => {\n setCompleting(false)\n setDragX(0)\n _confirm()\n }, COMPLETE_ANIMATION_MS)\n }\n\n function handlePointerDown(event: React.PointerEvent<HTMLButtonElement>) {\n if (!isInteractive) return\n setDragging(true)\n startXRef.current = event.clientX\n event.currentTarget.setPointerCapture?.(event.pointerId)\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLButtonElement>) {\n if (!dragging) return\n const max = _maxDrag()\n const delta = event.clientX - startXRef.current\n const next = Math.min(Math.max(delta, 0), max)\n setDragX(next)\n if (max > 0 && next >= max * CONFIRM_THRESHOLD) _complete()\n }\n\n function handlePointerEnd() {\n if (!dragging) return\n setDragging(false)\n if (dragX > 0) setShowHint(true)\n setDragX(0)\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {\n if (!isInteractive) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n _confirm()\n }\n }\n\n const classes = classNames(\n 'au-special-button',\n 'au-special-button--type-slider',\n {\n [`au-special-button--variant-${variant}`]: !!variant,\n 'au-special-button--dragging': dragging,\n 'au-special-button--completing': completing,\n 'au-special-button--disabled': disabled,\n 'au-special-button--loading': loading,\n 'au-special-button--success': isSuccess,\n 'au-special-button--skeleton': skeleton,\n },\n )\n\n function _renderKnobIcon() {\n if (isSuccess) return <IconCheck aria-hidden=\"true\" />\n if (disabled) return <IconSlash aria-hidden=\"true\" />\n return <IconArrowRight aria-hidden=\"true\" />\n }\n\n const maxDrag = _maxDrag()\n const dragProgress = maxDrag > 0 ? dragX / maxDrag : 0\n\n return (\n <div className=\"au-special-button-wrapper\">\n <div\n ref={containerRef}\n className={classes}\n style={\n {\n '--au-special-button-progress': dragProgress,\n } as React.CSSProperties\n }\n data-testid={dataTestId}>\n {loading && <IconLoader />}\n {!loading && !skeleton && (\n <>\n <span className=\"au-special-button__label\">{children}</span>\n <button\n type=\"button\"\n className=\"au-special-button__knob\"\n aria-label={knobAriaLabel}\n disabled={disabled}\n style={\n dragX > 0 ? { transform: `translateX(${dragX}px)` } : undefined\n }\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerEnd}\n onPointerCancel={handlePointerEnd}\n onKeyDown={handleKeyDown}>\n {_renderKnobIcon()}\n </button>\n </>\n )}\n </div>\n {showHint && !isSuccess && (\n <span className=\"au-special-button__hint\" role=\"status\">\n {incompleteHint}\n </span>\n )}\n </div>\n )\n}\n\nexport const SpecialButton = ({ type = 'press', ...props }: SpecialButtonProps) => {\n if (type === 'slider') return <_SliderButton {...props} />\n return <_PressButton {...props} />\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .au-special-button{position:relative;display:flex;align-items:center;justify-content:center;height:48px;border-radius:48px;overflow:hidden;background-color:#0048db;color:#fff;font-family:"Source Sans 3",sans-serif;font-size:16px;font-weight:600;-webkit-user-select:none;user-select:none}.au-special-button--type-press{display:inline-flex;gap:8px;padding:8px 16px;border:none;text-align:center;cursor:pointer;touch-action:none;-webkit-tap-highlight-color:transparent}.au-special-button--type-press .au-icon,.au-special-button--type-press .au-icon>svg{width:20px;height:20px;color:#fff}.au-special-button__fill{position:absolute;top:0;left:0;bottom:0;width:0;background-color:#18256c;transition:width .2s ease}.au-special-button__label{position:relative;display:inline-flex;align-items:center;gap:8px}.au-special-button--holding .au-special-button__fill{width:100%;transition:width var(--au-special-button-duration, 1.5s) linear}.au-special-button--type-press.au-special-button--success .au-special-button__fill,.au-special-button--type-press.au-special-button--loading .au-special-button__fill{width:100%;transition:width .3s ease}.au-special-button--type-press.au-special-button--disabled{background-color:#e2e4e9;color:#c4c9d4;cursor:not-allowed}.au-special-button--type-press.au-special-button--disabled .au-icon,.au-special-button--type-press.au-special-button--disabled .au-icon>svg{width:16px;height:16px;color:#c4c9d4}.au-special-button--type-press.au-special-button--loading{cursor:progress}.au-special-button--type-press.au-special-button--loading .au-icon{position:relative;animation:au-special-button-spin 1s infinite linear}.au-special-button--expand-x{width:100%}.au-special-button__knob{position:absolute;top:4px;left:4px;display:flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:none;border-radius:50%;background-color:#fff;box-shadow:0 24px 56px #7686ad14,0 12px 12px #0048db0a;cursor:grab;touch-action:none;transition:transform .2s ease}.au-special-button__knob .au-icon,.au-special-button__knob .au-icon>svg{width:24px;height:24px;color:#0048db}.au-special-button--dragging .au-special-button__knob{cursor:grabbing;transition:none}.au-special-button--completing .au-special-button__knob{cursor:default;transition:transform .4s ease-out}.au-special-button--type-slider .au-special-button__label{padding:8px 48px;opacity:calc(1 - var(--au-special-button-progress, 0) * 1.4);transition:opacity .1s linear}.au-special-button--variant-secondary{background-color:#fff;border:1px solid #0048db;color:#0048db}.au-special-button--type-slider.au-special-button--disabled{background-color:#f6f7fa;border:none;color:#c4c9d4}.au-special-button--type-slider.au-special-button--disabled .au-special-button__knob{background-color:#e2e4e9;box-shadow:none;cursor:not-allowed}.au-special-button--type-slider.au-special-button--disabled .au-special-button__knob .au-icon,.au-special-button--type-slider.au-special-button--disabled .au-special-button__knob .au-icon>svg{color:#c4c9d4}.au-special-button--type-slider.au-special-button--success{background-color:#138040;border:none;color:#fff}.au-special-button--type-slider.au-special-button--success .au-special-button__label{opacity:0}.au-special-button--type-slider.au-special-button--success .au-special-button__knob{left:auto;right:4px;cursor:default}.au-special-button--type-slider.au-special-button--success .au-special-button__knob .au-icon,.au-special-button--type-slider.au-special-button--success .au-special-button__knob .au-icon>svg{color:#138040}.au-special-button--variant-secondary.au-special-button--success{background-color:#fff;border:1px solid #10593b;color:#10593b}.au-special-button--variant-secondary.au-special-button--success .au-special-button__knob .au-icon,.au-special-button--variant-secondary.au-special-button--success .au-special-button__knob .au-icon>svg{color:#10593b}.au-special-button--type-slider.au-special-button--loading{background-color:#10593b;border:none;cursor:progress}.au-special-button--type-slider.au-special-button--loading .au-icon{animation:au-special-button-spin 1s infinite linear}.au-special-button--type-slider.au-special-button--loading .au-icon,.au-special-button--type-slider.au-special-button--loading .au-icon>svg{width:20px;height:20px;color:#fff}.au-special-button--skeleton{background-color:#f6f7fa;border:none;animation:au-special-button-pulse 1.5s ease-in-out infinite}.au-special-button__hint{display:block;margin-top:8px;text-align:center;font-family:"Source Sans 3",sans-serif;font-size:12px;font-weight:400;color:#313131}.au-special-button-wrapper{width:100%}@keyframes au-special-button-spin{to{transform:rotate(360deg)}}@keyframes au-special-button-pulse{0%,to{opacity:1}50%{opacity:.6}}
@@ -1,7 +1,11 @@
1
- type SpinnerProps = {
2
- size: number;
3
- color: string;
1
+ export type SpinnerProps = {
2
+ /**
3
+ * Token size (Figma: Spinner, ↕ Size). small = 16px, medium = 20px, large = 32px.
4
+ * @default 'medium'
5
+ */
6
+ size?: 'small' | 'medium' | 'large';
7
+ /** White spinner for colored backgrounds (Figma: Negative). */
8
+ negative?: boolean;
4
9
  'data-testid'?: string;
5
10
  };
6
- export declare const Spinner: React.FC<SpinnerProps>;
7
- export {};
11
+ export declare const Spinner: ({ size, negative, "data-testid": dataTestId, }: SpinnerProps) => import("react/jsx-runtime").JSX.Element;