@bitrise/bitkit-v2 0.3.332 → 0.3.334
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/dist/components/BitkitDialog/BitkitDialog.d.ts +4 -1
- package/dist/components/BitkitDialog/BitkitDialog.js +2 -1
- package/dist/components/BitkitDialog/BitkitDialog.js.map +1 -1
- package/dist/components/BitkitDialog/BitkitFormDialog.js +2 -1
- package/dist/components/BitkitDialog/BitkitFormDialog.js.map +1 -1
- package/dist/components/BitkitDialog/BitkitStepperDialog.d.ts +4 -1
- package/dist/components/BitkitDialog/BitkitStepperDialog.js +2 -1
- package/dist/components/BitkitDialog/BitkitStepperDialog.js.map +1 -1
- package/dist/components/BitkitDialog/DialogShell.d.ts +8 -3
- package/dist/components/BitkitDialog/DialogShell.js +5 -2
- package/dist/components/BitkitDialog/DialogShell.js.map +1 -1
- package/dist/components/BitkitTooltip/BitkitTooltip.d.ts +24 -2
- package/dist/components/BitkitTooltip/BitkitTooltip.js +17 -3
- package/dist/components/BitkitTooltip/BitkitTooltip.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
import { DialogShellProps } from './DialogShell';
|
|
3
4
|
export interface BitkitDialogProps {
|
|
4
5
|
children?: ReactNode;
|
|
5
6
|
closable?: boolean;
|
|
6
7
|
footerButtons?: ReactNode;
|
|
7
8
|
footerContent?: ReactNode;
|
|
8
9
|
headerLabel?: string;
|
|
10
|
+
/** Element to focus when the dialog opens, instead of the first focusable one. */
|
|
11
|
+
initialFocusEl?: DialogShellProps['initialFocusEl'];
|
|
9
12
|
maxHeight?: string;
|
|
10
13
|
onExitComplete?: () => void;
|
|
11
14
|
onOpenChange?: (details: {
|
|
@@ -21,7 +24,7 @@ export interface BitkitDialogProps {
|
|
|
21
24
|
variant?: 'overflowContent';
|
|
22
25
|
}
|
|
23
26
|
declare const _default: {
|
|
24
|
-
({ children, closable, footerButtons, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant, }: BitkitDialogProps): import("react").JSX.Element;
|
|
27
|
+
({ children, closable, footerButtons, footerContent, headerLabel, initialFocusEl, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant, }: BitkitDialogProps): import("react").JSX.Element;
|
|
25
28
|
displayName: string;
|
|
26
29
|
} & {
|
|
27
30
|
ActionTrigger: import('react').ForwardRefExoticComponent<Dialog.ActionTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -4,8 +4,9 @@ import DialogShell from "./DialogShell.js";
|
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import { Dialog } from "@chakra-ui/react/dialog";
|
|
6
6
|
//#region lib/components/BitkitDialog/BitkitDialog.tsx
|
|
7
|
-
var BitkitDialog = ({ children, closable = true, footerButtons, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant }) => /* @__PURE__ */ jsx(DialogShell, {
|
|
7
|
+
var BitkitDialog = ({ children, closable = true, footerButtons, footerContent, headerLabel, initialFocusEl, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant }) => /* @__PURE__ */ jsx(DialogShell, {
|
|
8
8
|
closable,
|
|
9
|
+
initialFocusEl,
|
|
9
10
|
onExitComplete,
|
|
10
11
|
onOpenChange,
|
|
11
12
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { type ReactNode } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport DialogInner from './DialogInner';\nimport DialogShell from './DialogShell';\n\nexport interface BitkitDialogProps {\n children?: ReactNode;\n closable?: boolean;\n footerButtons?: ReactNode;\n footerContent?: ReactNode;\n headerLabel?: string;\n maxHeight?: string;\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n showScrollGradient?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'full';\n title: ReactNode;\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\nconst BitkitDialog = ({\n children,\n closable = true,\n footerButtons,\n footerContent,\n headerLabel,\n maxHeight,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n title,\n trigger,\n variant,\n}: BitkitDialogProps) => (\n <DialogShell\n closable={closable}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content maxHeight={maxHeight}>\n <DialogInner\n closable={closable}\n footerButtons={footerButtons}\n footerContent={footerContent}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {children}\n </DialogInner>\n </Dialog.Content>\n </DialogShell>\n);\n\nBitkitDialog.displayName = 'BitkitDialog';\n\nexport default withSubComponents(BitkitDialog, { ActionTrigger: Dialog.ActionTrigger });\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"BitkitDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { type ReactNode } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport DialogInner from './DialogInner';\nimport DialogShell, { type DialogShellProps } from './DialogShell';\n\nexport interface BitkitDialogProps {\n children?: ReactNode;\n closable?: boolean;\n footerButtons?: ReactNode;\n footerContent?: ReactNode;\n headerLabel?: string;\n /** Element to focus when the dialog opens, instead of the first focusable one. */\n initialFocusEl?: DialogShellProps['initialFocusEl'];\n maxHeight?: string;\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n showScrollGradient?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'full';\n title: ReactNode;\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\nconst BitkitDialog = ({\n children,\n closable = true,\n footerButtons,\n footerContent,\n headerLabel,\n initialFocusEl,\n maxHeight,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n title,\n trigger,\n variant,\n}: BitkitDialogProps) => (\n <DialogShell\n closable={closable}\n initialFocusEl={initialFocusEl}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content maxHeight={maxHeight}>\n <DialogInner\n closable={closable}\n footerButtons={footerButtons}\n footerContent={footerContent}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {children}\n </DialogInner>\n </Dialog.Content>\n </DialogShell>\n);\n\nBitkitDialog.displayName = 'BitkitDialog';\n\nexport default withSubComponents(BitkitDialog, { ActionTrigger: Dialog.ActionTrigger });\n"],"mappings":";;;;;;AA4BA,IAAM,gBAAgB,EACpB,UACA,WAAW,MACX,eACA,eACA,aACA,gBACA,WACA,gBACA,cACA,MACA,eACA,gBACA,oBACA,MACA,OACA,SACA,cAEA,oBAAC,aAAD;CACY;CACM;CACA;CACF;CACR;CACS;CACC;CACV;CACG;CACA;CAET,UAAA,oBAAC,OAAO,SAAR;EAA2B;EACzB,UAAA,oBAAC,aAAD;GACY;GACK;GACA;GACF;GACG;GACI;GACb;GACE;GAER;EACU,CAAA;CACC,CAAA;AACL,CAAA;AAGf,aAAa,cAAc;AAE3B,IAAA,uBAAe,kBAAkB,cAAc,EAAE,eAAe,OAAO,cAAc,CAAC"}
|
|
@@ -13,9 +13,10 @@ import { Dialog } from "@chakra-ui/react/dialog";
|
|
|
13
13
|
* does NOT accept Chakra style props (`width`, `padding`, …), which would override the `size` variant.
|
|
14
14
|
*/
|
|
15
15
|
var BitkitFormDialog = forwardRef((props, ref) => {
|
|
16
|
-
const { children, closable = true, footerButtons, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant, ...formProps } = props;
|
|
16
|
+
const { children, closable = true, footerButtons, footerContent, headerLabel, initialFocusEl, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant, ...formProps } = props;
|
|
17
17
|
return /* @__PURE__ */ jsx(DialogShell, {
|
|
18
18
|
closable,
|
|
19
|
+
initialFocusEl,
|
|
19
20
|
onExitComplete,
|
|
20
21
|
onOpenChange,
|
|
21
22
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitFormDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitFormDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { chakra } from '@chakra-ui/react/styled-system';\nimport { type ComponentPropsWithoutRef, forwardRef } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport { type BitkitDialogProps } from './BitkitDialog';\nimport DialogInner from './DialogInner';\nimport DialogShell from './DialogShell';\n\nexport interface BitkitFormDialogProps\n extends BitkitDialogProps, Omit<ComponentPropsWithoutRef<'form'>, keyof BitkitDialogProps> {}\n\n/**\n * A dialog whose entire content is a `<form>`, so a `type=\"submit\"` button in the footer submits\n * natively. Exposes native form attributes (`onSubmit`, `method`, `noValidate`, …) alongside the\n * standard dialog props. Like the other dialog overlays it owns its own layout — it intentionally\n * does NOT accept Chakra style props (`width`, `padding`, …), which would override the `size` variant.\n */\nconst BitkitFormDialog = forwardRef<HTMLFormElement, BitkitFormDialogProps>((props, ref) => {\n const {\n children,\n closable = true,\n footerButtons,\n footerContent,\n headerLabel,\n maxHeight,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n title,\n trigger,\n variant,\n ...formProps\n } = props;\n\n return (\n <DialogShell\n closable={closable}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content asChild maxHeight={maxHeight}>\n <chakra.form ref={ref} {...formProps}>\n <DialogInner\n closable={closable}\n footerButtons={footerButtons}\n footerContent={footerContent}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {children}\n </DialogInner>\n </chakra.form>\n </Dialog.Content>\n </DialogShell>\n );\n});\n\nBitkitFormDialog.displayName = 'BitkitFormDialog';\n\nexport default withSubComponents(BitkitFormDialog, { ActionTrigger: Dialog.ActionTrigger });\n"],"mappings":";;;;;;;;;;;;;;AAkBA,IAAM,mBAAmB,YAAoD,OAAO,QAAQ;CAC1F,MAAM,EACJ,UACA,WAAW,MACX,eACA,eACA,aACA,WACA,gBACA,cACA,MACA,eACA,gBACA,oBACA,MACA,OACA,SACA,SACA,GAAG,cACD;CAEJ,OACE,oBAAC,aAAD;EACY;EACM;EACF;EACR;EACS;EACC;EACV;EACG;EACA;EAET,UAAA,oBAAC,OAAO,SAAR;GAAgB,SAAA;GAAmB;GACjC,UAAA,oBAAC,OAAO,MAAR;IAAkB;IAAK,GAAI;IACzB,UAAA,oBAAC,aAAD;KACY;KACK;KACA;KACF;KACG;KACI;KACb;KACE;KAER;IACU,CAAA;GACF,CAAA;EACC,CAAA;CACL,CAAA;AAEjB,CAAC;AAED,iBAAiB,cAAc;AAE/B,IAAA,2BAAe,kBAAkB,kBAAkB,EAAE,eAAe,OAAO,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"BitkitFormDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitFormDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { chakra } from '@chakra-ui/react/styled-system';\nimport { type ComponentPropsWithoutRef, forwardRef } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport { type BitkitDialogProps } from './BitkitDialog';\nimport DialogInner from './DialogInner';\nimport DialogShell from './DialogShell';\n\nexport interface BitkitFormDialogProps\n extends BitkitDialogProps, Omit<ComponentPropsWithoutRef<'form'>, keyof BitkitDialogProps> {}\n\n/**\n * A dialog whose entire content is a `<form>`, so a `type=\"submit\"` button in the footer submits\n * natively. Exposes native form attributes (`onSubmit`, `method`, `noValidate`, …) alongside the\n * standard dialog props. Like the other dialog overlays it owns its own layout — it intentionally\n * does NOT accept Chakra style props (`width`, `padding`, …), which would override the `size` variant.\n */\nconst BitkitFormDialog = forwardRef<HTMLFormElement, BitkitFormDialogProps>((props, ref) => {\n const {\n children,\n closable = true,\n footerButtons,\n footerContent,\n headerLabel,\n initialFocusEl,\n maxHeight,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n title,\n trigger,\n variant,\n ...formProps\n } = props;\n\n return (\n <DialogShell\n closable={closable}\n initialFocusEl={initialFocusEl}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content asChild maxHeight={maxHeight}>\n <chakra.form ref={ref} {...formProps}>\n <DialogInner\n closable={closable}\n footerButtons={footerButtons}\n footerContent={footerContent}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {children}\n </DialogInner>\n </chakra.form>\n </Dialog.Content>\n </DialogShell>\n );\n});\n\nBitkitFormDialog.displayName = 'BitkitFormDialog';\n\nexport default withSubComponents(BitkitFormDialog, { ActionTrigger: Dialog.ActionTrigger });\n"],"mappings":";;;;;;;;;;;;;;AAkBA,IAAM,mBAAmB,YAAoD,OAAO,QAAQ;CAC1F,MAAM,EACJ,UACA,WAAW,MACX,eACA,eACA,aACA,gBACA,WACA,gBACA,cACA,MACA,eACA,gBACA,oBACA,MACA,OACA,SACA,SACA,GAAG,cACD;CAEJ,OACE,oBAAC,aAAD;EACY;EACM;EACA;EACF;EACR;EACS;EACC;EACV;EACG;EACA;EAET,UAAA,oBAAC,OAAO,SAAR;GAAgB,SAAA;GAAmB;GACjC,UAAA,oBAAC,OAAO,MAAR;IAAkB;IAAK,GAAI;IACzB,UAAA,oBAAC,aAAD;KACY;KACK;KACA;KACF;KACG;KACI;KACb;KACE;KAER;IACU,CAAA;GACF,CAAA;EACC,CAAA;CACL,CAAA;AAEjB,CAAC;AAED,iBAAiB,cAAc;AAE/B,IAAA,2BAAe,kBAAkB,kBAAkB,EAAE,eAAe,OAAO,cAAc,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { BitkitStepperDialogStepProps } from './BitkitStepperDialogStep';
|
|
4
|
+
import { DialogShellProps } from './DialogShell';
|
|
4
5
|
export { useStepperDialog } from './StepperContext';
|
|
5
6
|
export interface BitkitStepperDialogProps {
|
|
6
7
|
/** `BitkitStepperDialog.Step` children, one per step. */
|
|
@@ -8,6 +9,8 @@ export interface BitkitStepperDialogProps {
|
|
|
8
9
|
closable?: boolean;
|
|
9
10
|
/** Initial step when uncontrolled. Resets to this when the dialog closes. */
|
|
10
11
|
defaultStep?: number;
|
|
12
|
+
/** Element to focus when the dialog opens, instead of the first focusable one. */
|
|
13
|
+
initialFocusEl?: DialogShellProps['initialFocusEl'];
|
|
11
14
|
/**
|
|
12
15
|
* Footer content rendered raw. Stepper footers are space-between (Cancel left, Prev/Next right),
|
|
13
16
|
* so build the nav row here with `useStepperDialog()` — there is no `footerButtons` slot, which
|
|
@@ -34,7 +37,7 @@ export interface BitkitStepperDialogProps {
|
|
|
34
37
|
variant?: 'overflowContent';
|
|
35
38
|
}
|
|
36
39
|
declare const _default: {
|
|
37
|
-
({ children, closable, defaultStep, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, onStepChange, open, preventScroll, scrollBehavior, showScrollGradient, size, step: stepProp, title, trigger, variant, }: BitkitStepperDialogProps): import("react").JSX.Element;
|
|
40
|
+
({ children, closable, defaultStep, initialFocusEl, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, onStepChange, open, preventScroll, scrollBehavior, showScrollGradient, size, step: stepProp, title, trigger, variant, }: BitkitStepperDialogProps): import("react").JSX.Element;
|
|
38
41
|
displayName: string;
|
|
39
42
|
} & {
|
|
40
43
|
ActionTrigger: import('react').ForwardRefExoticComponent<Dialog.ActionTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -13,7 +13,7 @@ import { Dialog } from "@chakra-ui/react/dialog";
|
|
|
13
13
|
* state, auto-renders the steps header, and shows only the active step's body. Footer navigation is
|
|
14
14
|
* wired by the consumer through the `useStepperDialog()` hook.
|
|
15
15
|
*/
|
|
16
|
-
var BitkitStepperDialog = ({ children, closable = true, defaultStep = 0, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, onStepChange, open, preventScroll, scrollBehavior, showScrollGradient, size, step: stepProp, title, trigger, variant }) => {
|
|
16
|
+
var BitkitStepperDialog = ({ children, closable = true, defaultStep = 0, initialFocusEl, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, onStepChange, open, preventScroll, scrollBehavior, showScrollGradient, size, step: stepProp, title, trigger, variant }) => {
|
|
17
17
|
const [internalStep, setInternalStep] = useState(defaultStep);
|
|
18
18
|
const isControlled = stepProp !== void 0;
|
|
19
19
|
const rawStep = (isControlled ? stepProp : internalStep) ?? 0;
|
|
@@ -55,6 +55,7 @@ var BitkitStepperDialog = ({ children, closable = true, defaultStep = 0, footerC
|
|
|
55
55
|
value: ctx,
|
|
56
56
|
children: /* @__PURE__ */ jsx(DialogShell, {
|
|
57
57
|
closable,
|
|
58
|
+
initialFocusEl,
|
|
58
59
|
onExitComplete,
|
|
59
60
|
onOpenChange: handleOpenChange,
|
|
60
61
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitStepperDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitStepperDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { Children, isValidElement, type ReactElement, type ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitSteps from '../BitkitSteps/BitkitSteps';\nimport BitkitStepperDialogStep, { type BitkitStepperDialogStepProps } from './BitkitStepperDialogStep';\nimport DialogInner from './DialogInner';\nimport DialogShell from './DialogShell';\nimport { StepperDialogProvider } from './StepperContext';\n\nexport { useStepperDialog } from './StepperContext';\n\nexport interface BitkitStepperDialogProps {\n /** `BitkitStepperDialog.Step` children, one per step. */\n children: ReactNode;\n closable?: boolean;\n /** Initial step when uncontrolled. Resets to this when the dialog closes. */\n defaultStep?: number;\n /**\n * Footer content rendered raw. Stepper footers are space-between (Cancel left, Prev/Next right),\n * so build the nav row here with `useStepperDialog()` — there is no `footerButtons` slot, which\n * would force right-alignment.\n */\n footerContent?: ReactNode;\n headerLabel?: string;\n maxHeight?: string;\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n /** Called whenever the active step changes (controlled or uncontrolled). */\n onStepChange?: (step: number) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n showScrollGradient?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'full';\n /** Controlled active step. Omit for uncontrolled (see `defaultStep`). */\n step?: number;\n title: ReactNode;\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\n/**\n * A dialog that walks through a sequence of `BitkitStepperDialog.Step` children. It owns the step\n * state, auto-renders the steps header, and shows only the active step's body. Footer navigation is\n * wired by the consumer through the `useStepperDialog()` hook.\n */\nconst BitkitStepperDialog = ({\n children,\n closable = true,\n defaultStep = 0,\n footerContent,\n headerLabel,\n maxHeight,\n onExitComplete,\n onOpenChange,\n onStepChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n step: stepProp,\n title,\n trigger,\n variant,\n}: BitkitStepperDialogProps) => {\n const [internalStep, setInternalStep] = useState(defaultStep);\n const isControlled = stepProp !== undefined;\n const rawStep = (isControlled ? stepProp : internalStep) ?? 0;\n const steps = Children.toArray(children).filter(\n (child): child is ReactElement<BitkitStepperDialogStepProps> =>\n isValidElement(child) && child.type === BitkitStepperDialogStep,\n );\n const totalSteps = steps.length;\n const step = Math.max(0, Math.min(rawStep, Math.max(0, totalSteps - 1)));\n\n const setStep = useCallback(\n (next: number) => {\n const clamped = Math.max(0, Math.min(next, totalSteps - 1));\n if (!isControlled) setInternalStep(clamped);\n onStepChange?.(clamped);\n },\n [isControlled, onStepChange, totalSteps],\n );\n\n const ctx = useMemo(\n () => ({\n goTo: setStep,\n isFirst: step === 0,\n isLast: step === totalSteps - 1,\n next: () => setStep(step + 1),\n prev: () => setStep(step - 1),\n setStep,\n step,\n totalSteps,\n }),\n [setStep, step, totalSteps],\n );\n\n const handleOpenChange = (details: { open: boolean }) => {\n if (!details.open && !isControlled) setInternalStep(defaultStep);\n onOpenChange?.(details);\n };\n\n const stepsHeader = (\n <BitkitSteps step={step}>\n {steps.map((child, index) => (\n <BitkitSteps.Item key={index} label={child.props.label} />\n ))}\n </BitkitSteps>\n );\n\n return (\n <StepperDialogProvider value={ctx}>\n <DialogShell\n closable={closable}\n onExitComplete={onExitComplete}\n onOpenChange={handleOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content maxHeight={maxHeight}>\n <DialogInner\n closable={closable}\n footerContent={footerContent}\n headerExtra={stepsHeader}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {steps[step]}\n </DialogInner>\n </Dialog.Content>\n </DialogShell>\n </StepperDialogProvider>\n );\n};\n\nBitkitStepperDialog.displayName = 'BitkitStepperDialog';\n\nexport default withSubComponents(BitkitStepperDialog, {\n ActionTrigger: Dialog.ActionTrigger,\n Step: BitkitStepperDialogStep,\n});\n"],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"BitkitStepperDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitStepperDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { Children, isValidElement, type ReactElement, type ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitSteps from '../BitkitSteps/BitkitSteps';\nimport BitkitStepperDialogStep, { type BitkitStepperDialogStepProps } from './BitkitStepperDialogStep';\nimport DialogInner from './DialogInner';\nimport DialogShell, { type DialogShellProps } from './DialogShell';\nimport { StepperDialogProvider } from './StepperContext';\n\nexport { useStepperDialog } from './StepperContext';\n\nexport interface BitkitStepperDialogProps {\n /** `BitkitStepperDialog.Step` children, one per step. */\n children: ReactNode;\n closable?: boolean;\n /** Initial step when uncontrolled. Resets to this when the dialog closes. */\n defaultStep?: number;\n /** Element to focus when the dialog opens, instead of the first focusable one. */\n initialFocusEl?: DialogShellProps['initialFocusEl'];\n /**\n * Footer content rendered raw. Stepper footers are space-between (Cancel left, Prev/Next right),\n * so build the nav row here with `useStepperDialog()` — there is no `footerButtons` slot, which\n * would force right-alignment.\n */\n footerContent?: ReactNode;\n headerLabel?: string;\n maxHeight?: string;\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n /** Called whenever the active step changes (controlled or uncontrolled). */\n onStepChange?: (step: number) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n showScrollGradient?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'full';\n /** Controlled active step. Omit for uncontrolled (see `defaultStep`). */\n step?: number;\n title: ReactNode;\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\n/**\n * A dialog that walks through a sequence of `BitkitStepperDialog.Step` children. It owns the step\n * state, auto-renders the steps header, and shows only the active step's body. Footer navigation is\n * wired by the consumer through the `useStepperDialog()` hook.\n */\nconst BitkitStepperDialog = ({\n children,\n closable = true,\n defaultStep = 0,\n initialFocusEl,\n footerContent,\n headerLabel,\n maxHeight,\n onExitComplete,\n onOpenChange,\n onStepChange,\n open,\n preventScroll,\n scrollBehavior,\n showScrollGradient,\n size,\n step: stepProp,\n title,\n trigger,\n variant,\n}: BitkitStepperDialogProps) => {\n const [internalStep, setInternalStep] = useState(defaultStep);\n const isControlled = stepProp !== undefined;\n const rawStep = (isControlled ? stepProp : internalStep) ?? 0;\n const steps = Children.toArray(children).filter(\n (child): child is ReactElement<BitkitStepperDialogStepProps> =>\n isValidElement(child) && child.type === BitkitStepperDialogStep,\n );\n const totalSteps = steps.length;\n const step = Math.max(0, Math.min(rawStep, Math.max(0, totalSteps - 1)));\n\n const setStep = useCallback(\n (next: number) => {\n const clamped = Math.max(0, Math.min(next, totalSteps - 1));\n if (!isControlled) setInternalStep(clamped);\n onStepChange?.(clamped);\n },\n [isControlled, onStepChange, totalSteps],\n );\n\n const ctx = useMemo(\n () => ({\n goTo: setStep,\n isFirst: step === 0,\n isLast: step === totalSteps - 1,\n next: () => setStep(step + 1),\n prev: () => setStep(step - 1),\n setStep,\n step,\n totalSteps,\n }),\n [setStep, step, totalSteps],\n );\n\n const handleOpenChange = (details: { open: boolean }) => {\n if (!details.open && !isControlled) setInternalStep(defaultStep);\n onOpenChange?.(details);\n };\n\n const stepsHeader = (\n <BitkitSteps step={step}>\n {steps.map((child, index) => (\n <BitkitSteps.Item key={index} label={child.props.label} />\n ))}\n </BitkitSteps>\n );\n\n return (\n <StepperDialogProvider value={ctx}>\n <DialogShell\n closable={closable}\n initialFocusEl={initialFocusEl}\n onExitComplete={onExitComplete}\n onOpenChange={handleOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n trigger={trigger}\n variant={variant}\n >\n <Dialog.Content maxHeight={maxHeight}>\n <DialogInner\n closable={closable}\n footerContent={footerContent}\n headerExtra={stepsHeader}\n headerLabel={headerLabel}\n scrollBehavior={scrollBehavior}\n showScrollGradient={showScrollGradient}\n title={title}\n variant={variant}\n >\n {steps[step]}\n </DialogInner>\n </Dialog.Content>\n </DialogShell>\n </StepperDialogProvider>\n );\n};\n\nBitkitStepperDialog.displayName = 'BitkitStepperDialog';\n\nexport default withSubComponents(BitkitStepperDialog, {\n ActionTrigger: Dialog.ActionTrigger,\n Step: BitkitStepperDialogStep,\n});\n"],"mappings":";;;;;;;;;;;;;;;AAiDA,IAAM,uBAAuB,EAC3B,UACA,WAAW,MACX,cAAc,GACd,gBACA,eACA,aACA,WACA,gBACA,cACA,cACA,MACA,eACA,gBACA,oBACA,MACA,MAAM,UACN,OACA,SACA,cAC8B;CAC9B,MAAM,CAAC,cAAc,mBAAmB,SAAS,WAAW;CAC5D,MAAM,eAAe,aAAa,KAAA;CAClC,MAAM,WAAW,eAAe,WAAW,iBAAiB;CAC5D,MAAM,QAAQ,SAAS,QAAQ,QAAQ,CAAC,CAAC,QACtC,UACC,eAAe,KAAK,KAAK,MAAM,SAAS,uBAC5C;CACA,MAAM,aAAa,MAAM;CACzB,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,KAAK,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC;CAEvE,MAAM,UAAU,aACb,SAAiB;EAChB,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,aAAa,CAAC,CAAC;EAC1D,IAAI,CAAC,cAAc,gBAAgB,OAAO;EAC1C,eAAe,OAAO;CACxB,GACA;EAAC;EAAc;EAAc;CAAU,CACzC;CAEA,MAAM,MAAM,eACH;EACL,MAAM;EACN,SAAS,SAAS;EAClB,QAAQ,SAAS,aAAa;EAC9B,YAAY,QAAQ,OAAO,CAAC;EAC5B,YAAY,QAAQ,OAAO,CAAC;EAC5B;EACA;EACA;CACF,IACA;EAAC;EAAS;EAAM;CAAU,CAC5B;CAEA,MAAM,oBAAoB,YAA+B;EACvD,IAAI,CAAC,QAAQ,QAAQ,CAAC,cAAc,gBAAgB,WAAW;EAC/D,eAAe,OAAO;CACxB;CAEA,MAAM,cACJ,oBAAC,qBAAD;EAAmB;EAChB,UAAA,MAAM,KAAK,OAAO,UACjB,oBAAC,oBAAY,MAAb,EAA8B,OAAO,MAAM,MAAM,MAAQ,GAAlC,KAAkC,CAC1D;CACU,CAAA;CAGf,OACE,oBAAC,uBAAD;EAAuB,OAAO;EAC5B,UAAA,oBAAC,aAAD;GACY;GACM;GACA;GAChB,cAAc;GACR;GACS;GACC;GACV;GACG;GACA;GAET,UAAA,oBAAC,OAAO,SAAR;IAA2B;IACzB,UAAA,oBAAC,aAAD;KACY;KACK;KACf,aAAa;KACA;KACG;KACI;KACb;KACE;KAER,UAAA,MAAM;IACI,CAAA;GACC,CAAA;EACL,CAAA;CACQ,CAAA;AAE3B;AAEA,oBAAoB,cAAc;AAElC,IAAA,8BAAe,kBAAkB,qBAAqB;CACpD,eAAe,OAAO;CACtB,MAAM;AACR,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
2
3
|
export interface DialogShellProps {
|
|
3
4
|
/** The `Dialog.Content` element (rendered inside the positioner). */
|
|
4
5
|
children: ReactNode;
|
|
5
6
|
closable?: boolean;
|
|
7
|
+
/** Element to focus when the dialog opens, instead of the first focusable one. */
|
|
8
|
+
initialFocusEl?: ComponentProps<typeof Dialog.Root>['initialFocusEl'];
|
|
6
9
|
onExitComplete?: () => void;
|
|
7
10
|
onOpenChange?: (details: {
|
|
8
11
|
open: boolean;
|
|
@@ -17,8 +20,10 @@ export interface DialogShellProps {
|
|
|
17
20
|
/**
|
|
18
21
|
* Shared overlay shell for every Bitkit dialog flavour: `Dialog.Root` + optional trigger + portal +
|
|
19
22
|
* backdrop + positioner. Dismiss policy is derived from `closable` for ESC/close-trigger; outside
|
|
20
|
-
* clicks are always ignored (`closeOnInteractOutside={false}`).
|
|
23
|
+
* clicks are always ignored (`closeOnInteractOutside={false}`). Note that `closable` does not reach
|
|
24
|
+
* `ActionTrigger` -- a footer button wired to it closes the dialog either way, so a caller that has
|
|
25
|
+
* to block every route out disables that button itself.
|
|
21
26
|
* The caller passes the `Dialog.Content` (or a `Dialog.Content asChild` wrapper) as children.
|
|
22
27
|
**/
|
|
23
|
-
declare const DialogShell: ({ children, closable, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior: scrollBehaviorProp, size, trigger, variant, }: DialogShellProps) => import("react").JSX.Element;
|
|
28
|
+
declare const DialogShell: ({ children, closable, initialFocusEl, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior: scrollBehaviorProp, size, trigger, variant, }: DialogShellProps) => import("react").JSX.Element;
|
|
24
29
|
export default DialogShell;
|
|
@@ -6,14 +6,17 @@ import { Dialog } from "@chakra-ui/react/dialog";
|
|
|
6
6
|
/**
|
|
7
7
|
* Shared overlay shell for every Bitkit dialog flavour: `Dialog.Root` + optional trigger + portal +
|
|
8
8
|
* backdrop + positioner. Dismiss policy is derived from `closable` for ESC/close-trigger; outside
|
|
9
|
-
* clicks are always ignored (`closeOnInteractOutside={false}`).
|
|
9
|
+
* clicks are always ignored (`closeOnInteractOutside={false}`). Note that `closable` does not reach
|
|
10
|
+
* `ActionTrigger` -- a footer button wired to it closes the dialog either way, so a caller that has
|
|
11
|
+
* to block every route out disables that button itself.
|
|
10
12
|
* The caller passes the `Dialog.Content` (or a `Dialog.Content asChild` wrapper) as children.
|
|
11
13
|
**/
|
|
12
|
-
var DialogShell = ({ children, closable = true, onExitComplete, onOpenChange, open, preventScroll = true, scrollBehavior: scrollBehaviorProp, size, trigger, variant }) => {
|
|
14
|
+
var DialogShell = ({ children, closable = true, initialFocusEl, onExitComplete, onOpenChange, open, preventScroll = true, scrollBehavior: scrollBehaviorProp, size, trigger, variant }) => {
|
|
13
15
|
const scrollBehavior = resolveScrollBehavior(variant, scrollBehaviorProp);
|
|
14
16
|
return /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
15
17
|
closeOnEscape: closable,
|
|
16
18
|
closeOnInteractOutside: false,
|
|
19
|
+
initialFocusEl,
|
|
17
20
|
onExitComplete,
|
|
18
21
|
onOpenChange,
|
|
19
22
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DialogShell.js","names":[],"sources":["../../../lib/components/BitkitDialog/DialogShell.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { type ReactNode } from 'react';\n\nimport { resolveScrollBehavior } from './DialogBodyContext';\n\nexport interface DialogShellProps {\n /** The `Dialog.Content` element (rendered inside the positioner). */\n children: ReactNode;\n closable?: boolean;\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n size?: 'sm' | 'md' | 'lg' | 'full';\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\n/**\n * Shared overlay shell for every Bitkit dialog flavour: `Dialog.Root` + optional trigger + portal +\n * backdrop + positioner. Dismiss policy is derived from `closable` for ESC/close-trigger; outside\n * clicks are always ignored (`closeOnInteractOutside={false}`).\n * The caller passes the `Dialog.Content` (or a `Dialog.Content asChild` wrapper) as children.\n **/\n\nconst DialogShell = ({\n children,\n closable = true,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll = true,\n scrollBehavior: scrollBehaviorProp,\n size,\n trigger,\n variant,\n}: DialogShellProps) => {\n const scrollBehavior = resolveScrollBehavior(variant, scrollBehaviorProp);\n\n return (\n <Dialog.Root\n closeOnEscape={closable}\n closeOnInteractOutside={false}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n variant={variant}\n >\n {trigger && <Dialog.Trigger asChild>{trigger}</Dialog.Trigger>}\n <Portal>\n <Dialog.Backdrop />\n <Dialog.Positioner>{children}</Dialog.Positioner>\n </Portal>\n </Dialog.Root>\n );\n};\n\nexport default DialogShell;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DialogShell.js","names":[],"sources":["../../../lib/components/BitkitDialog/DialogShell.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { type ComponentProps, type ReactNode } from 'react';\n\nimport { resolveScrollBehavior } from './DialogBodyContext';\n\nexport interface DialogShellProps {\n /** The `Dialog.Content` element (rendered inside the positioner). */\n children: ReactNode;\n closable?: boolean;\n /** Element to focus when the dialog opens, instead of the first focusable one. */\n initialFocusEl?: ComponentProps<typeof Dialog.Root>['initialFocusEl'];\n onExitComplete?: () => void;\n onOpenChange?: (details: { open: boolean }) => void;\n open?: boolean;\n preventScroll?: boolean;\n scrollBehavior?: 'inside' | 'outside';\n size?: 'sm' | 'md' | 'lg' | 'full';\n trigger?: ReactNode;\n variant?: 'overflowContent';\n}\n\n/**\n * Shared overlay shell for every Bitkit dialog flavour: `Dialog.Root` + optional trigger + portal +\n * backdrop + positioner. Dismiss policy is derived from `closable` for ESC/close-trigger; outside\n * clicks are always ignored (`closeOnInteractOutside={false}`). Note that `closable` does not reach\n * `ActionTrigger` -- a footer button wired to it closes the dialog either way, so a caller that has\n * to block every route out disables that button itself.\n * The caller passes the `Dialog.Content` (or a `Dialog.Content asChild` wrapper) as children.\n **/\n\nconst DialogShell = ({\n children,\n closable = true,\n initialFocusEl,\n onExitComplete,\n onOpenChange,\n open,\n preventScroll = true,\n scrollBehavior: scrollBehaviorProp,\n size,\n trigger,\n variant,\n}: DialogShellProps) => {\n const scrollBehavior = resolveScrollBehavior(variant, scrollBehaviorProp);\n\n return (\n <Dialog.Root\n closeOnEscape={closable}\n closeOnInteractOutside={false}\n initialFocusEl={initialFocusEl}\n onExitComplete={onExitComplete}\n onOpenChange={onOpenChange}\n open={open}\n preventScroll={preventScroll}\n scrollBehavior={scrollBehavior}\n size={size}\n variant={variant}\n >\n {trigger && <Dialog.Trigger asChild>{trigger}</Dialog.Trigger>}\n <Portal>\n <Dialog.Backdrop />\n <Dialog.Positioner>{children}</Dialog.Positioner>\n </Portal>\n </Dialog.Root>\n );\n};\n\nexport default DialogShell;\n"],"mappings":";;;;;;;;;;;;;AA+BA,IAAM,eAAe,EACnB,UACA,WAAW,MACX,gBACA,gBACA,cACA,MACA,gBAAgB,MAChB,gBAAgB,oBAChB,MACA,SACA,cACsB;CACtB,MAAM,iBAAiB,sBAAsB,SAAS,kBAAkB;CAExE,OACE,qBAAC,OAAO,MAAR;EACE,eAAe;EACf,wBAAwB;EACR;EACA;EACF;EACR;EACS;EACC;EACV;EACG;EAVX,UAAA,CAYG,WAAW,oBAAC,OAAO,SAAR;GAAgB,SAAA;GAAS,UAAA;EAAwB,CAAA,GAC7D,qBAAC,QAAD,EAAA,UAAA,CACE,oBAAC,OAAO,UAAR,CAAkB,CAAA,GAClB,oBAAC,OAAO,YAAR,EAAoB,SAA4B,CAAA,CAC1C,EAAA,CAAA,CACG;;AAEjB"}
|
|
@@ -8,7 +8,10 @@ export type BitkitTooltipProps = {
|
|
|
8
8
|
* the pointer can move into the tooltip without dismissing it.
|
|
9
9
|
*/
|
|
10
10
|
button?: BitkitColorButtonProps;
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* The trigger the tooltip is anchored to. Rendered via `asChild`, so it must accept a ref —
|
|
13
|
+
* unless `wrapTrigger` puts a wrapper in between.
|
|
14
|
+
*/
|
|
12
15
|
children: ReactNode;
|
|
13
16
|
/** Dismiss the tooltip when the trigger is clicked. */
|
|
14
17
|
closeOnClick?: TooltipRootProps['closeOnClick'];
|
|
@@ -41,6 +44,25 @@ export type BitkitTooltipProps = {
|
|
|
41
44
|
placement?: NonNullable<TooltipRootProps['positioning']>['placement'];
|
|
42
45
|
/** The tooltip's text. Plain string only — use `icon`, `learnMoreUrl` and `button` for the rest. */
|
|
43
46
|
text: string;
|
|
47
|
+
/**
|
|
48
|
+
* Render the trigger inside a focusable wrapper instead of on the trigger itself. Only for triggers
|
|
49
|
+
* that cannot take focus — on a focusable one this adds a second, redundant tab stop for the same
|
|
50
|
+
* control. A disabled `<button>` dispatches no pointer events and is out of the tab order, so
|
|
51
|
+
* without a wrapper the tooltip never opens — in the one state whose explanation the user actually
|
|
52
|
+
* needs.
|
|
53
|
+
*
|
|
54
|
+
* Chakra v2's `Tooltip` had this built in as `shouldWrapChildren`, rendering a
|
|
55
|
+
* `<span display="inline-block" tabIndex={0}>` that carried the trigger props. Ark's tooltip has no
|
|
56
|
+
* equivalent, and Chakra's own v2->v3 codemod replaces it with a bare `<span>` — which restores
|
|
57
|
+
* hover but silently drops the tab stop, so the tooltip stays unreachable by keyboard. This prop is
|
|
58
|
+
* that escape hatch, `tabIndex` included.
|
|
59
|
+
*
|
|
60
|
+
* The wrapper is a plain focusable span, so focusing it announces the trigger's label and the
|
|
61
|
+
* tooltip text, not the trigger's own state — a disabled button inside is not re-announced as
|
|
62
|
+
* disabled. Conveying that would mean keeping the trigger focusable with `aria-disabled` instead
|
|
63
|
+
* of the native attribute, which is a change to what `disabled` means, not a tooltip concern.
|
|
64
|
+
*/
|
|
65
|
+
wrapTrigger?: boolean;
|
|
44
66
|
};
|
|
45
67
|
/**
|
|
46
68
|
* A hover/focus tooltip anchored to its child. `text` carries the message, `icon` appends a glyph
|
|
@@ -55,7 +77,7 @@ export type BitkitTooltipProps = {
|
|
|
55
77
|
* the manual override.
|
|
56
78
|
*/
|
|
57
79
|
declare const BitkitTooltip: {
|
|
58
|
-
({ button, children, closeOnClick, disablePortal, disabled, icon: Icon, learnMoreTarget, learnMoreUrl, onOpenChange, open, openDelay, placement, text, }: BitkitTooltipProps): import("react").JSX.Element;
|
|
80
|
+
({ button, children, closeOnClick, disablePortal, disabled, icon: Icon, learnMoreTarget, learnMoreUrl, onOpenChange, open, openDelay, placement, text, wrapTrigger, }: BitkitTooltipProps): import("react").JSX.Element;
|
|
59
81
|
displayName: string;
|
|
60
82
|
};
|
|
61
83
|
export default BitkitTooltip;
|
|
@@ -2,7 +2,7 @@ import BitkitPortalContext from "../../utilities/BitkitPortalContext.js";
|
|
|
2
2
|
import { rem } from "../../theme/themeUtils.js";
|
|
3
3
|
import BitkitColorButton from "../BitkitColorButton/BitkitColorButton.js";
|
|
4
4
|
import { Box } from "@chakra-ui/react/box";
|
|
5
|
-
import { useContext, useRef } from "react";
|
|
5
|
+
import { isValidElement, useContext, useRef } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Portal } from "@chakra-ui/react/portal";
|
|
8
8
|
import { Tooltip } from "@chakra-ui/react/tooltip";
|
|
@@ -20,7 +20,7 @@ import { Link } from "@chakra-ui/react/link";
|
|
|
20
20
|
* `BitkitPortalContext` so an interactive tooltip stays inside the focus trap; `disablePortal` is
|
|
21
21
|
* the manual override.
|
|
22
22
|
*/
|
|
23
|
-
var BitkitTooltip = ({ button, children, closeOnClick, disablePortal, disabled, icon: Icon, learnMoreTarget, learnMoreUrl, onOpenChange, open, openDelay, placement = "top", text }) => {
|
|
23
|
+
var BitkitTooltip = ({ button, children, closeOnClick, disablePortal, disabled, icon: Icon, learnMoreTarget, learnMoreUrl, onOpenChange, open, openDelay, placement = "top", text, wrapTrigger }) => {
|
|
24
24
|
const { disablePortal: disablePortalFromContext } = useContext(BitkitPortalContext);
|
|
25
25
|
const isInteractive = !!learnMoreUrl || !!button;
|
|
26
26
|
const triggerRef = useRef(null);
|
|
@@ -43,7 +43,21 @@ var BitkitTooltip = ({ button, children, closeOnClick, disablePortal, disabled,
|
|
|
43
43
|
children: [/* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
44
44
|
ref: triggerRef,
|
|
45
45
|
asChild: true,
|
|
46
|
-
children
|
|
46
|
+
children: wrapTrigger || !isValidElement(children) ? /* @__PURE__ */ jsx(Box, {
|
|
47
|
+
as: "span",
|
|
48
|
+
display: "inline-flex",
|
|
49
|
+
tabIndex: 0,
|
|
50
|
+
css: { _focusVisible: {
|
|
51
|
+
outline: "none",
|
|
52
|
+
"& > *": {
|
|
53
|
+
outlineColor: "var(--focus-ring-color)",
|
|
54
|
+
outlineOffset: "var(--focus-ring-offset, 2px)",
|
|
55
|
+
outlineStyle: "var(--focus-ring-style, solid)",
|
|
56
|
+
outlineWidth: "var(--focus-ring-width, 2px)"
|
|
57
|
+
}
|
|
58
|
+
} },
|
|
59
|
+
children
|
|
60
|
+
}) : children
|
|
47
61
|
}), /* @__PURE__ */ jsx(Portal, {
|
|
48
62
|
disabled: disablePortal || disablePortalFromContext,
|
|
49
63
|
children: /* @__PURE__ */ jsx(Tooltip.Positioner, { children: /* @__PURE__ */ jsxs(Tooltip.Content, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitTooltip.js","names":[],"sources":["../../../lib/components/BitkitTooltip/BitkitTooltip.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Link } from '@chakra-ui/react/link';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Tooltip, type TooltipRootProps } from '@chakra-ui/react/tooltip';\nimport { type ReactNode, type Ref, useContext, useRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport { rem } from '../../theme/themeUtils';\nimport BitkitPortalContext from '../../utilities/BitkitPortalContext';\nimport BitkitColorButton, { type BitkitColorButtonProps } from '../BitkitColorButton/BitkitColorButton';\n\nexport type BitkitTooltipProps = {\n /**\n * Action button rendered at the end of the tooltip. Setting it makes the tooltip interactive, so\n * the pointer can move into the tooltip without dismissing it.\n */\n button?: BitkitColorButtonProps;\n /** The trigger the tooltip is anchored to. Rendered via `asChild`, so it must accept a ref. */\n children: ReactNode;\n /** Dismiss the tooltip when the trigger is clicked. */\n closeOnClick?: TooltipRootProps['closeOnClick'];\n /**\n * Render the tooltip inline instead of in a portal. Only needed when it must stay inside its\n * parent's DOM subtree — a dialog already sets this for you.\n */\n disablePortal?: boolean;\n /** Render the trigger without a tooltip — for hints that only apply in some states. */\n disabled?: TooltipRootProps['disabled'];\n /**\n * Icon rendered after `text`, at size 16. Use it for the affordance the tooltip describes — an\n * `IconArrowNortheast` when the trigger opens something in a new tab, for instance.\n */\n icon?: BitkitIconComponent;\n /** Target for the \"Learn more\" link. `_blank` also sets `rel=\"noopener noreferrer\"`. */\n learnMoreTarget?: HTMLAnchorElement['target'];\n /**\n * Adds a \"Learn more\" link pointing here. Setting it makes the tooltip interactive, so the\n * pointer can move into the tooltip to reach the link.\n */\n learnMoreUrl?: string;\n /** Called when the tooltip opens or closes, including from hover and focus. */\n onOpenChange?: TooltipRootProps['onOpenChange'];\n /** Controlled open state. Leave unset to let hover and focus drive it. */\n open?: TooltipRootProps['open'];\n /** Delay in ms before an uncontrolled tooltip opens on hover. */\n openDelay?: TooltipRootProps['openDelay'];\n /** Where the tooltip sits relative to the trigger (default `top`). It flips if space is short. */\n placement?: NonNullable<TooltipRootProps['positioning']>['placement'];\n /** The tooltip's text. Plain string only — use `icon`, `learnMoreUrl` and `button` for the rest. */\n text: string;\n};\n\n/**\n * A hover/focus tooltip anchored to its child. `text` carries the message, `icon` appends a glyph\n * after it, and `learnMoreUrl`/`button` add a link and an action.\n *\n * Setting either of those two makes the tooltip *interactive*: it gains roomier padding and stays\n * open while the pointer travels into it, so the link and the button can actually be reached.\n *\n * The content renders in a portal, so it escapes any ancestor that traps stacking (`isolation`,\n * `transform`, a `z-index`ed positioned box) or clips overflow. Dialogs turn that off through\n * `BitkitPortalContext` so an interactive tooltip stays inside the focus trap; `disablePortal` is\n * the manual override.\n */\nconst BitkitTooltip = ({\n button,\n children,\n closeOnClick,\n disablePortal,\n disabled,\n icon: Icon,\n learnMoreTarget,\n learnMoreUrl,\n onOpenChange,\n open,\n openDelay,\n placement = 'top',\n text,\n}: BitkitTooltipProps) => {\n const { disablePortal: disablePortalFromContext } = useContext(BitkitPortalContext);\n const isInteractive = !!learnMoreUrl || !!button;\n\n // Anchor positioning to the trigger node by ref rather than relying on Zag's\n // id/data-scope lookup. When the trigger is also wrapped by another `asChild`\n // trigger (e.g. Menu.Trigger), the outer trigger's id and data-scope/data-part\n // overwrite ours on the shared node, so `getTriggerEl()` can't find it and the\n // tooltip loses its anchor. `getAnchorElement` takes precedence over the id\n // lookup, so this is safe in the standalone case too.\n const triggerRef = useRef<HTMLElement>(null);\n\n return (\n <Tooltip.Root\n closeOnClick={closeOnClick}\n disabled={disabled}\n interactive={isInteractive || undefined}\n onOpenChange={onOpenChange}\n open={open}\n openDelay={openDelay}\n paddingSize={isInteractive ? 'lg' : undefined}\n positioning={{ getAnchorElement: () => triggerRef.current, placement, offset: { mainAxis: 4, crossAxis: 0 } }}\n >\n <Tooltip.Trigger ref={triggerRef as Ref<HTMLButtonElement>} asChild>\n {children}\n </Tooltip.Trigger>\n <Portal disabled={disablePortal || disablePortalFromContext}>\n <Tooltip.Positioner>\n <Tooltip.Content maxWidth={rem(320)} css={isInteractive && { minWidth: rem(240) }}>\n <Tooltip.Arrow>\n <Tooltip.ArrowTip />\n </Tooltip.Arrow>\n <Box display=\"flex\" gap=\"8\">\n {text}\n {Icon && <Icon flexShrink=\"0\" size=\"16\" />}\n </Box>\n {isInteractive && (\n <Box alignItems=\"center\" display=\"flex\" gap=\"16\" marginBlockStart=\"16\">\n {learnMoreUrl && (\n <Link\n color=\"color/purple/highlight\"\n href={learnMoreUrl}\n rel={learnMoreTarget === '_blank' ? 'noopener noreferrer' : undefined}\n target={learnMoreTarget}\n >\n Learn more\n </Link>\n )}\n {button && <BitkitColorButton css={{ marginInlineStart: 'auto' }} {...button} />}\n </Box>\n )}\n </Tooltip.Content>\n </Tooltip.Positioner>\n </Portal>\n </Tooltip.Root>\n );\n};\n\nBitkitTooltip.displayName = 'BitkitTooltip';\n\nexport default BitkitTooltip;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAgEA,IAAM,iBAAiB,EACrB,QACA,UACA,cACA,eACA,UACA,MAAM,MACN,iBACA,cACA,cACA,MACA,WACA,YAAY,OACZ,WACwB;CACxB,MAAM,EAAE,eAAe,6BAA6B,WAAW,mBAAmB;CAClF,MAAM,gBAAgB,CAAC,CAAC,gBAAgB,CAAC,CAAC;CAQ1C,MAAM,aAAa,OAAoB,IAAI;CAE3C,OACE,qBAAC,QAAQ,MAAT;EACgB;EACJ;EACV,aAAa,iBAAiB,KAAA;EAChB;EACR;EACK;EACX,aAAa,gBAAgB,OAAO,KAAA;EACpC,aAAa;GAAE,wBAAwB,WAAW;GAAS;GAAW,QAAQ;IAAE,UAAU;IAAG,WAAW;GAAE;EAAE;EAR9G,UAAA,CAUE,oBAAC,QAAQ,SAAT;GAAiB,KAAK;GAAsC,SAAA;GACzD;EACc,CAAA,GACjB,oBAAC,QAAD;GAAQ,UAAU,iBAAiB;GACjC,UAAA,oBAAC,QAAQ,YAAT,EAAA,UACE,qBAAC,QAAQ,SAAT;IAAiB,UAAU,IAAI,GAAG;IAAG,KAAK,iBAAiB,EAAE,UAAU,IAAI,GAAG,EAAE;IAAhF,UAAA;KACE,oBAAC,QAAQ,OAAT,EAAA,UACE,oBAAC,QAAQ,UAAT,CAAmB,CAAA,EACN,CAAA;KACf,qBAAC,KAAD;MAAK,SAAQ;MAAO,KAAI;MAAxB,UAAA,CACG,MACA,QAAQ,oBAAC,MAAD;OAAM,YAAW;OAAI,MAAK;MAAM,CAAA,CACtC;;KACJ,iBACC,qBAAC,KAAD;MAAK,YAAW;MAAS,SAAQ;MAAO,KAAI;MAAK,kBAAiB;MAAlE,UAAA,CACG,gBACC,oBAAC,MAAD;OACE,OAAM;OACN,MAAM;OACN,KAAK,oBAAoB,WAAW,wBAAwB,KAAA;OAC5D,QAAQ;OACT,UAAA;MAEK,CAAA,GAEP,UAAU,oBAAC,mBAAD;OAAmB,KAAK,EAAE,mBAAmB,OAAO;OAAG,GAAI;MAAS,CAAA,CAC5E;;IAEQ;GACC,CAAA,EAAA,CAAA;EACd,CAAA,CACI;;AAElB;AAEA,cAAc,cAAc"}
|
|
1
|
+
{"version":3,"file":"BitkitTooltip.js","names":[],"sources":["../../../lib/components/BitkitTooltip/BitkitTooltip.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Link } from '@chakra-ui/react/link';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Tooltip, type TooltipRootProps } from '@chakra-ui/react/tooltip';\nimport { isValidElement, type ReactNode, type Ref, useContext, useRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport { rem } from '../../theme/themeUtils';\nimport BitkitPortalContext from '../../utilities/BitkitPortalContext';\nimport BitkitColorButton, { type BitkitColorButtonProps } from '../BitkitColorButton/BitkitColorButton';\n\nexport type BitkitTooltipProps = {\n /**\n * Action button rendered at the end of the tooltip. Setting it makes the tooltip interactive, so\n * the pointer can move into the tooltip without dismissing it.\n */\n button?: BitkitColorButtonProps;\n /**\n * The trigger the tooltip is anchored to. Rendered via `asChild`, so it must accept a ref —\n * unless `wrapTrigger` puts a wrapper in between.\n */\n children: ReactNode;\n /** Dismiss the tooltip when the trigger is clicked. */\n closeOnClick?: TooltipRootProps['closeOnClick'];\n /**\n * Render the tooltip inline instead of in a portal. Only needed when it must stay inside its\n * parent's DOM subtree — a dialog already sets this for you.\n */\n disablePortal?: boolean;\n /** Render the trigger without a tooltip — for hints that only apply in some states. */\n disabled?: TooltipRootProps['disabled'];\n /**\n * Icon rendered after `text`, at size 16. Use it for the affordance the tooltip describes — an\n * `IconArrowNortheast` when the trigger opens something in a new tab, for instance.\n */\n icon?: BitkitIconComponent;\n /** Target for the \"Learn more\" link. `_blank` also sets `rel=\"noopener noreferrer\"`. */\n learnMoreTarget?: HTMLAnchorElement['target'];\n /**\n * Adds a \"Learn more\" link pointing here. Setting it makes the tooltip interactive, so the\n * pointer can move into the tooltip to reach the link.\n */\n learnMoreUrl?: string;\n /** Called when the tooltip opens or closes, including from hover and focus. */\n onOpenChange?: TooltipRootProps['onOpenChange'];\n /** Controlled open state. Leave unset to let hover and focus drive it. */\n open?: TooltipRootProps['open'];\n /** Delay in ms before an uncontrolled tooltip opens on hover. */\n openDelay?: TooltipRootProps['openDelay'];\n /** Where the tooltip sits relative to the trigger (default `top`). It flips if space is short. */\n placement?: NonNullable<TooltipRootProps['positioning']>['placement'];\n /** The tooltip's text. Plain string only — use `icon`, `learnMoreUrl` and `button` for the rest. */\n text: string;\n /**\n * Render the trigger inside a focusable wrapper instead of on the trigger itself. Only for triggers\n * that cannot take focus — on a focusable one this adds a second, redundant tab stop for the same\n * control. A disabled `<button>` dispatches no pointer events and is out of the tab order, so\n * without a wrapper the tooltip never opens — in the one state whose explanation the user actually\n * needs.\n *\n * Chakra v2's `Tooltip` had this built in as `shouldWrapChildren`, rendering a\n * `<span display=\"inline-block\" tabIndex={0}>` that carried the trigger props. Ark's tooltip has no\n * equivalent, and Chakra's own v2->v3 codemod replaces it with a bare `<span>` — which restores\n * hover but silently drops the tab stop, so the tooltip stays unreachable by keyboard. This prop is\n * that escape hatch, `tabIndex` included.\n *\n * The wrapper is a plain focusable span, so focusing it announces the trigger's label and the\n * tooltip text, not the trigger's own state — a disabled button inside is not re-announced as\n * disabled. Conveying that would mean keeping the trigger focusable with `aria-disabled` instead\n * of the native attribute, which is a change to what `disabled` means, not a tooltip concern.\n */\n wrapTrigger?: boolean;\n};\n\n/**\n * A hover/focus tooltip anchored to its child. `text` carries the message, `icon` appends a glyph\n * after it, and `learnMoreUrl`/`button` add a link and an action.\n *\n * Setting either of those two makes the tooltip *interactive*: it gains roomier padding and stays\n * open while the pointer travels into it, so the link and the button can actually be reached.\n *\n * The content renders in a portal, so it escapes any ancestor that traps stacking (`isolation`,\n * `transform`, a `z-index`ed positioned box) or clips overflow. Dialogs turn that off through\n * `BitkitPortalContext` so an interactive tooltip stays inside the focus trap; `disablePortal` is\n * the manual override.\n */\nconst BitkitTooltip = ({\n button,\n children,\n closeOnClick,\n disablePortal,\n disabled,\n icon: Icon,\n learnMoreTarget,\n learnMoreUrl,\n onOpenChange,\n open,\n openDelay,\n placement = 'top',\n text,\n wrapTrigger,\n}: BitkitTooltipProps) => {\n const { disablePortal: disablePortalFromContext } = useContext(BitkitPortalContext);\n const isInteractive = !!learnMoreUrl || !!button;\n\n // Anchor positioning to the trigger node by ref rather than relying on Zag's\n // id/data-scope lookup. When the trigger is also wrapped by another `asChild`\n // trigger (e.g. Menu.Trigger), the outer trigger's id and data-scope/data-part\n // overwrite ours on the shared node, so `getTriggerEl()` can't find it and the\n // tooltip loses its anchor. `getAnchorElement` takes precedence over the id\n // lookup, so this is safe in the standalone case too.\n const triggerRef = useRef<HTMLElement>(null);\n\n return (\n <Tooltip.Root\n closeOnClick={closeOnClick}\n disabled={disabled}\n interactive={isInteractive || undefined}\n onOpenChange={onOpenChange}\n open={open}\n openDelay={openDelay}\n paddingSize={isInteractive ? 'lg' : undefined}\n positioning={{ getAnchorElement: () => triggerRef.current, placement, offset: { mainAxis: 4, crossAxis: 0 } }}\n >\n <Tooltip.Trigger ref={triggerRef as Ref<HTMLButtonElement>} asChild>\n {wrapTrigger || !isValidElement(children) ? (\n // inline-flex so the wrapper shrink-wraps the trigger: a plain inline span adds descender\n // space below it and shifts the alignment of whatever sits next to it.\n <Box\n as=\"span\"\n display=\"inline-flex\"\n tabIndex={0}\n css={{\n // The wrapper owns the tab stop, but the focus ring belongs on the trigger: an outline\n // follows the border-radius of the element it is drawn on, and the wrapper has none —\n // so leaving it here squares off a pill or a round trigger.\n _focusVisible: {\n outline: 'none',\n '& > *': {\n outlineColor: 'var(--focus-ring-color)',\n outlineOffset: 'var(--focus-ring-offset, 2px)',\n outlineStyle: 'var(--focus-ring-style, solid)',\n outlineWidth: 'var(--focus-ring-width, 2px)',\n },\n },\n }}\n >\n {children}\n </Box>\n ) : (\n children\n )}\n </Tooltip.Trigger>\n <Portal disabled={disablePortal || disablePortalFromContext}>\n <Tooltip.Positioner>\n <Tooltip.Content maxWidth={rem(320)} css={isInteractive && { minWidth: rem(240) }}>\n <Tooltip.Arrow>\n <Tooltip.ArrowTip />\n </Tooltip.Arrow>\n <Box display=\"flex\" gap=\"8\">\n {text}\n {Icon && <Icon flexShrink=\"0\" size=\"16\" />}\n </Box>\n {isInteractive && (\n <Box alignItems=\"center\" display=\"flex\" gap=\"16\" marginBlockStart=\"16\">\n {learnMoreUrl && (\n <Link\n color=\"color/purple/highlight\"\n href={learnMoreUrl}\n rel={learnMoreTarget === '_blank' ? 'noopener noreferrer' : undefined}\n target={learnMoreTarget}\n >\n Learn more\n </Link>\n )}\n {button && <BitkitColorButton css={{ marginInlineStart: 'auto' }} {...button} />}\n </Box>\n )}\n </Tooltip.Content>\n </Tooltip.Positioner>\n </Portal>\n </Tooltip.Root>\n );\n};\n\nBitkitTooltip.displayName = 'BitkitTooltip';\n\nexport default BitkitTooltip;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsFA,IAAM,iBAAiB,EACrB,QACA,UACA,cACA,eACA,UACA,MAAM,MACN,iBACA,cACA,cACA,MACA,WACA,YAAY,OACZ,MACA,kBACwB;CACxB,MAAM,EAAE,eAAe,6BAA6B,WAAW,mBAAmB;CAClF,MAAM,gBAAgB,CAAC,CAAC,gBAAgB,CAAC,CAAC;CAQ1C,MAAM,aAAa,OAAoB,IAAI;CAE3C,OACE,qBAAC,QAAQ,MAAT;EACgB;EACJ;EACV,aAAa,iBAAiB,KAAA;EAChB;EACR;EACK;EACX,aAAa,gBAAgB,OAAO,KAAA;EACpC,aAAa;GAAE,wBAAwB,WAAW;GAAS;GAAW,QAAQ;IAAE,UAAU;IAAG,WAAW;GAAE;EAAE;EAR9G,UAAA,CAUE,oBAAC,QAAQ,SAAT;GAAiB,KAAK;GAAsC,SAAA;GACzD,UAAA,eAAe,CAAC,eAAe,QAAQ,IAGtC,oBAAC,KAAD;IACE,IAAG;IACH,SAAQ;IACR,UAAU;IACV,KAAK,EAIH,eAAe;KACb,SAAS;KACT,SAAS;MACP,cAAc;MACd,eAAe;MACf,cAAc;MACd,cAAc;KAChB;IACF,EACF;IAEC;GACE,CAAA,IAEL;EAEa,CAAA,GACjB,oBAAC,QAAD;GAAQ,UAAU,iBAAiB;GACjC,UAAA,oBAAC,QAAQ,YAAT,EAAA,UACE,qBAAC,QAAQ,SAAT;IAAiB,UAAU,IAAI,GAAG;IAAG,KAAK,iBAAiB,EAAE,UAAU,IAAI,GAAG,EAAE;IAAhF,UAAA;KACE,oBAAC,QAAQ,OAAT,EAAA,UACE,oBAAC,QAAQ,UAAT,CAAmB,CAAA,EACN,CAAA;KACf,qBAAC,KAAD;MAAK,SAAQ;MAAO,KAAI;MAAxB,UAAA,CACG,MACA,QAAQ,oBAAC,MAAD;OAAM,YAAW;OAAI,MAAK;MAAM,CAAA,CACtC;;KACJ,iBACC,qBAAC,KAAD;MAAK,YAAW;MAAS,SAAQ;MAAO,KAAI;MAAK,kBAAiB;MAAlE,UAAA,CACG,gBACC,oBAAC,MAAD;OACE,OAAM;OACN,MAAM;OACN,KAAK,oBAAoB,WAAW,wBAAwB,KAAA;OAC5D,QAAQ;OACT,UAAA;MAEK,CAAA,GAEP,UAAU,oBAAC,mBAAD;OAAmB,KAAK,EAAE,mBAAmB,OAAO;OAAG,GAAI;MAAS,CAAA,CAC5E;;IAEQ;GACC,CAAA,EAAA,CAAA;EACd,CAAA,CACI;;AAElB;AAEA,cAAc,cAAc"}
|