@bitrise/bitkit-v2 0.3.388 → 0.3.389
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/AGENTS.md +2 -1
- package/dist/components/BitkitActionMenu/BitkitActionMenu.d.ts +14 -2
- package/dist/components/BitkitActionMenu/BitkitActionMenu.js +13 -5
- package/dist/components/BitkitActionMenu/BitkitActionMenu.js.map +1 -1
- package/dist/components/BitkitDialog/BitkitDialog.d.ts +3 -2
- package/dist/components/BitkitDialog/BitkitDialog.js.map +1 -1
- package/dist/components/BitkitDialog/BitkitFormDialog.d.ts +1 -1
- package/dist/components/BitkitDialog/BitkitStepperDialog.d.ts +3 -2
- package/dist/components/BitkitDialog/BitkitStepperDialog.js.map +1 -1
- package/dist/components/BitkitDialog/DialogShell.d.ts +0 -8
- package/dist/components/BitkitDialog/DialogShell.js.map +1 -1
- package/dist/components/BitkitToast/BitkitToast.d.ts +2 -12
- package/dist/components/BitkitToast/BitkitToast.js.map +1 -1
- package/dist/theme/slot-recipes/Menu.recipe.js +3 -0
- package/dist/theme/slot-recipes/Menu.recipe.js.map +1 -1
- package/dist/utilities/dataAttributes.d.ts +36 -0
- package/dist/utilities/dataAttributes.js +30 -0
- package/dist/utilities/dataAttributes.js.map +1 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -116,7 +116,7 @@ Bitkit components use consistent prop names across the library:
|
|
|
116
116
|
<BitkitActionMenu.Item href="/settings" value="settings">Settings</BitkitActionMenu.Item>
|
|
117
117
|
<BitkitActionMenu.Item href="https://example.com" isExternal value="docs">Open docs</BitkitActionMenu.Item>
|
|
118
118
|
```
|
|
119
|
-
- **`BitkitActionMenu.Item` slots** — `icon` is the leading icon, sized from the menu's `size`; `secondaryText` adds a quieter second line; `isDanger` styles the row as destructive. There is no trailing-icon prop: the only trailing icon in the design is the "leaves this page" arrow, and `isExternal` adds it for you. Groups and rules are their own children, not props:
|
|
119
|
+
- **`BitkitActionMenu.Item` slots** — `icon` is the leading icon, sized from the menu's `size`; `secondaryText` adds a quieter second line; `isDanger` styles the row as destructive. There is no trailing-icon prop: the only trailing icon in the design is the "leaves this page" arrow, and `isExternal` adds it for you. `value` is optional — omit it for a command item that does its work in `onClick`, pass one only if you read `onSelect` on the menu. Groups and rules are their own children, not props:
|
|
120
120
|
```tsx
|
|
121
121
|
<BitkitActionMenu size="md" trigger={<BitkitIconButton icon={IconDots} label="Actions" />}>
|
|
122
122
|
<BitkitActionMenu.Item icon={IconPencil} value="rename">Rename</BitkitActionMenu.Item>
|
|
@@ -127,6 +127,7 @@ Bitkit components use consistent prop names across the library:
|
|
|
127
127
|
<BitkitActionMenu.Item icon={IconTrash} isDanger secondaryText="This cannot be undone" value="delete">Delete</BitkitActionMenu.Item>
|
|
128
128
|
</BitkitActionMenu>
|
|
129
129
|
```
|
|
130
|
+
`data-*` attributes on `BitkitActionMenu` reach the element carrying `role="menu"` (the portalled list), and nothing else passes through — the same contract the dialogs have.
|
|
130
131
|
- **Form components are flat** — `BitkitTextInput`, `BitkitSelect`, `BitkitCombobox`, etc. expose `label`, `errorText`, `helperText`, etc. directly as props. No need to wrap in a separate field component.
|
|
131
132
|
- **`BitkitTextInput` in-field slots** — all four slots take a `ReactNode`, not just icons/strings: `startElement` / `endElement` render inside the field (an icon, badge, text, or an interactive control like a reveal/clear button), and `startAddon` / `endAddon` render as a bordered, attached box outside the field (a text label like `$` / `USD`, or a component such as a `select` / button). These match the Figma slot names. The validation status icon (error/warning) is added automatically and sits left of `endElement`. For a component addon that brings its own styling, pass `startAddonProps={{ unstyled: true }}` (or `endAddonProps`) to drop the default grey box:
|
|
132
133
|
```tsx
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { Menu, MenuItemGroupProps, MenuItemProps, MenuRootProps, MenuSeparatorProps } from '@chakra-ui/react/menu';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { BitkitIconComponent } from '../../icons';
|
|
4
|
-
|
|
4
|
+
import { BitkitDataAttributes } from '../../utilities/dataAttributes';
|
|
5
|
+
/**
|
|
6
|
+
* `data-*` attributes are forwarded to the element carrying `role="menu"` (the menu content), and
|
|
7
|
+
* nothing else is — the same contract the dialogs have. The menu portals out, so this is the only
|
|
8
|
+
* way to address the rendered list, e.g. from a test.
|
|
9
|
+
*/
|
|
10
|
+
export interface BitkitActionMenuProps extends Omit<MenuRootProps, 'children'>, BitkitDataAttributes {
|
|
5
11
|
/** The menu's items — `BitkitActionMenu.Item`, `.Group` and `.Separator`. */
|
|
6
12
|
children?: ReactNode;
|
|
7
13
|
/**
|
|
@@ -15,7 +21,7 @@ export interface BitkitActionMenuProps extends Omit<MenuRootProps, 'children'> {
|
|
|
15
21
|
*/
|
|
16
22
|
trigger: ReactNode;
|
|
17
23
|
}
|
|
18
|
-
interface BitkitActionMenuItemCommonProps extends MenuItemProps {
|
|
24
|
+
interface BitkitActionMenuItemCommonProps extends Omit<MenuItemProps, 'value'> {
|
|
19
25
|
/** The item's label. */
|
|
20
26
|
children?: ReactNode;
|
|
21
27
|
/** Leading icon, sized from the menu's `size` (24 on `lg`, 16 on `md`). */
|
|
@@ -24,6 +30,12 @@ interface BitkitActionMenuItemCommonProps extends MenuItemProps {
|
|
|
24
30
|
isDanger?: boolean;
|
|
25
31
|
/** A second, quieter line under the label. Adding it makes the row taller and top-aligns the icon. */
|
|
26
32
|
secondaryText?: ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Identifies the item to the menu machine. Omit it for a command item that does its own work in
|
|
35
|
+
* `onClick` — a generated id is used, and typeahead matches the label either way. Pass one when
|
|
36
|
+
* you read `onSelect` on the menu itself and need to tell the items apart.
|
|
37
|
+
*/
|
|
38
|
+
value?: string;
|
|
27
39
|
}
|
|
28
40
|
interface BitkitActionMenuItemAsButtonProps extends BitkitActionMenuItemCommonProps {
|
|
29
41
|
href?: undefined;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { withSubComponents } from "../../utilities/withSubComponents.js";
|
|
2
2
|
import IconArrowNortheast from "../../icons/IconArrowNortheast.js";
|
|
3
|
+
import { splitDataAttributes } from "../../utilities/dataAttributes.js";
|
|
3
4
|
import { Box } from "@chakra-ui/react/box";
|
|
4
|
-
import { createContext, forwardRef, useContext } from "react";
|
|
5
|
+
import { createContext, forwardRef, useContext, useId } from "react";
|
|
5
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { Portal } from "@chakra-ui/react/portal";
|
|
7
8
|
import { Menu, useMenuStyles } from "@chakra-ui/react/menu";
|
|
@@ -10,15 +11,19 @@ import { Text } from "@chakra-ui/react/text";
|
|
|
10
11
|
//#region lib/components/BitkitActionMenu/BitkitActionMenu.tsx
|
|
11
12
|
var BitkitActionMenuContext = createContext("lg");
|
|
12
13
|
var BitkitActionMenu = ({ trigger, children, size = "lg", ...props }) => {
|
|
14
|
+
const { dataAttributes, rest: rootProps } = splitDataAttributes(props);
|
|
13
15
|
return /* @__PURE__ */ jsxs(Menu.Root, {
|
|
14
16
|
size,
|
|
15
|
-
...
|
|
17
|
+
...rootProps,
|
|
16
18
|
children: [/* @__PURE__ */ jsx(Menu.Trigger, {
|
|
17
19
|
asChild: true,
|
|
18
20
|
children: trigger
|
|
19
21
|
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsx(BitkitActionMenuContext.Provider, {
|
|
20
22
|
value: size,
|
|
21
|
-
children: /* @__PURE__ */ jsx(Menu.Content, {
|
|
23
|
+
children: /* @__PURE__ */ jsx(Menu.Content, {
|
|
24
|
+
...dataAttributes,
|
|
25
|
+
children
|
|
26
|
+
})
|
|
22
27
|
}) }) })]
|
|
23
28
|
});
|
|
24
29
|
};
|
|
@@ -28,6 +33,7 @@ var BitkitActionMenuItem = forwardRef((props, ref) => {
|
|
|
28
33
|
const style = useMenuStyles();
|
|
29
34
|
const iconSize = useContext(BitkitActionMenuContext) === "lg" ? "24" : "16";
|
|
30
35
|
const hasHelper = secondaryText ? true : void 0;
|
|
36
|
+
const fallbackValue = useId();
|
|
31
37
|
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
32
38
|
Icon && /* @__PURE__ */ jsx(Icon, { size: iconSize }),
|
|
33
39
|
/* @__PURE__ */ jsxs(Box, {
|
|
@@ -43,13 +49,14 @@ var BitkitActionMenuItem = forwardRef((props, ref) => {
|
|
|
43
49
|
})
|
|
44
50
|
] });
|
|
45
51
|
if (props.href !== void 0) {
|
|
46
|
-
const { children: _children, href, icon: _icon, isDanger: _isDanger, isExternal, rel, secondaryText: _secondaryText, target, ...rest } = props;
|
|
52
|
+
const { children: _children, href, icon: _icon, isDanger: _isDanger, isExternal, rel, secondaryText: _secondaryText, target, value, ...rest } = props;
|
|
47
53
|
const effectiveTarget = isExternal ? "_blank" : target;
|
|
48
54
|
const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
|
|
49
55
|
return /* @__PURE__ */ jsx(Menu.Item, {
|
|
50
56
|
asChild: true,
|
|
51
57
|
"data-danger": isDanger,
|
|
52
58
|
"data-helper": hasHelper,
|
|
59
|
+
value: value ?? fallbackValue,
|
|
53
60
|
...rest,
|
|
54
61
|
children: /* @__PURE__ */ jsx("a", {
|
|
55
62
|
ref,
|
|
@@ -60,11 +67,12 @@ var BitkitActionMenuItem = forwardRef((props, ref) => {
|
|
|
60
67
|
})
|
|
61
68
|
});
|
|
62
69
|
}
|
|
63
|
-
const { children: _children, icon: _icon, isDanger: _isDanger, secondaryText: _secondaryText, ...rest } = props;
|
|
70
|
+
const { children: _children, icon: _icon, isDanger: _isDanger, secondaryText: _secondaryText, value, ...rest } = props;
|
|
64
71
|
return /* @__PURE__ */ jsx(Menu.Item, {
|
|
65
72
|
"data-danger": isDanger,
|
|
66
73
|
"data-helper": hasHelper,
|
|
67
74
|
ref,
|
|
75
|
+
value: value ?? fallbackValue,
|
|
68
76
|
...rest,
|
|
69
77
|
children: content
|
|
70
78
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitActionMenu.js","names":[],"sources":["../../../lib/components/BitkitActionMenu/BitkitActionMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport {\n Menu,\n type MenuItemGroupProps,\n type MenuItemProps,\n type MenuRootProps,\n type MenuSeparatorProps,\n useMenuStyles,\n} from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator as ChakraSeparator } from '@chakra-ui/react/separator';\nimport { Text } from '@chakra-ui/react/text';\nimport { createContext, forwardRef, type ReactNode, type Ref, useContext } from 'react';\n\nimport { type BitkitIconComponent, IconArrowNortheast } from '../../icons';\nimport { withSubComponents } from '../../utilities/withSubComponents';\n\nconst BitkitActionMenuContext = createContext<MenuRootProps['size']>('lg');\n\nexport interface BitkitActionMenuProps extends Omit<MenuRootProps, 'children'
|
|
1
|
+
{"version":3,"file":"BitkitActionMenu.js","names":[],"sources":["../../../lib/components/BitkitActionMenu/BitkitActionMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport {\n Menu,\n type MenuItemGroupProps,\n type MenuItemProps,\n type MenuRootProps,\n type MenuSeparatorProps,\n useMenuStyles,\n} from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator as ChakraSeparator } from '@chakra-ui/react/separator';\nimport { Text } from '@chakra-ui/react/text';\nimport { createContext, forwardRef, type ReactNode, type Ref, useContext, useId } from 'react';\n\nimport { type BitkitIconComponent, IconArrowNortheast } from '../../icons';\nimport { type BitkitDataAttributes, splitDataAttributes } from '../../utilities/dataAttributes';\nimport { withSubComponents } from '../../utilities/withSubComponents';\n\nconst BitkitActionMenuContext = createContext<MenuRootProps['size']>('lg');\n\n/**\n * `data-*` attributes are forwarded to the element carrying `role=\"menu\"` (the menu content), and\n * nothing else is — the same contract the dialogs have. The menu portals out, so this is the only\n * way to address the rendered list, e.g. from a test.\n */\nexport interface BitkitActionMenuProps extends Omit<MenuRootProps, 'children'>, BitkitDataAttributes {\n /** The menu's items — `BitkitActionMenu.Item`, `.Group` and `.Separator`. */\n children?: ReactNode;\n /**\n * Row density, inherited by every item. `lg` (default) is the standalone action menu; `md` is for\n * menus attached to dense UI, such as an overflow menu in a toolbar or a tab bar.\n */\n size?: MenuRootProps['size'];\n /**\n * The element the menu is anchored to — usually a `BitkitIconButton` or `BitkitButton`. Rendered\n * via `asChild`, so it must accept a ref.\n */\n trigger: ReactNode;\n}\n\nconst BitkitActionMenu = ({ trigger, children, size = 'lg', ...props }: BitkitActionMenuProps) => {\n // `Menu.Root` is a provider, not an element, so it drops the `data-*` attributes — they belong on\n // the content, which is the element carrying `role=\"menu\"`.\n const { dataAttributes, rest: rootProps } = splitDataAttributes(props);\n\n return (\n <Menu.Root size={size} {...rootProps}>\n <Menu.Trigger asChild>{trigger}</Menu.Trigger>\n <Portal>\n <Menu.Positioner>\n <BitkitActionMenuContext.Provider value={size}>\n <Menu.Content {...dataAttributes}>{children}</Menu.Content>\n </BitkitActionMenuContext.Provider>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n );\n};\nBitkitActionMenu.displayName = 'BitkitActionMenu';\n\ninterface BitkitActionMenuItemCommonProps extends Omit<MenuItemProps, 'value'> {\n /** The item's label. */\n children?: ReactNode;\n /** Leading icon, sized from the menu's `size` (24 on `lg`, 16 on `md`). */\n icon?: BitkitIconComponent;\n /** Style the item as destructive — red label and icon. Use it for delete and similar actions. */\n isDanger?: boolean;\n /** A second, quieter line under the label. Adding it makes the row taller and top-aligns the icon. */\n secondaryText?: ReactNode;\n /**\n * Identifies the item to the menu machine. Omit it for a command item that does its own work in\n * `onClick` — a generated id is used, and typeahead matches the label either way. Pass one when\n * you read `onSelect` on the menu itself and need to tell the items apart.\n */\n value?: string;\n}\n\ninterface BitkitActionMenuItemAsButtonProps extends BitkitActionMenuItemCommonProps {\n href?: undefined;\n isExternal?: undefined;\n rel?: undefined;\n target?: undefined;\n}\n\ninterface BitkitActionMenuItemAsAnchorProps extends BitkitActionMenuItemCommonProps {\n /** Renders the item as an `<a>` instead of a menu button. */\n href: string;\n /**\n * Shorthand for `target=\"_blank\"` plus `rel=\"noreferrer noopener\"`. Also puts an\n * `IconArrowNortheast` at the end of the row — the design system's \"leaves this page\" marker.\n */\n isExternal?: boolean;\n /** Extra `rel` tokens. With `isExternal` the safety tokens are appended to these. */\n rel?: string;\n /** Anchor target. Ignored when `isExternal` is set. */\n target?: string;\n}\n\nexport type BitkitActionMenuItemProps = BitkitActionMenuItemAsButtonProps | BitkitActionMenuItemAsAnchorProps;\n\nconst BitkitActionMenuItem = forwardRef<HTMLElement, BitkitActionMenuItemProps>((props, ref) => {\n const { children, icon: Icon, isDanger, secondaryText } = props;\n const style = useMenuStyles();\n const menuCtx = useContext(BitkitActionMenuContext);\n const iconSize = menuCtx === 'lg' ? '24' : '16';\n const hasHelper = secondaryText ? true : undefined;\n const fallbackValue = useId();\n\n const content = (\n <>\n {Icon && <Icon size={iconSize} />}\n <Box flex=\"1\">\n <Text>{children}</Text>\n {secondaryText && <Text css={style.itemHelper}>{secondaryText}</Text>}\n </Box>\n {props.isExternal && <IconArrowNortheast data-suffix-icon size={iconSize} />}\n </>\n );\n\n if (props.href !== undefined) {\n const {\n children: _children,\n href,\n icon: _icon,\n isDanger: _isDanger,\n isExternal,\n rel,\n secondaryText: _secondaryText,\n target,\n value,\n ...rest\n } = props;\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n return (\n <Menu.Item asChild data-danger={isDanger} data-helper={hasHelper} value={value ?? fallbackValue} {...rest}>\n <a ref={ref as Ref<HTMLAnchorElement>} href={href} rel={effectiveRel} target={effectiveTarget}>\n {content}\n </a>\n </Menu.Item>\n );\n }\n\n const {\n children: _children,\n icon: _icon,\n isDanger: _isDanger,\n secondaryText: _secondaryText,\n value,\n ...rest\n } = props;\n return (\n <Menu.Item\n data-danger={isDanger}\n data-helper={hasHelper}\n ref={ref as Ref<HTMLDivElement>}\n value={value ?? fallbackValue}\n {...rest}\n >\n {content}\n </Menu.Item>\n );\n});\nBitkitActionMenuItem.displayName = 'BitkitActionMenu.Item';\n\nexport interface BitkitActionMenuGroupProps extends MenuItemGroupProps {\n /** The group's items. */\n children?: ReactNode;\n /** The group's heading, rendered uppercase with a rule filling the rest of the row. */\n label: ReactNode;\n}\n\nconst BitkitActionMenuGroup = forwardRef<HTMLDivElement, BitkitActionMenuGroupProps>(\n ({ label, children, ...props }, ref) => {\n return (\n <Menu.ItemGroup ref={ref} {...props}>\n <Menu.ItemGroupLabel>\n <Text>{label}</Text>\n <ChakraSeparator flex=\"1\" />\n </Menu.ItemGroupLabel>\n {children}\n </Menu.ItemGroup>\n );\n },\n);\nBitkitActionMenuGroup.displayName = 'BitkitActionMenu.Group';\n\nexport type BitkitActionMenuSeparatorProps = MenuSeparatorProps;\n\nconst BitkitActionMenuSeparator = forwardRef<HTMLHRElement, BitkitActionMenuSeparatorProps>((props, ref) => {\n return <Menu.Separator ref={ref} {...props} />;\n});\nBitkitActionMenuSeparator.displayName = 'BitkitActionMenu.Separator';\n\nexport default withSubComponents(BitkitActionMenu, {\n Group: BitkitActionMenuGroup,\n Item: BitkitActionMenuItem,\n Separator: BitkitActionMenuSeparator,\n});\n"],"mappings":";;;;;;;;;;;AAkBA,IAAM,0BAA0B,cAAqC,IAAI;AAsBzE,IAAM,oBAAoB,EAAE,SAAS,UAAU,OAAO,MAAM,GAAG,YAAmC;CAGhG,MAAM,EAAE,gBAAgB,MAAM,cAAc,oBAAoB,KAAK;CAErE,OACE,qBAAC,KAAK,MAAN;EAAiB;EAAM,GAAI;EAA3B,UAAA,CACE,oBAAC,KAAK,SAAN;GAAc,SAAA;GAAS,UAAA;EAAsB,CAAA,GAC7C,oBAAC,QAAD,EAAA,UACE,oBAAC,KAAK,YAAN,EAAA,UACE,oBAAC,wBAAwB,UAAzB;GAAkC,OAAO;GACvC,UAAA,oBAAC,KAAK,SAAN;IAAc,GAAI;IAAiB;GAAuB,CAAA;EAC1B,CAAA,EACnB,CAAA,EACX,CAAA,CACC;;AAEf;AACA,iBAAiB,cAAc;AA0C/B,IAAM,uBAAuB,YAAoD,OAAO,QAAQ;CAC9F,MAAM,EAAE,UAAU,MAAM,MAAM,UAAU,kBAAkB;CAC1D,MAAM,QAAQ,cAAc;CAE5B,MAAM,WADU,WAAW,uBACV,MAAY,OAAO,OAAO;CAC3C,MAAM,YAAY,gBAAgB,OAAO,KAAA;CACzC,MAAM,gBAAgB,MAAM;CAE5B,MAAM,UACJ,qBAAA,YAAA,EAAA,UAAA;EACG,QAAQ,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;EAChC,qBAAC,KAAD;GAAK,MAAK;GAAV,UAAA,CACE,oBAAC,MAAD,EAAO,SAAe,CAAA,GACrB,iBAAiB,oBAAC,MAAD;IAAM,KAAK,MAAM;IAAa,UAAA;GAAoB,CAAA,CACjE;;EACJ,MAAM,cAAc,oBAAC,oBAAD;GAAoB,oBAAA;GAAiB,MAAM;EAAW,CAAA;CAC3E,EAAA,CAAA;CAGJ,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,EACJ,UAAU,WACV,MACA,MAAM,OACN,UAAU,WACV,YACA,KACA,eAAe,gBACf,QACA,OACA,GAAG,SACD;EACJ,MAAM,kBAAkB,aAAa,WAAW;EAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;EACjG,OACE,oBAAC,KAAK,MAAN;GAAW,SAAA;GAAQ,eAAa;GAAU,eAAa;GAAW,OAAO,SAAS;GAAe,GAAI;GACnG,UAAA,oBAAC,KAAD;IAAQ;IAAqC;IAAM,KAAK;IAAc,QAAQ;IAC3E,UAAA;GACA,CAAA;EACM,CAAA;CAEf;CAEA,MAAM,EACJ,UAAU,WACV,MAAM,OACN,UAAU,WACV,eAAe,gBACf,OACA,GAAG,SACD;CACJ,OACE,oBAAC,KAAK,MAAN;EACE,eAAa;EACb,eAAa;EACR;EACL,OAAO,SAAS;EAChB,GAAI;EAEH,UAAA;CACQ,CAAA;AAEf,CAAC;AACD,qBAAqB,cAAc;AASnC,IAAM,wBAAwB,YAC3B,EAAE,OAAO,UAAU,GAAG,SAAS,QAAQ;CACtC,OACE,qBAAC,KAAK,WAAN;EAAqB;EAAK,GAAI;EAA9B,UAAA,CACE,qBAAC,KAAK,gBAAN,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UAAO,MAAY,CAAA,GACnB,oBAAC,WAAD,EAAiB,MAAK,IAAK,CAAA,CACR,EAAA,CAAA,GACpB,QACa;;AAEpB,CACF;AACA,sBAAsB,cAAc;AAIpC,IAAM,4BAA4B,YAA2D,OAAO,QAAQ;CAC1G,OAAO,oBAAC,KAAK,WAAN;EAAqB;EAAK,GAAI;CAAQ,CAAA;AAC/C,CAAC;AACD,0BAA0B,cAAc;AAExC,IAAA,2BAAe,kBAAkB,kBAAkB;CACjD,OAAO;CACP,MAAM;CACN,WAAW;AACb,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { BitkitDataAttributes } from '../../utilities/dataAttributes';
|
|
4
|
+
import { DialogShellProps } from './DialogShell';
|
|
4
5
|
export type BitkitDialogProps = {
|
|
5
6
|
children?: ReactNode;
|
|
6
7
|
closable?: boolean;
|
|
@@ -22,7 +23,7 @@ export type BitkitDialogProps = {
|
|
|
22
23
|
title: ReactNode;
|
|
23
24
|
trigger?: ReactNode;
|
|
24
25
|
variant?: 'overflowContent';
|
|
25
|
-
} &
|
|
26
|
+
} & BitkitDataAttributes;
|
|
26
27
|
declare const _default: {
|
|
27
28
|
({ children, closable, footerButtons, footerContent, headerLabel, initialFocusEl, maxHeight, onExitComplete, onOpenChange, open, preventScroll, scrollBehavior, showScrollGradient, size, title, trigger, variant, ...dataAttributes }: BitkitDialogProps): import("react").JSX.Element;
|
|
28
29
|
displayName: string;
|
|
@@ -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, { type
|
|
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 { type BitkitDataAttributes } from '../../utilities/dataAttributes';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport DialogInner from './DialogInner';\nimport DialogShell, { type DialogShellProps } from './DialogShell';\n\nexport type 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 // Data attributes are forwarded to the element carrying `role=\"dialog\"`, and nothing else is —\n // style props, `className` and `id` don't pass through.\n} & BitkitDataAttributes;\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 ...dataAttributes\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} {...dataAttributes}>\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":";;;;;;AA+BA,IAAM,gBAAgB,EACpB,UACA,WAAW,MACX,eACA,eACA,aACA,gBACA,WACA,gBACA,cACA,MACA,eACA,gBACA,oBACA,MACA,OACA,SACA,SACA,GAAG,qBAEH,oBAAC,aAAD;CACY;CACM;CACA;CACF;CACR;CACS;CACC;CACV;CACG;CACA;CAET,UAAA,oBAAC,OAAO,SAAR;EAA2B;EAAW,GAAI;EACxC,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"}
|
|
@@ -26,7 +26,7 @@ declare const _default: import('react').ForwardRefExoticComponent<{
|
|
|
26
26
|
title: import('react').ReactNode;
|
|
27
27
|
trigger?: import('react').ReactNode;
|
|
28
28
|
variant?: "overflowContent";
|
|
29
|
-
} & import('
|
|
29
|
+
} & import('../../utilities/dataAttributes').BitkitDataAttributes & {
|
|
30
30
|
/** Skips the browser's native constraint validation on submit. */
|
|
31
31
|
noValidate?: boolean;
|
|
32
32
|
onSubmit?: FormEventHandler<HTMLFormElement>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
import { BitkitDataAttributes } from '../../utilities/dataAttributes';
|
|
3
4
|
import { BitkitStepperDialogStepProps } from './BitkitStepperDialogStep';
|
|
4
|
-
import {
|
|
5
|
+
import { DialogShellProps } from './DialogShell';
|
|
5
6
|
export { useStepperDialog } from './StepperContext';
|
|
6
7
|
export type BitkitStepperDialogProps = {
|
|
7
8
|
/** `BitkitStepperDialog.Step` children, one per step. */
|
|
@@ -35,7 +36,7 @@ export type BitkitStepperDialogProps = {
|
|
|
35
36
|
title: ReactNode;
|
|
36
37
|
trigger?: ReactNode;
|
|
37
38
|
variant?: 'overflowContent';
|
|
38
|
-
} &
|
|
39
|
+
} & BitkitDataAttributes;
|
|
39
40
|
declare const _default: {
|
|
40
41
|
({ children, closable, defaultStep, initialFocusEl, footerContent, headerLabel, maxHeight, onExitComplete, onOpenChange, onStepChange, open, preventScroll, scrollBehavior, showScrollGradient, size, step: stepProp, title, trigger, variant, ...dataAttributes }: BitkitStepperDialogProps): import("react").JSX.Element;
|
|
41
42
|
displayName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitStepperDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitStepperDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { type ReactElement, type ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { flattenChildren } from '../../utilities/flattenChildren';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitSteps from '../BitkitSteps/BitkitSteps';\nimport BitkitStepperDialogStep, { type BitkitStepperDialogStepProps } from './BitkitStepperDialogStep';\nimport DialogInner from './DialogInner';\nimport DialogShell, { type
|
|
1
|
+
{"version":3,"file":"BitkitStepperDialog.js","names":[],"sources":["../../../lib/components/BitkitDialog/BitkitStepperDialog.tsx"],"sourcesContent":["import { Dialog } from '@chakra-ui/react/dialog';\nimport { type ReactElement, type ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { type BitkitDataAttributes } from '../../utilities/dataAttributes';\nimport { flattenChildren } from '../../utilities/flattenChildren';\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 type 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 // Data attributes are forwarded to the element carrying `role=\"dialog\"`, and nothing else is —\n // style props, `className` and `id` don't pass through.\n} & BitkitDataAttributes;\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 ...dataAttributes\n}: BitkitStepperDialogProps) => {\n const [internalStep, setInternalStep] = useState(defaultStep);\n const isControlled = stepProp !== undefined;\n const rawStep = (isControlled ? stepProp : internalStep) ?? 0;\n const steps = flattenChildren(children).filter(\n (child): child is ReactElement<BitkitStepperDialogStepProps> => 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} {...dataAttributes}>\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":";;;;;;;;;;;;;;;;AAqDA,IAAM,uBAAuB,EAC3B,UACA,WAAW,MACX,cAAc,GACd,gBACA,eACA,aACA,WACA,gBACA,cACA,cACA,MACA,eACA,gBACA,oBACA,MACA,MAAM,UACN,OACA,SACA,SACA,GAAG,qBAC2B;CAC9B,MAAM,CAAC,cAAc,mBAAmB,SAAS,WAAW;CAC5D,MAAM,eAAe,aAAa,KAAA;CAClC,MAAM,WAAW,eAAe,WAAW,iBAAiB;CAC5D,MAAM,QAAQ,gBAAgB,QAAQ,CAAC,CAAC,QACrC,UAA+D,MAAM,SAAS,uBACjF;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;IAAW,GAAI;IACxC,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,13 +1,5 @@
|
|
|
1
1
|
import { Dialog } from '@chakra-ui/react/dialog';
|
|
2
2
|
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
-
/**
|
|
4
|
-
* Data attributes every dialog flavour forwards to its content element — the one carrying
|
|
5
|
-
* `role="dialog"`. The case this exists for is `data-clarity-unmask`, which opts a region out of
|
|
6
|
-
* session replay masking, exactly where support needs to read it.
|
|
7
|
-
*/
|
|
8
|
-
export interface DialogDataAttributes {
|
|
9
|
-
[dataAttribute: `data-${string}`]: string | undefined;
|
|
10
|
-
}
|
|
11
3
|
export interface DialogShellProps {
|
|
12
4
|
/** The `Dialog.Content` element (rendered inside the positioner). */
|
|
13
5
|
children: ReactNode;
|
|
@@ -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 ComponentProps, type ReactNode } from 'react';\n\nimport { resolveScrollBehavior } from './DialogBodyContext';\n\
|
|
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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { NotificationVariant } from '../../theme/common/AlertAndToast.common';
|
|
3
|
+
import { BitkitDataAttributes } from '../../utilities/dataAttributes';
|
|
3
4
|
import { NotificationAction } from '../common/notificationMaps';
|
|
4
5
|
export type BitkitToastVariant = NotificationVariant;
|
|
5
6
|
export type BitkitToastProps = {
|
|
@@ -15,18 +16,7 @@ export type BitkitToastProps = {
|
|
|
15
16
|
timestamp?: string;
|
|
16
17
|
titleText?: ReactNode;
|
|
17
18
|
variant: BitkitToastVariant;
|
|
18
|
-
} &
|
|
19
|
-
/**
|
|
20
|
-
* Data attributes are forwarded to the toast's root element. `createBitkitToast` is a
|
|
21
|
-
* function rather than a component, so props can't be spread onto anything directly —
|
|
22
|
-
* these travel through the toast store's `meta` and are applied when it renders.
|
|
23
|
-
*
|
|
24
|
-
* The case this exists for is `data-clarity-unmask`, which opts a region out of session
|
|
25
|
-
* replay masking: without it a migrated error toast shows up as blocks in the replay,
|
|
26
|
-
* exactly where support needs to read what went wrong.
|
|
27
|
-
*/
|
|
28
|
-
[dataAttribute: `data-${string}`]: string | undefined;
|
|
29
|
-
};
|
|
19
|
+
} & BitkitDataAttributes;
|
|
30
20
|
export declare const toaster: import('@chakra-ui/react').CreateToasterReturn<ReactNode>;
|
|
31
21
|
declare const createBitkitToast: (props: BitkitToastProps) => string;
|
|
32
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitToast.js","names":[],"sources":["../../../lib/components/BitkitToast/BitkitToast.tsx"],"sourcesContent":["import { createToaster } from '@chakra-ui/react/toast';\nimport { type ReactNode } from 'react';\n\nimport { type NotificationVariant } from '../../theme/common/AlertAndToast.common';\nimport { type NotificationAction } from '../common/notificationMaps';\n\nexport type BitkitToastVariant = NotificationVariant;\n\nexport type BitkitToastProps = {\n action?: NotificationAction;\n dismissible?: boolean;\n /**\n * How long the toast stays visible, in milliseconds. Overrides the per-variant\n * default for any variant: 5000ms for `ai`/`info`/`success`/`warning`, `Infinity`\n * for `critical` and `progress`. Pass `Infinity` to make a toast persist.\n */\n duration?: number;\n messageText: ReactNode;\n timestamp?: string;\n titleText?: ReactNode;\n variant: BitkitToastVariant;\n
|
|
1
|
+
{"version":3,"file":"BitkitToast.js","names":[],"sources":["../../../lib/components/BitkitToast/BitkitToast.tsx"],"sourcesContent":["import { createToaster } from '@chakra-ui/react/toast';\nimport { type ReactNode } from 'react';\n\nimport { type NotificationVariant } from '../../theme/common/AlertAndToast.common';\nimport { type BitkitDataAttributes } from '../../utilities/dataAttributes';\nimport { type NotificationAction } from '../common/notificationMaps';\n\nexport type BitkitToastVariant = NotificationVariant;\n\nexport type BitkitToastProps = {\n action?: NotificationAction;\n dismissible?: boolean;\n /**\n * How long the toast stays visible, in milliseconds. Overrides the per-variant\n * default for any variant: 5000ms for `ai`/`info`/`success`/`warning`, `Infinity`\n * for `critical` and `progress`. Pass `Infinity` to make a toast persist.\n */\n duration?: number;\n messageText: ReactNode;\n timestamp?: string;\n titleText?: ReactNode;\n variant: BitkitToastVariant;\n // Data attributes are forwarded to the toast's root element. `createBitkitToast` is a function\n // rather than a component, so props can't be spread onto anything directly — these travel\n // through the toast store's `meta` and are applied when it renders. The case it exists for is\n // `data-clarity-unmask`: without it a migrated error toast shows up as blocks in session replay,\n // exactly where support needs to read what went wrong.\n} & BitkitDataAttributes;\n\n// Zag's internal priority table only knows its 5 built-in types and crashes\n// on our custom variants (ai/critical/progress). We replicate Zag's algorithm\n// with our full variant set and compute priority ourselves, so the broken\n// lookup is never reached. Each tuple is [actionable, nonActionable] — mirrors\n// Zag, which ranks actionable toasts higher. Lower number = higher in the stack.\nconst TOAST_PRIORITIES = {\n critical: [1, 2], // ~ Zag \"error\" — most urgent\n warning: [3, 6], // = Zag \"warning\"\n progress: [4, 5], // ~ Zag \"loading\"\n success: [5, 7], // = Zag \"success\"\n ai: [6, 8], // ~ Zag \"info\"\n info: [6, 8], // = Zag \"info\" — least urgent\n} as const satisfies Record<BitkitToastVariant, readonly [number, number]>;\n\n// Same name-collision problem as the priorities above: Zag keys its timeout table\n// by its own type names, so only info/warning/success happen to match ours and the\n// rest silently fall back to its 5000ms DEFAULT. We own the full table instead.\n// `critical` and `progress` persist until dismissed — an error the user must see,\n// and an operation that is still running, should not disappear on a timer.\nconst TOAST_DURATIONS = {\n ai: 5000,\n critical: Infinity,\n info: 5000,\n progress: Infinity,\n success: 5000,\n warning: 5000,\n} as const satisfies Record<BitkitToastVariant, number>;\n\nexport const toaster = createToaster({\n max: 5,\n placement: 'top-end',\n pauseOnPageIdle: true,\n});\n\nconst createBitkitToast = (props: BitkitToastProps) => {\n const { action, dismissible = true, duration, messageText, timestamp, titleText, variant, ...dataAttributes } = props;\n\n const [actionable, nonActionable] = TOAST_PRIORITIES[variant];\n\n return toaster.create({\n closable: dismissible,\n description: messageText,\n duration: duration ?? TOAST_DURATIONS[variant],\n meta: { action, dataAttributes, timestamp },\n priority: action ? actionable : nonActionable,\n title: titleText,\n type: variant,\n });\n};\n\n/**\n * Closes the toast with the given id — the one `createBitkitToast` returns — or every\n * visible toast when called without an id — note that an `undefined` id counts as \"no id\",\n * so guard ids that may not be set yet. Use it to close `duration: Infinity` toasts\n * (`critical`, `progress`) from code once the operation they report on ends, and to clean\n * up toasts between tests. The node is unmounted 200ms after the call — Zag's fixed\n * `removeDelay`, which cuts the exit transition short rather than waiting it out — so in\n * tests, assert its absence with `waitFor` or advance the timers.\n */\nexport const dismissBitkitToast = (id?: string) => toaster.dismiss(id);\n\nexport default createBitkitToast;\n"],"mappings":";;AAkCA,IAAM,mBAAmB;CACvB,UAAU,CAAC,GAAG,CAAC;CACf,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,GAAG,CAAC;CACf,SAAS,CAAC,GAAG,CAAC;CACd,IAAI,CAAC,GAAG,CAAC;CACT,MAAM,CAAC,GAAG,CAAC;AACb;AAOA,IAAM,kBAAkB;CACtB,IAAI;CACJ,UAAU;CACV,MAAM;CACN,UAAU;CACV,SAAS;CACT,SAAS;AACX;AAEA,IAAa,UAAU,cAAc;CACnC,KAAK;CACL,WAAW;CACX,iBAAiB;AACnB,CAAC;AAED,IAAM,qBAAqB,UAA4B;CACrD,MAAM,EAAE,QAAQ,cAAc,MAAM,UAAU,aAAa,WAAW,WAAW,SAAS,GAAG,mBAAmB;CAEhH,MAAM,CAAC,YAAY,iBAAiB,iBAAiB;CAErD,OAAO,QAAQ,OAAO;EACpB,UAAU;EACV,aAAa;EACb,UAAU,YAAY,gBAAgB;EACtC,MAAM;GAAE;GAAQ;GAAgB;EAAU;EAC1C,UAAU,SAAS,aAAa;EAChC,OAAO;EACP,MAAM;CACR,CAAC;AACH;;;;;;;;;;AAWA,IAAa,sBAAsB,OAAgB,QAAQ,QAAQ,EAAE"}
|
|
@@ -46,6 +46,8 @@ var menuSlotRecipe = defineSlotRecipe({
|
|
|
46
46
|
boxShadow: "elevation/lg",
|
|
47
47
|
background: "background/primary",
|
|
48
48
|
maxHeight: "var(--available-height)",
|
|
49
|
+
overflow: "hidden",
|
|
50
|
+
overflowY: "auto",
|
|
49
51
|
_open: {
|
|
50
52
|
animationStyle: "slide-fade-in",
|
|
51
53
|
animationDuration: "fast"
|
|
@@ -91,6 +93,7 @@ var menuSlotRecipe = defineSlotRecipe({
|
|
|
91
93
|
"& [data-suffix-icon]": { color: "icon/tertiary" }
|
|
92
94
|
},
|
|
93
95
|
itemGroupLabel: {
|
|
96
|
+
"& .separator": { borderColor: "border/minimal" },
|
|
94
97
|
textStyle: "heading/h6",
|
|
95
98
|
color: "text/tertiary",
|
|
96
99
|
paddingTop: "12",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/Menu.recipe.ts"],"sourcesContent":["import { menuAnatomy } from '@chakra-ui/react/anatomy';\nimport { defineSlotRecipe, type SystemStyleObject } from '@chakra-ui/react/styled-system';\n\nconst itemActive: SystemStyleObject = {\n background: 'button/secondary/bg-active',\n _icon: {\n color: 'icon/primary',\n },\n};\nconst itemActiveDanger: SystemStyleObject = {\n background: 'button/danger-secondary/bg-active',\n color: 'button/danger-secondary/fg-active',\n _icon: {\n color: 'button/danger-secondary/fg-active',\n },\n};\nconst menuSlotRecipe = defineSlotRecipe({\n className: 'menu',\n slots: [...menuAnatomy.keys(), 'itemHelper'],\n variants: {\n size: {\n lg: {\n item: {\n alignItems: 'center',\n paddingY: '12',\n textStyle: 'body/lg/regular',\n // With a helper line the item aligns to the top of the label and gets tighter padding.\n '&[data-helper]': {\n alignItems: 'flex-start',\n paddingY: '8',\n },\n },\n },\n md: {\n item: {\n alignItems: 'center',\n // The label line (20px) alone is shorter than the designed 40px row.\n minHeight: '40',\n paddingY: '8',\n textStyle: 'body/md/regular',\n '&[data-helper]': {\n _icon: {\n // Optically center the 16px icon against the 20px label line.\n marginTop: '2',\n },\n alignItems: 'flex-start',\n paddingY: '6',\n },\n },\n },\n },\n },\n base: {\n content: {\n // Sit above the legacy v1 full-dialog/drawer layer (zIndex.fullDialog = 1200); the menu\n // portals out, so without this it renders behind a v1 FloatingDrawer. Matches the content-slot\n // z-index convention of the other floating recipes (Popover, Tooltip, Combobox/Select).\n zIndex: 'popover',\n borderRadius: '4',\n paddingY: '8',\n border: '1px solid',\n borderColor: 'border/minimal',\n _focusVisible: { outline: 'none' },\n boxShadow: 'elevation/lg',\n background: 'background/primary',\n maxHeight: 'var(--available-height)',\n _open: {\n animationStyle: 'slide-fade-in',\n animationDuration: 'fast',\n },\n _closed: {\n animationStyle: 'slide-fade-out',\n animationDuration: 'faster',\n },\n },\n itemHelper: {\n textStyle: 'body/sm/regular',\n color: 'text/secondary',\n },\n item: {\n _icon: {\n color: 'icon/secondary',\n _active: {\n color: 'icon/primary',\n },\n },\n cursor: 'pointer',\n display: 'flex',\n gap: '12',\n userSelect: 'none',\n flexDirection: 'row',\n paddingLeft: '16',\n paddingRight: '24',\n _disabled: {\n cursor: 'not-allowed',\n },\n '&[data-danger]': {\n color: 'button/danger-secondary/fg',\n _icon: {\n color: 'button/danger-secondary/fg',\n },\n _active: itemActiveDanger,\n _highlighted: {\n background: 'button/danger-secondary/bg-hover',\n color: 'button/danger-secondary/fg-hover',\n _active: itemActiveDanger,\n _icon: {\n color: 'button/danger-secondary/fg-hover',\n },\n },\n },\n _active: itemActive,\n _highlighted: {\n background: 'button/secondary/bg-hover',\n _active: itemActive,\n },\n // The \"leaves this page\" arrow is quieter than the leading icon, and stays that way in every\n // state — including the destructive one, which overrides `_icon` above.\n '& [data-suffix-icon]': {\n color: 'icon/tertiary',\n },\n },\n itemGroupLabel: {\n textStyle: 'heading/h6',\n color: 'text/tertiary',\n paddingTop: '12',\n paddingLeft: '16',\n paddingRight: '16',\n paddingBottom: '6',\n display: 'flex',\n gap: '8',\n flexDirection: 'row',\n alignItems: 'center',\n },\n separator: {\n color: 'border/minimal',\n marginY: '8',\n },\n },\n defaultVariants: {\n size: 'lg',\n },\n});\n\nexport default menuSlotRecipe;\n"],"mappings":";;;AAGA,IAAM,aAAgC;CACpC,YAAY;CACZ,OAAO,EACL,OAAO,eACT;AACF;AACA,IAAM,mBAAsC;CAC1C,YAAY;CACZ,OAAO;CACP,OAAO,EACL,OAAO,oCACT;AACF;AACA,IAAM,iBAAiB,iBAAiB;CACtC,WAAW;CACX,OAAO,CAAC,GAAG,YAAY,KAAK,GAAG,YAAY;CAC3C,UAAU,EACR,MAAM;EACJ,IAAI,EACF,MAAM;GACJ,YAAY;GACZ,UAAU;GACV,WAAW;GAEX,kBAAkB;IAChB,YAAY;IACZ,UAAU;GACZ;EACF,EACF;EACA,IAAI,EACF,MAAM;GACJ,YAAY;GAEZ,WAAW;GACX,UAAU;GACV,WAAW;GACX,kBAAkB;IAChB,OAAO,EAEL,WAAW,IACb;IACA,YAAY;IACZ,UAAU;GACZ;EACF,EACF;CACF,EACF;CACA,MAAM;EACJ,SAAS;GAIP,QAAQ;GACR,cAAc;GACd,UAAU;GACV,QAAQ;GACR,aAAa;GACb,eAAe,EAAE,SAAS,OAAO;GACjC,WAAW;GACX,YAAY;GACZ,WAAW;GACX,OAAO;IACL,gBAAgB;IAChB,mBAAmB;GACrB;GACA,SAAS;IACP,gBAAgB;IAChB,mBAAmB;GACrB;EACF;EACA,YAAY;GACV,WAAW;GACX,OAAO;EACT;EACA,MAAM;GACJ,OAAO;IACL,OAAO;IACP,SAAS,EACP,OAAO,eACT;GACF;GACA,QAAQ;GACR,SAAS;GACT,KAAK;GACL,YAAY;GACZ,eAAe;GACf,aAAa;GACb,cAAc;GACd,WAAW,EACT,QAAQ,cACV;GACA,kBAAkB;IAChB,OAAO;IACP,OAAO,EACL,OAAO,6BACT;IACA,SAAS;IACT,cAAc;KACZ,YAAY;KACZ,OAAO;KACP,SAAS;KACT,OAAO,EACL,OAAO,mCACT;IACF;GACF;GACA,SAAS;GACT,cAAc;IACZ,YAAY;IACZ,SAAS;GACX;GAGA,wBAAwB,EACtB,OAAO,gBACT;EACF;EACA,gBAAgB;
|
|
1
|
+
{"version":3,"file":"Menu.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/Menu.recipe.ts"],"sourcesContent":["import { menuAnatomy } from '@chakra-ui/react/anatomy';\nimport { defineSlotRecipe, type SystemStyleObject } from '@chakra-ui/react/styled-system';\n\nconst itemActive: SystemStyleObject = {\n background: 'button/secondary/bg-active',\n _icon: {\n color: 'icon/primary',\n },\n};\nconst itemActiveDanger: SystemStyleObject = {\n background: 'button/danger-secondary/bg-active',\n color: 'button/danger-secondary/fg-active',\n _icon: {\n color: 'button/danger-secondary/fg-active',\n },\n};\nconst menuSlotRecipe = defineSlotRecipe({\n className: 'menu',\n slots: [...menuAnatomy.keys(), 'itemHelper'],\n variants: {\n size: {\n lg: {\n item: {\n alignItems: 'center',\n paddingY: '12',\n textStyle: 'body/lg/regular',\n // With a helper line the item aligns to the top of the label and gets tighter padding.\n '&[data-helper]': {\n alignItems: 'flex-start',\n paddingY: '8',\n },\n },\n },\n md: {\n item: {\n alignItems: 'center',\n // The label line (20px) alone is shorter than the designed 40px row.\n minHeight: '40',\n paddingY: '8',\n textStyle: 'body/md/regular',\n '&[data-helper]': {\n _icon: {\n // Optically center the 16px icon against the 20px label line.\n marginTop: '2',\n },\n alignItems: 'flex-start',\n paddingY: '6',\n },\n },\n },\n },\n },\n base: {\n content: {\n // Sit above the legacy v1 full-dialog/drawer layer (zIndex.fullDialog = 1200); the menu\n // portals out, so without this it renders behind a v1 FloatingDrawer. Matches the content-slot\n // z-index convention of the other floating recipes (Popover, Tooltip, Combobox/Select).\n zIndex: 'popover',\n borderRadius: '4',\n paddingY: '8',\n border: '1px solid',\n borderColor: 'border/minimal',\n _focusVisible: { outline: 'none' },\n boxShadow: 'elevation/lg',\n background: 'background/primary',\n maxHeight: 'var(--available-height)',\n // The cap is useless without these: the positioner sets --available-height from the viewport,\n // and a longer list then spills out of the content box instead of scrolling inside it.\n overflow: 'hidden',\n overflowY: 'auto',\n _open: {\n animationStyle: 'slide-fade-in',\n animationDuration: 'fast',\n },\n _closed: {\n animationStyle: 'slide-fade-out',\n animationDuration: 'faster',\n },\n },\n itemHelper: {\n textStyle: 'body/sm/regular',\n color: 'text/secondary',\n },\n item: {\n _icon: {\n color: 'icon/secondary',\n _active: {\n color: 'icon/primary',\n },\n },\n cursor: 'pointer',\n display: 'flex',\n gap: '12',\n userSelect: 'none',\n flexDirection: 'row',\n paddingLeft: '16',\n paddingRight: '24',\n _disabled: {\n cursor: 'not-allowed',\n },\n '&[data-danger]': {\n color: 'button/danger-secondary/fg',\n _icon: {\n color: 'button/danger-secondary/fg',\n },\n _active: itemActiveDanger,\n _highlighted: {\n background: 'button/danger-secondary/bg-hover',\n color: 'button/danger-secondary/fg-hover',\n _active: itemActiveDanger,\n _icon: {\n color: 'button/danger-secondary/fg-hover',\n },\n },\n },\n _active: itemActive,\n _highlighted: {\n background: 'button/secondary/bg-hover',\n _active: itemActive,\n },\n // The \"leaves this page\" arrow is quieter than the leading icon, and stays that way in every\n // state — including the destructive one, which overrides `_icon` above.\n '& [data-suffix-icon]': {\n color: 'icon/tertiary',\n },\n },\n itemGroupLabel: {\n // The rule after the label is a Chakra Separator, whose recipe base is `border/regular` — a\n // shade darker than the menu's own separator. Match `BitkitActionMenu.Separator`.\n '& .separator': {\n borderColor: 'border/minimal',\n },\n textStyle: 'heading/h6',\n color: 'text/tertiary',\n paddingTop: '12',\n paddingLeft: '16',\n paddingRight: '16',\n paddingBottom: '6',\n display: 'flex',\n gap: '8',\n flexDirection: 'row',\n alignItems: 'center',\n },\n separator: {\n color: 'border/minimal',\n marginY: '8',\n },\n },\n defaultVariants: {\n size: 'lg',\n },\n});\n\nexport default menuSlotRecipe;\n"],"mappings":";;;AAGA,IAAM,aAAgC;CACpC,YAAY;CACZ,OAAO,EACL,OAAO,eACT;AACF;AACA,IAAM,mBAAsC;CAC1C,YAAY;CACZ,OAAO;CACP,OAAO,EACL,OAAO,oCACT;AACF;AACA,IAAM,iBAAiB,iBAAiB;CACtC,WAAW;CACX,OAAO,CAAC,GAAG,YAAY,KAAK,GAAG,YAAY;CAC3C,UAAU,EACR,MAAM;EACJ,IAAI,EACF,MAAM;GACJ,YAAY;GACZ,UAAU;GACV,WAAW;GAEX,kBAAkB;IAChB,YAAY;IACZ,UAAU;GACZ;EACF,EACF;EACA,IAAI,EACF,MAAM;GACJ,YAAY;GAEZ,WAAW;GACX,UAAU;GACV,WAAW;GACX,kBAAkB;IAChB,OAAO,EAEL,WAAW,IACb;IACA,YAAY;IACZ,UAAU;GACZ;EACF,EACF;CACF,EACF;CACA,MAAM;EACJ,SAAS;GAIP,QAAQ;GACR,cAAc;GACd,UAAU;GACV,QAAQ;GACR,aAAa;GACb,eAAe,EAAE,SAAS,OAAO;GACjC,WAAW;GACX,YAAY;GACZ,WAAW;GAGX,UAAU;GACV,WAAW;GACX,OAAO;IACL,gBAAgB;IAChB,mBAAmB;GACrB;GACA,SAAS;IACP,gBAAgB;IAChB,mBAAmB;GACrB;EACF;EACA,YAAY;GACV,WAAW;GACX,OAAO;EACT;EACA,MAAM;GACJ,OAAO;IACL,OAAO;IACP,SAAS,EACP,OAAO,eACT;GACF;GACA,QAAQ;GACR,SAAS;GACT,KAAK;GACL,YAAY;GACZ,eAAe;GACf,aAAa;GACb,cAAc;GACd,WAAW,EACT,QAAQ,cACV;GACA,kBAAkB;IAChB,OAAO;IACP,OAAO,EACL,OAAO,6BACT;IACA,SAAS;IACT,cAAc;KACZ,YAAY;KACZ,OAAO;KACP,SAAS;KACT,OAAO,EACL,OAAO,mCACT;IACF;GACF;GACA,SAAS;GACT,cAAc;IACZ,YAAY;IACZ,SAAS;GACX;GAGA,wBAAwB,EACtB,OAAO,gBACT;EACF;EACA,gBAAgB;GAGd,gBAAgB,EACd,aAAa,iBACf;GACA,WAAW;GACX,OAAO;GACP,YAAY;GACZ,aAAa;GACb,cAAc;GACd,eAAe;GACf,SAAS;GACT,KAAK;GACL,eAAe;GACf,YAAY;EACd;EACA,WAAW;GACT,OAAO;GACP,SAAS;EACX;CACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `data-*` attributes a component accepts and forwards verbatim to the one element it decides is
|
|
3
|
+
* the right target — never as a general prop passthrough. Mix it into a props type with `&` or
|
|
4
|
+
* `extends`.
|
|
5
|
+
*
|
|
6
|
+
* Components that own their layout (overlays, floating content) don't forward arbitrary props, so
|
|
7
|
+
* without this there is no way to address what they render. The cases it exists for are
|
|
8
|
+
* `data-testid`, and `data-clarity-unmask`, which opts a region out of session replay masking.
|
|
9
|
+
*
|
|
10
|
+
* Say in each component's own docs *which* element receives them — it differs: the dialogs use the
|
|
11
|
+
* element carrying `role="dialog"`, `BitkitActionMenu` the one carrying `role="menu"`.
|
|
12
|
+
*/
|
|
13
|
+
export interface BitkitDataAttributes {
|
|
14
|
+
[dataAttribute: `data-${string}`]: string | undefined;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Splits `data-*` attributes out of a props object so they can be sent somewhere other than the
|
|
18
|
+
* rest of the props.
|
|
19
|
+
*
|
|
20
|
+
* Needed when the remaining props go to something that is not a DOM element — a machine's root
|
|
21
|
+
* provider, say. Those drop anything they don't recognise, and silently, because TypeScript does
|
|
22
|
+
* not check hyphenated JSX attributes against a props type. A component whose props all land on one
|
|
23
|
+
* chakra element doesn't need this: a plain `{...rest}` already carries them.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const { dataAttributes, rest } = splitDataAttributes(props);
|
|
27
|
+
* return (
|
|
28
|
+
* <Menu.Root {...rest}>
|
|
29
|
+
* <Menu.Content {...dataAttributes} />
|
|
30
|
+
* </Menu.Root>
|
|
31
|
+
* );
|
|
32
|
+
*/
|
|
33
|
+
export declare const splitDataAttributes: <T extends object>(props: T) => {
|
|
34
|
+
dataAttributes: BitkitDataAttributes;
|
|
35
|
+
rest: Omit<T, `data-${string}`>;
|
|
36
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region lib/utilities/dataAttributes.ts
|
|
2
|
+
/**
|
|
3
|
+
* Splits `data-*` attributes out of a props object so they can be sent somewhere other than the
|
|
4
|
+
* rest of the props.
|
|
5
|
+
*
|
|
6
|
+
* Needed when the remaining props go to something that is not a DOM element — a machine's root
|
|
7
|
+
* provider, say. Those drop anything they don't recognise, and silently, because TypeScript does
|
|
8
|
+
* not check hyphenated JSX attributes against a props type. A component whose props all land on one
|
|
9
|
+
* chakra element doesn't need this: a plain `{...rest}` already carries them.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { dataAttributes, rest } = splitDataAttributes(props);
|
|
13
|
+
* return (
|
|
14
|
+
* <Menu.Root {...rest}>
|
|
15
|
+
* <Menu.Content {...dataAttributes} />
|
|
16
|
+
* </Menu.Root>
|
|
17
|
+
* );
|
|
18
|
+
*/
|
|
19
|
+
var splitDataAttributes = (props) => {
|
|
20
|
+
const entries = Object.entries(props);
|
|
21
|
+
const isDataAttribute = (key) => key.startsWith("data-");
|
|
22
|
+
return {
|
|
23
|
+
dataAttributes: Object.fromEntries(entries.filter(([key]) => isDataAttribute(key))),
|
|
24
|
+
rest: Object.fromEntries(entries.filter(([key]) => !isDataAttribute(key)))
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { splitDataAttributes };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=dataAttributes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataAttributes.js","names":[],"sources":["../../lib/utilities/dataAttributes.ts"],"sourcesContent":["/**\n * `data-*` attributes a component accepts and forwards verbatim to the one element it decides is\n * the right target — never as a general prop passthrough. Mix it into a props type with `&` or\n * `extends`.\n *\n * Components that own their layout (overlays, floating content) don't forward arbitrary props, so\n * without this there is no way to address what they render. The cases it exists for are\n * `data-testid`, and `data-clarity-unmask`, which opts a region out of session replay masking.\n *\n * Say in each component's own docs *which* element receives them — it differs: the dialogs use the\n * element carrying `role=\"dialog\"`, `BitkitActionMenu` the one carrying `role=\"menu\"`.\n */\nexport interface BitkitDataAttributes {\n [dataAttribute: `data-${string}`]: string | undefined;\n}\n\n/**\n * Splits `data-*` attributes out of a props object so they can be sent somewhere other than the\n * rest of the props.\n *\n * Needed when the remaining props go to something that is not a DOM element — a machine's root\n * provider, say. Those drop anything they don't recognise, and silently, because TypeScript does\n * not check hyphenated JSX attributes against a props type. A component whose props all land on one\n * chakra element doesn't need this: a plain `{...rest}` already carries them.\n *\n * @example\n * const { dataAttributes, rest } = splitDataAttributes(props);\n * return (\n * <Menu.Root {...rest}>\n * <Menu.Content {...dataAttributes} />\n * </Menu.Root>\n * );\n */\nexport const splitDataAttributes = <T extends object>(props: T) => {\n const entries = Object.entries(props);\n const isDataAttribute = (key: string) => key.startsWith('data-');\n\n return {\n dataAttributes: Object.fromEntries(entries.filter(([key]) => isDataAttribute(key))) as BitkitDataAttributes,\n rest: Object.fromEntries(entries.filter(([key]) => !isDataAttribute(key))) as Omit<T, `data-${string}`>,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiCA,IAAa,uBAAyC,UAAa;CACjE,MAAM,UAAU,OAAO,QAAQ,KAAK;CACpC,MAAM,mBAAmB,QAAgB,IAAI,WAAW,OAAO;CAE/D,OAAO;EACL,gBAAgB,OAAO,YAAY,QAAQ,QAAQ,CAAC,SAAS,gBAAgB,GAAG,CAAC,CAAC;EAClF,MAAM,OAAO,YAAY,QAAQ,QAAQ,CAAC,SAAS,CAAC,gBAAgB,GAAG,CAAC,CAAC;CAC3E;AACF"}
|