@bitrise/bitkit-v2 0.3.428 → 0.3.430-beta.2742

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 CHANGED
@@ -129,11 +129,11 @@ Bitkit components use consistent prop names across the library:
129
129
  ```
130
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.
131
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.
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
+ - **`BitkitTextInput` slots** — `startElement` / `endElement` take a `ReactNode` and render inside the field (an icon, badge, text, or an interactive control like a reveal/clear button). `startAddon` / `endAddon` render outside the border, attached to the field, and switch on the content type: a **string** gets the standard bordered grey box (a unit label like `$` / `USD`), while any **component** renders as itself, welded to the field — it keeps its own styling and the corners it touches are squared for you. So a button addon needs nothing beyond its own `size` and `variant`: don't square its corners by hand, and don't look for a way to strip the grey box — the content type is the switch. These match the Figma slot names. The validation status icon (error/warning) is added automatically and sits left of `endElement`. The field's `state` doesn't reach a component addon, so disable it yourself when it should follow:
133
133
  ```tsx
134
134
  <BitkitTextInput startElement={<IconSearch />} endElement={<BitkitBadge>New</BitkitBadge>} />
135
135
  <BitkitTextInput startAddon="$" endAddon="USD" />
136
- <BitkitTextInput startAddon={<BitkitButton variant="secondary">USD</BitkitButton>} startAddonProps={{ unstyled: true }} />
136
+ <BitkitTextInput endAddon={<BitkitIconButton icon={IconCopy} label="Copy" onClick={copy} variant="secondary" />} state="readOnly" value={token} />
137
137
  ```
138
138
  - **Three dialog components, one shell** — pick by intent, never reach for low-level dialog primitives (there are none exported):
139
139
  - `BitkitDialog` — header (title + close) + body (`children`) + footer. The body is the dialog's `children`. The footer is two slot props: `footerButtons` (action buttons, auto-wrapped in the standard right-aligned row — no manual wrapper) and `footerContent` (arbitrary content rendered raw, e.g. an inline `BitkitAlert`). Both can be combined (content first, then buttons); omit both for a passive dialog with no footer.
@@ -1,6 +1,6 @@
1
1
  import { BoxProps } from '@chakra-ui/react/box';
2
2
  import { SeparatorProps } from '@chakra-ui/react/separator';
3
- import { HTMLChakraProps } from '@chakra-ui/react/styled-system';
3
+ import { HTMLChakraProps, Tokens } from '@chakra-ui/react/styled-system';
4
4
  import { ReactNode } from 'react';
5
5
  import { BitkitIconComponent } from '../../icons';
6
6
  import { BitkitGroupHeadingProps } from '../BitkitGroupHeading/BitkitGroupHeading';
@@ -33,6 +33,60 @@ interface BitkitPageSidebarItemButtonProps extends Omit<HTMLChakraProps<'button'
33
33
  href?: never;
34
34
  }
35
35
  export type BitkitPageSidebarItemProps = BitkitPageSidebarItemButtonProps | BitkitPageSidebarItemLinkProps;
36
+ /**
37
+ * The tokens a stage's icon may be coloured with.
38
+ *
39
+ * `Tokens` is generated in the consumer's own project by `chakra typegen`, which
40
+ * `scripts/postinstall.cjs` runs and which exits 0 with a warning when it cannot. Where it did not
41
+ * run, `Tokens['colors']` is Chakra's stock union, the `Extract` has nothing to match and collapses
42
+ * to `never` -- which would make every `iconColor` a type error pointing at the wrong thing. So it
43
+ * falls back to `string`: the narrowing is a guard where the types are real, not a tripwire where
44
+ * they are not.
45
+ */
46
+ type BitkitStatusColorToken = [Extract<Tokens['colors'], `color/${string}` | `icon/${string}`>] extends [never] ? string : Extract<Tokens['colors'], `color/${string}` | `icon/${string}`>;
47
+ export interface BitkitPageSidebarProgressItemProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {
48
+ /**
49
+ * Trailing content between the label and the connector — a `BitkitBadge` counting what the stage
50
+ * is waiting on. Sized to itself; the connector takes the rest.
51
+ *
52
+ * The design draws it 20px tall, which is `size="xs"`. The badge arrives as a node, so the
53
+ * component cannot set that for you — a taller one grows the row past its 40px.
54
+ */
55
+ badge?: ReactNode;
56
+ /** The row's label. */
57
+ children: ReactNode;
58
+ /**
59
+ * The status icon. Unlike `Item`, whose icon colour the sidebar owns, this one carries the
60
+ * stage's status, so `iconColor` is the consumer's to set — `selected`, `notRequired` and
61
+ * `state="disabled"` still win over it, since those describe the row rather than the status.
62
+ */
63
+ icon: BitkitIconComponent;
64
+ /**
65
+ * A semantic token for the status the icon is showing. Left out, the icon takes the sidebar's own
66
+ * `icon/secondary` — which is what the design gives a stage whose icon carries no status, such as
67
+ * an approvals step.
68
+ *
69
+ * Narrowed to the `icon/*` and `color/*` tokens, so a name that does not exist is a compile error
70
+ * rather than a colour that silently does not apply. Both families are here because the statuses
71
+ * need both: the design takes success and failure from `icon/*` but in-progress from
72
+ * `color/orange/bold`, which the `icon/*` set has no equivalent of.
73
+ */
74
+ iconColor?: BitkitStatusColorToken;
75
+ /**
76
+ * A stage the release does not have to clear. Steps the icon and the label down one level, so the
77
+ * row reads as present but not awaited.
78
+ */
79
+ notRequired?: boolean;
80
+ /** Follows the label after a middle dot — `auto-upload`, `not required`. */
81
+ secondaryText?: string;
82
+ selected?: boolean;
83
+ state?: 'disabled';
84
+ /**
85
+ * Draws the dashed rule that runs from the badge to the trailing edge, tying one stage to the
86
+ * next. The last stage in a list has nothing to tie to, so it goes without.
87
+ */
88
+ withConnector?: boolean;
89
+ }
36
90
  interface BitkitPageSidebarTitleCommonProps extends BoxProps {
37
91
  backLabel?: string;
38
92
  children: ReactNode;
@@ -68,6 +122,7 @@ declare const _default: import('react').ForwardRefExoticComponent<BitkitPageSide
68
122
  Footer: import('react').ForwardRefExoticComponent<BitkitPageSidebarFooterProps & import('react').RefAttributes<HTMLDivElement>>;
69
123
  GroupHeading: import('react').ForwardRefExoticComponent<BitkitGroupHeadingProps & import('react').RefAttributes<HTMLDivElement>>;
70
124
  Item: import('react').ForwardRefExoticComponent<BitkitPageSidebarItemProps & import('react').RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
125
+ ProgressItem: import('react').ForwardRefExoticComponent<BitkitPageSidebarProgressItemProps & import('react').RefAttributes<HTMLButtonElement>>;
71
126
  Project: import('react').ForwardRefExoticComponent<BitkitPageSidebarProjectProps & import('react').RefAttributes<HTMLDivElement>>;
72
127
  Title: import('react').ForwardRefExoticComponent<BitkitPageSidebarTitleProps & import('react').RefAttributes<HTMLDivElement>>;
73
128
  };
@@ -143,6 +143,85 @@ var BitkitPageSidebarItem = forwardRef((props, ref) => {
143
143
  }));
144
144
  });
145
145
  BitkitPageSidebarItem.displayName = "BitkitPageSidebarItem";
146
+ /**
147
+ * A stage of something that progresses, as a row of the page sidebar — a release running through
148
+ * its steps, and whatever comes to look like it.
149
+ *
150
+ * It is a sibling of `Item` rather than a variant of it: the row reports where a stage stands
151
+ * rather than navigating, so its icon is status-coloured, its label does not grow, and a dashed
152
+ * connector runs to the trailing edge between the stages.
153
+ *
154
+ * Always a `<button>`, and always interactive — it carries the shared row's pointer cursor and
155
+ * hover background, so a row without an `onClick` looks actionable and is not. `Item`'s
156
+ * button-or-anchor union is deliberately not here: a stage is selected within the page it is
157
+ * already on rather than navigated to.
158
+ */
159
+ var BitkitPageSidebarProgressItem = forwardRef((props, ref) => {
160
+ const { badge, children, className, css, icon: Icon, iconColor, notRequired, secondaryText, selected, state, withConnector, ...rest } = props;
161
+ const isDisabled = state === "disabled";
162
+ const isSelected = selected && !isDisabled;
163
+ const isNotRequired = notRequired && !isDisabled && !isSelected;
164
+ const statusColor = isDisabled || isNotRequired || isSelected ? void 0 : iconColor;
165
+ const styles = useSlotRecipe({ key: "pageSidebar" })({
166
+ isDisabled,
167
+ notRequired: isNotRequired,
168
+ selected: isSelected
169
+ });
170
+ return /* @__PURE__ */ jsxs(chakra.button, {
171
+ ref,
172
+ ...rest,
173
+ "aria-current": isSelected ? "step" : void 0,
174
+ className: className ? `group ${className}` : "group",
175
+ css: [
176
+ styles.item,
177
+ styles.progressRow,
178
+ css
179
+ ],
180
+ disabled: isDisabled,
181
+ type: "button",
182
+ children: [/* @__PURE__ */ jsxs(Box, {
183
+ as: "span",
184
+ css: [styles.contentBlock, styles.progressContentBlock],
185
+ children: [
186
+ /* @__PURE__ */ jsx(Icon, {
187
+ color: statusColor,
188
+ css: [styles.progressIcon, showAtDesktop],
189
+ size: "16"
190
+ }),
191
+ /* @__PURE__ */ jsx(Icon, {
192
+ color: statusColor,
193
+ css: [styles.progressIcon, showAtMobile],
194
+ size: "24"
195
+ }),
196
+ /* @__PURE__ */ jsxs(Box, {
197
+ as: "span",
198
+ css: styles.progressTextBlock,
199
+ children: [/* @__PURE__ */ jsx(Text, {
200
+ as: "span",
201
+ css: styles.progressLabel,
202
+ children
203
+ }), secondaryText && /* @__PURE__ */ jsx(Text, {
204
+ as: "span",
205
+ css: styles.progressSecondaryText,
206
+ children: `\u00b7 ${secondaryText}`
207
+ })]
208
+ }),
209
+ (badge || withConnector) && /* @__PURE__ */ jsxs(Box, {
210
+ as: "span",
211
+ css: styles.progressBlocker,
212
+ children: [badge, withConnector && /* @__PURE__ */ jsx(Separator, {
213
+ "aria-hidden": true,
214
+ css: styles.progressConnector
215
+ })]
216
+ })
217
+ ]
218
+ }), isSelected && /* @__PURE__ */ jsx(Box, {
219
+ as: "span",
220
+ css: styles.selectionMarker
221
+ })]
222
+ });
223
+ });
224
+ BitkitPageSidebarProgressItem.displayName = "BitkitPageSidebarProgressItem";
146
225
  var BitkitPageSidebarTitle = forwardRef((props, ref) => {
147
226
  const { backHref, backLabel = "Back", children, css, onBackClick, ...rest } = props;
148
227
  const hasBack = backHref !== void 0 || onBackClick !== void 0;
@@ -255,6 +334,7 @@ var BitkitPageSidebar_default = withSubComponents(BitkitPageSidebar, {
255
334
  Footer: BitkitPageSidebarFooter,
256
335
  GroupHeading: BitkitPageSidebarGroupHeading,
257
336
  Item: BitkitPageSidebarItem,
337
+ ProgressItem: BitkitPageSidebarProgressItem,
258
338
  Project: BitkitPageSidebarProject,
259
339
  Title: BitkitPageSidebarTitle
260
340
  });
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitPageSidebar.js","names":[],"sources":["../../../lib/components/BitkitPageSidebar/BitkitPageSidebar.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { Separator, type SeparatorProps } from '@chakra-ui/react/separator';\nimport { chakra, type HTMLChakraProps, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport IconChevronLeft from '../../icons/IconChevronLeft';\nimport useIsTruncated from '../../utilities/useIsTruncated';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitControlButton from '../BitkitControlButton/BitkitControlButton';\nimport BitkitGroupHeading, { type BitkitGroupHeadingProps } from '../BitkitGroupHeading/BitkitGroupHeading';\nimport BitkitOverflowTooltip from '../BitkitOverflowTooltip/BitkitOverflowTooltip';\n\n// The 16 and 24 icons are separate drawings, not one scaled to two sizes, so the breakpoint swap\n// cannot live in the recipe — both are rendered and one is hidden. A `useBreakpointValue` would\n// render a single icon, but it only re-reads on mount: resize a live page across `tablet` and the\n// row resizes underneath an icon that keeps its old size.\nconst showAtDesktop = { display: { base: 'none', tablet: 'block' } };\nconst showAtMobile = { display: { base: 'block', tablet: 'none' } };\n\n// ----- BitkitPageSidebar (Root) -----\n\nexport interface BitkitPageSidebarProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Page-level navigation sidebar. It expects three children, in this order:\n *\n * ```tsx\n * <BitkitPageSidebar>\n * <BitkitPageSidebar.Title>Title</BitkitPageSidebar.Title>\n * <BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Item icon={IconWorkflow}>Workflows</BitkitPageSidebar.Item>\n * </BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>\n * </BitkitPageSidebar>\n * ```\n *\n * `Title` and `Footer` are optional. The sidebar scrolls as a single block: when the navigation is\n * taller than the viewport the whole thing — footer included — grows and scrolls with the page,\n * which is why `Body` keeps a minimum gap above the footer so the two blocks never touch.\n *\n * The `<nav>` carries a default `aria-label` so it is not announced as an unnamed landmark. A page\n * with more than one sidebar should name each one — pass your own `aria-label` (or\n * `aria-labelledby`), which overrides the default.\n *\n * It stands at least viewport-tall by default. An embedded panel that should size to its content\n * opts out with `minHeight=\"auto\"`.\n *\n * Below the `tablet` breakpoint it switches to the mobile design on its own — full width, 48px\n * rows, larger icons and labels, a squared-off selection edge. There is no prop for it: a sidebar\n * that narrow is a sidebar filling a phone.\n */\nconst BitkitPageSidebar = forwardRef<HTMLElement, BitkitPageSidebarProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={[styles.root, css]} {...rest}>\n <nav>{children}</nav>\n </Box>\n );\n});\n\nBitkitPageSidebar.displayName = 'BitkitPageSidebar';\n\n// ----- BitkitPageSidebar.Item -----\n\ninterface BitkitPageSidebarItemCommonProps {\n badge?: ReactNode;\n /**\n * The item's label. Typed as a string rather than `ReactNode` because the row truncates it with\n * an ellipsis, and the overflow tooltip needs the full text to reveal.\n */\n children: string;\n icon?: BitkitIconComponent;\n /**\n * Marks the item as the current page. Mutually exclusive with `state=\"disabled\"` — you cannot be\n * on a page whose nav item is unavailable — but the two are not type-checked against each other:\n * the combination only ever arrives from a computed `selected`, which no union can catch, and\n * checking it would break the ordinary `selected={item.id === currentId}` mapping. If both do\n * turn up, disabled wins, since that is the one of the two the design actually defines.\n */\n selected?: boolean;\n state?: 'disabled';\n suffixIcon?: BitkitIconComponent;\n}\n\ninterface BitkitPageSidebarItemLinkProps\n extends Omit<HTMLChakraProps<'a'>, 'children'>, BitkitPageSidebarItemCommonProps {\n href: string;\n}\n\ninterface BitkitPageSidebarItemButtonProps\n extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'>, BitkitPageSidebarItemCommonProps {\n href?: never;\n}\n\nexport type BitkitPageSidebarItemProps = BitkitPageSidebarItemButtonProps | BitkitPageSidebarItemLinkProps;\n\nconst BitkitPageSidebarItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, BitkitPageSidebarItemProps>(\n (props, ref) => {\n const { badge, children, icon: Icon, selected, state, suffixIcon: SuffixIcon, ...rest } = props;\n\n const isDisabled = state === 'disabled';\n // `selected` and `state=\"disabled\"` are not checked against each other in the types, so this is\n // the single place the overlap is resolved: disabled wins, and the two recipe variants can never\n // both claim the same slot.\n const isSelected = selected === true && !isDisabled;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, selected: isSelected });\n\n // The design gives neither a selected row nor a disabled one a trailing icon — the desktop\n // (`20014:6498`, `20014:6494`) and mobile (`9221:4417`) items drop it in those states.\n const VisibleSuffixIcon = isSelected || isDisabled ? undefined : SuffixIcon;\n\n const { isTruncated, ref: labelRef } = useIsTruncated<HTMLSpanElement>(children);\n\n const itemContent = (\n <>\n {/* `span`, not the default `div`: in button mode these sit inside a `<button>`, whose\n content model allows phrasing content only. */}\n <Box as=\"span\" css={styles.contentBlock}>\n {Icon && (\n <>\n <Icon css={[styles.itemIcon, showAtDesktop]} size=\"16\" />\n <Icon css={[styles.itemIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n <Text as=\"span\" css={styles.itemLabel} ref={labelRef}>\n {children}\n </Text>\n </Box>\n {badge}\n {VisibleSuffixIcon && (\n <>\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtDesktop]} size=\"16\" />\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </>\n );\n\n // The overflow tooltip anchors to the row itself, which is the focusable element: anchored to an\n // inner node it would only ever open on hover, leaving keyboard users unable to read a truncated\n // label. `Tooltip.Trigger` renders `asChild` and composes refs, so the consumer's forwarded ref\n // survives, and the ref measuring the truncation sits on the label further in.\n const withTooltip = (row: ReactNode) => (\n <BitkitOverflowTooltip disabled={!isTruncated} text={children}>\n {row}\n </BitkitOverflowTooltip>\n );\n\n // `chakra.a` / `chakra.button` rather than a named primitive: the item carries its own slot recipe,\n // and Chakra's `Button`/`Link` would layer their own recipe styles on top of it.\n if (rest.href !== undefined) {\n const { className, href, onClick, onKeyDown, ...linkRest } = rest;\n const handleClick = isDisabled\n ? (event: MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (event: KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n : onKeyDown;\n\n return withTooltip(\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...linkRest}\n aria-current={isSelected ? 'page' : undefined}\n aria-disabled={isDisabled || undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n // Dropping the attribute is what actually disables the link, the way `BitkitLink` and\n // `BitkitControlButton` do it. The handlers below only block `click` and `Enter`/`Space`;\n // a middle click fires `auxclick`, and \"Open link in new tab\" never reaches the page at\n // all, so both would still navigate while an `href` is there to follow.\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n >\n {itemContent}\n </chakra.a>,\n );\n }\n\n const { className, href: _href, ...buttonRest } = rest;\n\n return withTooltip(\n <chakra.button\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n aria-current={isSelected ? 'page' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n disabled={isDisabled}\n type=\"button\"\n >\n {itemContent}\n </chakra.button>,\n );\n },\n);\n\nBitkitPageSidebarItem.displayName = 'BitkitPageSidebarItem';\n\n// ----- BitkitPageSidebar.Title -----\n\ninterface BitkitPageSidebarTitleCommonProps extends BoxProps {\n backLabel?: string;\n children: ReactNode;\n}\n\ninterface BitkitPageSidebarTitleLinkProps extends BitkitPageSidebarTitleCommonProps {\n backHref: string;\n onBackClick?: never;\n}\n\ninterface BitkitPageSidebarTitleButtonProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick: () => void;\n}\n\ninterface BitkitPageSidebarTitlePlainProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick?: never;\n}\n\nexport type BitkitPageSidebarTitleProps =\n | BitkitPageSidebarTitleButtonProps\n | BitkitPageSidebarTitleLinkProps\n | BitkitPageSidebarTitlePlainProps;\n\nconst BitkitPageSidebarTitle = forwardRef<HTMLDivElement, BitkitPageSidebarTitleProps>((props, ref) => {\n const { backHref, backLabel = 'Back', children, css, onBackClick, ...rest } = props;\n\n const hasBack = backHref !== undefined || onBackClick !== undefined;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasBack });\n\n return (\n <Box ref={ref} css={[styles.title, css]} {...rest}>\n <Box css={styles.titleBlock}>\n {/* The label tooltip opens to the right. Its default `top` has nowhere to go here — the\n button sits at the very top of the sidebar, so the tooltip jams against the viewport\n edge and covers the header instead of flipping. */}\n {hasBack &&\n (backHref !== undefined ? (\n <BitkitControlButton\n href={backHref}\n icon={IconChevronLeft}\n label={backLabel}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ) : (\n <BitkitControlButton\n icon={IconChevronLeft}\n label={backLabel}\n onClick={onBackClick}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ))}\n <Text as=\"span\" css={styles.titleText}>\n {children}\n </Text>\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarTitle.displayName = 'BitkitPageSidebarTitle';\n\n// ----- BitkitPageSidebar.Body -----\n\nexport interface BitkitPageSidebarBodyProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Holds the navigation items. It absorbs the space left between `Title` and `Footer`, so the footer\n * sits at the bottom of the viewport on a short navigation, and keeps a minimum gap above the\n * footer so the two blocks stay visually separate however long the list gets.\n */\nconst BitkitPageSidebarBody = forwardRef<HTMLDivElement, BitkitPageSidebarBodyProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.body, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarBody.displayName = 'BitkitPageSidebarBody';\n\n// ----- BitkitPageSidebar.Footer -----\n\nexport interface BitkitPageSidebarFooterProps extends BoxProps {\n children: ReactNode;\n}\n\nconst BitkitPageSidebarFooter = forwardRef<HTMLDivElement, BitkitPageSidebarFooterProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.footer, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarFooter.displayName = 'BitkitPageSidebarFooter';\n\n// ----- BitkitPageSidebar.Project -----\n\nexport interface BitkitPageSidebarProjectProps extends BoxProps {\n label: string;\n value: string;\n}\n\nconst BitkitPageSidebarProject = forwardRef<HTMLDivElement, BitkitPageSidebarProjectProps>((props, ref) => {\n const { css, label, value, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n const { isTruncated, ref: valueRef } = useIsTruncated<HTMLSpanElement>(value);\n\n return (\n <Box ref={ref} css={[styles.project, css]} {...rest}>\n <Text as=\"span\" css={styles.projectLabel}>\n {label}\n </Text>\n {/* Wrapper for the same reason as in Item: the trigger cannot be the element being measured. */}\n <BitkitOverflowTooltip disabled={!isTruncated} text={value}>\n <Box css={styles.projectValueWrapper}>\n <Text as=\"span\" css={styles.projectValue} ref={valueRef}>\n {value}\n </Text>\n </Box>\n </BitkitOverflowTooltip>\n </Box>\n );\n});\n\nBitkitPageSidebarProject.displayName = 'BitkitPageSidebarProject';\n\n// ----- BitkitPageSidebar.GroupHeading -----\n\nexport type BitkitPageSidebarGroupHeadingProps = BitkitGroupHeadingProps;\n\nconst BitkitPageSidebarGroupHeading = forwardRef<HTMLDivElement, BitkitPageSidebarGroupHeadingProps>((props, ref) => {\n return <BitkitGroupHeading ref={ref} paddingBlockEnd=\"8\" paddingBlockStart=\"16\" paddingInline=\"24\" {...props} />;\n});\n\nBitkitPageSidebarGroupHeading.displayName = 'BitkitPageSidebarGroupHeading';\n\n// ----- BitkitPageSidebar.Divider -----\n\nexport type BitkitPageSidebarDividerProps = SeparatorProps;\n\nconst BitkitPageSidebarDivider = forwardRef<HTMLDivElement, BitkitPageSidebarDividerProps>((props, ref) => {\n const { css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return <Separator ref={ref} css={[styles.divider, css]} {...rest} />;\n});\n\nBitkitPageSidebarDivider.displayName = 'BitkitPageSidebarDivider';\n\nexport default withSubComponents(BitkitPageSidebar, {\n Body: BitkitPageSidebarBody,\n Divider: BitkitPageSidebarDivider,\n Footer: BitkitPageSidebarFooter,\n GroupHeading: BitkitPageSidebarGroupHeading,\n Item: BitkitPageSidebarItem,\n Project: BitkitPageSidebarProject,\n Title: BitkitPageSidebarTitle,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"BitkitPageSidebar.js","names":[],"sources":["../../../lib/components/BitkitPageSidebar/BitkitPageSidebar.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { Separator, type SeparatorProps } from '@chakra-ui/react/separator';\nimport { chakra, type HTMLChakraProps, type Tokens, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport IconChevronLeft from '../../icons/IconChevronLeft';\nimport useIsTruncated from '../../utilities/useIsTruncated';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitControlButton from '../BitkitControlButton/BitkitControlButton';\nimport BitkitGroupHeading, { type BitkitGroupHeadingProps } from '../BitkitGroupHeading/BitkitGroupHeading';\nimport BitkitOverflowTooltip from '../BitkitOverflowTooltip/BitkitOverflowTooltip';\n\n// The 16 and 24 icons are separate drawings, not one scaled to two sizes, so the breakpoint swap\n// cannot live in the recipe — both are rendered and one is hidden. A `useBreakpointValue` would\n// render a single icon, but it only re-reads on mount: resize a live page across `tablet` and the\n// row resizes underneath an icon that keeps its old size.\nconst showAtDesktop = { display: { base: 'none', tablet: 'block' } };\nconst showAtMobile = { display: { base: 'block', tablet: 'none' } };\n\n// ----- BitkitPageSidebar (Root) -----\n\nexport interface BitkitPageSidebarProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Page-level navigation sidebar. It expects three children, in this order:\n *\n * ```tsx\n * <BitkitPageSidebar>\n * <BitkitPageSidebar.Title>Title</BitkitPageSidebar.Title>\n * <BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Item icon={IconWorkflow}>Workflows</BitkitPageSidebar.Item>\n * </BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>\n * </BitkitPageSidebar>\n * ```\n *\n * `Title` and `Footer` are optional. The sidebar scrolls as a single block: when the navigation is\n * taller than the viewport the whole thing — footer included — grows and scrolls with the page,\n * which is why `Body` keeps a minimum gap above the footer so the two blocks never touch.\n *\n * The `<nav>` carries a default `aria-label` so it is not announced as an unnamed landmark. A page\n * with more than one sidebar should name each one — pass your own `aria-label` (or\n * `aria-labelledby`), which overrides the default.\n *\n * It stands at least viewport-tall by default. An embedded panel that should size to its content\n * opts out with `minHeight=\"auto\"`.\n *\n * Below the `tablet` breakpoint it switches to the mobile design on its own — full width, 48px\n * rows, larger icons and labels, a squared-off selection edge. There is no prop for it: a sidebar\n * that narrow is a sidebar filling a phone.\n */\nconst BitkitPageSidebar = forwardRef<HTMLElement, BitkitPageSidebarProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={[styles.root, css]} {...rest}>\n <nav>{children}</nav>\n </Box>\n );\n});\n\nBitkitPageSidebar.displayName = 'BitkitPageSidebar';\n\n// ----- BitkitPageSidebar.Item -----\n\ninterface BitkitPageSidebarItemCommonProps {\n badge?: ReactNode;\n /**\n * The item's label. Typed as a string rather than `ReactNode` because the row truncates it with\n * an ellipsis, and the overflow tooltip needs the full text to reveal.\n */\n children: string;\n icon?: BitkitIconComponent;\n /**\n * Marks the item as the current page. Mutually exclusive with `state=\"disabled\"` — you cannot be\n * on a page whose nav item is unavailable — but the two are not type-checked against each other:\n * the combination only ever arrives from a computed `selected`, which no union can catch, and\n * checking it would break the ordinary `selected={item.id === currentId}` mapping. If both do\n * turn up, disabled wins, since that is the one of the two the design actually defines.\n */\n selected?: boolean;\n state?: 'disabled';\n suffixIcon?: BitkitIconComponent;\n}\n\ninterface BitkitPageSidebarItemLinkProps\n extends Omit<HTMLChakraProps<'a'>, 'children'>, BitkitPageSidebarItemCommonProps {\n href: string;\n}\n\ninterface BitkitPageSidebarItemButtonProps\n extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'>, BitkitPageSidebarItemCommonProps {\n href?: never;\n}\n\nexport type BitkitPageSidebarItemProps = BitkitPageSidebarItemButtonProps | BitkitPageSidebarItemLinkProps;\n\nconst BitkitPageSidebarItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, BitkitPageSidebarItemProps>(\n (props, ref) => {\n const { badge, children, icon: Icon, selected, state, suffixIcon: SuffixIcon, ...rest } = props;\n\n const isDisabled = state === 'disabled';\n // `selected` and `state=\"disabled\"` are not checked against each other in the types, so this is\n // the single place the overlap is resolved: disabled wins, and the two recipe variants can never\n // both claim the same slot.\n const isSelected = selected === true && !isDisabled;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, selected: isSelected });\n\n // The design gives neither a selected row nor a disabled one a trailing icon — the desktop\n // (`20014:6498`, `20014:6494`) and mobile (`9221:4417`) items drop it in those states.\n const VisibleSuffixIcon = isSelected || isDisabled ? undefined : SuffixIcon;\n\n const { isTruncated, ref: labelRef } = useIsTruncated<HTMLSpanElement>(children);\n\n const itemContent = (\n <>\n {/* `span`, not the default `div`: in button mode these sit inside a `<button>`, whose\n content model allows phrasing content only. */}\n <Box as=\"span\" css={styles.contentBlock}>\n {Icon && (\n <>\n <Icon css={[styles.itemIcon, showAtDesktop]} size=\"16\" />\n <Icon css={[styles.itemIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n <Text as=\"span\" css={styles.itemLabel} ref={labelRef}>\n {children}\n </Text>\n </Box>\n {badge}\n {VisibleSuffixIcon && (\n <>\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtDesktop]} size=\"16\" />\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </>\n );\n\n // The overflow tooltip anchors to the row itself, which is the focusable element: anchored to an\n // inner node it would only ever open on hover, leaving keyboard users unable to read a truncated\n // label. `Tooltip.Trigger` renders `asChild` and composes refs, so the consumer's forwarded ref\n // survives, and the ref measuring the truncation sits on the label further in.\n const withTooltip = (row: ReactNode) => (\n <BitkitOverflowTooltip disabled={!isTruncated} text={children}>\n {row}\n </BitkitOverflowTooltip>\n );\n\n // `chakra.a` / `chakra.button` rather than a named primitive: the item carries its own slot recipe,\n // and Chakra's `Button`/`Link` would layer their own recipe styles on top of it.\n if (rest.href !== undefined) {\n const { className, href, onClick, onKeyDown, ...linkRest } = rest;\n const handleClick = isDisabled\n ? (event: MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (event: KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n : onKeyDown;\n\n return withTooltip(\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...linkRest}\n aria-current={isSelected ? 'page' : undefined}\n aria-disabled={isDisabled || undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n // Dropping the attribute is what actually disables the link, the way `BitkitLink` and\n // `BitkitControlButton` do it. The handlers below only block `click` and `Enter`/`Space`;\n // a middle click fires `auxclick`, and \"Open link in new tab\" never reaches the page at\n // all, so both would still navigate while an `href` is there to follow.\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n >\n {itemContent}\n </chakra.a>,\n );\n }\n\n const { className, href: _href, ...buttonRest } = rest;\n\n return withTooltip(\n <chakra.button\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n aria-current={isSelected ? 'page' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n disabled={isDisabled}\n type=\"button\"\n >\n {itemContent}\n </chakra.button>,\n );\n },\n);\n\nBitkitPageSidebarItem.displayName = 'BitkitPageSidebarItem';\n\n// ----- BitkitPageSidebar.ProgressItem -----\n\n/**\n * The tokens a stage's icon may be coloured with.\n *\n * `Tokens` is generated in the consumer's own project by `chakra typegen`, which\n * `scripts/postinstall.cjs` runs and which exits 0 with a warning when it cannot. Where it did not\n * run, `Tokens['colors']` is Chakra's stock union, the `Extract` has nothing to match and collapses\n * to `never` -- which would make every `iconColor` a type error pointing at the wrong thing. So it\n * falls back to `string`: the narrowing is a guard where the types are real, not a tripwire where\n * they are not.\n */\ntype BitkitStatusColorToken = [Extract<Tokens['colors'], `color/${string}` | `icon/${string}`>] extends [never]\n ? string\n : Extract<Tokens['colors'], `color/${string}` | `icon/${string}`>;\n\nexport interface BitkitPageSidebarProgressItemProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {\n /**\n * Trailing content between the label and the connector — a `BitkitBadge` counting what the stage\n * is waiting on. Sized to itself; the connector takes the rest.\n *\n * The design draws it 20px tall, which is `size=\"xs\"`. The badge arrives as a node, so the\n * component cannot set that for you — a taller one grows the row past its 40px.\n */\n badge?: ReactNode;\n /** The row's label. */\n children: ReactNode;\n /**\n * The status icon. Unlike `Item`, whose icon colour the sidebar owns, this one carries the\n * stage's status, so `iconColor` is the consumer's to set — `selected`, `notRequired` and\n * `state=\"disabled\"` still win over it, since those describe the row rather than the status.\n */\n icon: BitkitIconComponent;\n /**\n * A semantic token for the status the icon is showing. Left out, the icon takes the sidebar's own\n * `icon/secondary` — which is what the design gives a stage whose icon carries no status, such as\n * an approvals step.\n *\n * Narrowed to the `icon/*` and `color/*` tokens, so a name that does not exist is a compile error\n * rather than a colour that silently does not apply. Both families are here because the statuses\n * need both: the design takes success and failure from `icon/*` but in-progress from\n * `color/orange/bold`, which the `icon/*` set has no equivalent of.\n */\n iconColor?: BitkitStatusColorToken;\n /**\n * A stage the release does not have to clear. Steps the icon and the label down one level, so the\n * row reads as present but not awaited.\n */\n notRequired?: boolean;\n /** Follows the label after a middle dot — `auto-upload`, `not required`. */\n secondaryText?: string;\n selected?: boolean;\n state?: 'disabled';\n /**\n * Draws the dashed rule that runs from the badge to the trailing edge, tying one stage to the\n * next. The last stage in a list has nothing to tie to, so it goes without.\n */\n withConnector?: boolean;\n}\n\n/**\n * A stage of something that progresses, as a row of the page sidebar — a release running through\n * its steps, and whatever comes to look like it.\n *\n * It is a sibling of `Item` rather than a variant of it: the row reports where a stage stands\n * rather than navigating, so its icon is status-coloured, its label does not grow, and a dashed\n * connector runs to the trailing edge between the stages.\n *\n * Always a `<button>`, and always interactive — it carries the shared row's pointer cursor and\n * hover background, so a row without an `onClick` looks actionable and is not. `Item`'s\n * button-or-anchor union is deliberately not here: a stage is selected within the page it is\n * already on rather than navigated to.\n */\nconst BitkitPageSidebarProgressItem = forwardRef<HTMLButtonElement, BitkitPageSidebarProgressItemProps>(\n (props, ref) => {\n const {\n badge,\n children,\n className,\n css,\n icon: Icon,\n iconColor,\n notRequired,\n secondaryText,\n selected,\n state,\n withConnector,\n ...rest\n } = props;\n\n const isDisabled = state === 'disabled';\n // Disabled is the whole state of the row, so the other two are dropped rather than merged: the\n // recipe resolves a combination in its own order, and a disabled row came out of it carrying\n // the selected icon colour. Nothing about a disabled stage is selected or not-required.\n const isSelected = selected && !isDisabled;\n // And `selected` wins over `notRequired`, which the design decides rather than declaration\n // order: its `selected=yes, notRequired=true` variant draws the selected row's icon and label\n // and keeps `not required` in the secondary text -- which is what dropping this produces.\n const isNotRequired = notRequired && !isDisabled && !isSelected;\n\n const statusColor = isDisabled || isNotRequired || isSelected ? undefined : iconColor;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, notRequired: isNotRequired, selected: isSelected });\n\n return (\n <chakra.button\n ref={ref}\n {...rest}\n // `step` rather than the `page` an `Item` carries: these are stages of one thing, not\n // separate pages.\n aria-current={isSelected ? 'step' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={[styles.item, styles.progressRow, css]}\n disabled={isDisabled}\n type=\"button\"\n >\n <Box as=\"span\" css={[styles.contentBlock, styles.progressContentBlock]}>\n {/* Two icons, one per size, for the reason `Item` has two -- see `showAtDesktop`.\n The status colour applies while the row is ordinary: `selected`, `notRequired` and\n disabled are states of the row rather than of the status, and the design recolours the\n icon in all three, so the recipe takes it back there. */}\n <Icon color={statusColor} css={[styles.progressIcon, showAtDesktop]} size=\"16\" />\n <Icon color={statusColor} css={[styles.progressIcon, showAtMobile]} size=\"24\" />\n <Box as=\"span\" css={styles.progressTextBlock}>\n <Text as=\"span\" css={styles.progressLabel}>\n {children}\n </Text>\n {secondaryText && (\n <Text as=\"span\" css={styles.progressSecondaryText}>\n {`\\u00b7 ${secondaryText}`}\n </Text>\n )}\n </Box>\n {(badge || withConnector) && (\n <Box as=\"span\" css={styles.progressBlocker}>\n {badge}\n {/* Decorative: it ties the stages together visually and has nothing to separate in\n the button's accessibility tree. */}\n {withConnector && <Separator aria-hidden css={styles.progressConnector} />}\n </Box>\n )}\n </Box>\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </chakra.button>\n );\n },\n);\n\nBitkitPageSidebarProgressItem.displayName = 'BitkitPageSidebarProgressItem';\n\n// ----- BitkitPageSidebar.Title -----\n\ninterface BitkitPageSidebarTitleCommonProps extends BoxProps {\n backLabel?: string;\n children: ReactNode;\n}\n\ninterface BitkitPageSidebarTitleLinkProps extends BitkitPageSidebarTitleCommonProps {\n backHref: string;\n onBackClick?: never;\n}\n\ninterface BitkitPageSidebarTitleButtonProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick: () => void;\n}\n\ninterface BitkitPageSidebarTitlePlainProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick?: never;\n}\n\nexport type BitkitPageSidebarTitleProps =\n | BitkitPageSidebarTitleButtonProps\n | BitkitPageSidebarTitleLinkProps\n | BitkitPageSidebarTitlePlainProps;\n\nconst BitkitPageSidebarTitle = forwardRef<HTMLDivElement, BitkitPageSidebarTitleProps>((props, ref) => {\n const { backHref, backLabel = 'Back', children, css, onBackClick, ...rest } = props;\n\n const hasBack = backHref !== undefined || onBackClick !== undefined;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasBack });\n\n return (\n <Box ref={ref} css={[styles.title, css]} {...rest}>\n <Box css={styles.titleBlock}>\n {/* The label tooltip opens to the right. Its default `top` has nowhere to go here — the\n button sits at the very top of the sidebar, so the tooltip jams against the viewport\n edge and covers the header instead of flipping. */}\n {hasBack &&\n (backHref !== undefined ? (\n <BitkitControlButton\n href={backHref}\n icon={IconChevronLeft}\n label={backLabel}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ) : (\n <BitkitControlButton\n icon={IconChevronLeft}\n label={backLabel}\n onClick={onBackClick}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ))}\n <Text as=\"span\" css={styles.titleText}>\n {children}\n </Text>\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarTitle.displayName = 'BitkitPageSidebarTitle';\n\n// ----- BitkitPageSidebar.Body -----\n\nexport interface BitkitPageSidebarBodyProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Holds the navigation items. It absorbs the space left between `Title` and `Footer`, so the footer\n * sits at the bottom of the viewport on a short navigation, and keeps a minimum gap above the\n * footer so the two blocks stay visually separate however long the list gets.\n */\nconst BitkitPageSidebarBody = forwardRef<HTMLDivElement, BitkitPageSidebarBodyProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.body, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarBody.displayName = 'BitkitPageSidebarBody';\n\n// ----- BitkitPageSidebar.Footer -----\n\nexport interface BitkitPageSidebarFooterProps extends BoxProps {\n children: ReactNode;\n}\n\nconst BitkitPageSidebarFooter = forwardRef<HTMLDivElement, BitkitPageSidebarFooterProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.footer, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarFooter.displayName = 'BitkitPageSidebarFooter';\n\n// ----- BitkitPageSidebar.Project -----\n\nexport interface BitkitPageSidebarProjectProps extends BoxProps {\n label: string;\n value: string;\n}\n\nconst BitkitPageSidebarProject = forwardRef<HTMLDivElement, BitkitPageSidebarProjectProps>((props, ref) => {\n const { css, label, value, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n const { isTruncated, ref: valueRef } = useIsTruncated<HTMLSpanElement>(value);\n\n return (\n <Box ref={ref} css={[styles.project, css]} {...rest}>\n <Text as=\"span\" css={styles.projectLabel}>\n {label}\n </Text>\n {/* Wrapper for the same reason as in Item: the trigger cannot be the element being measured. */}\n <BitkitOverflowTooltip disabled={!isTruncated} text={value}>\n <Box css={styles.projectValueWrapper}>\n <Text as=\"span\" css={styles.projectValue} ref={valueRef}>\n {value}\n </Text>\n </Box>\n </BitkitOverflowTooltip>\n </Box>\n );\n});\n\nBitkitPageSidebarProject.displayName = 'BitkitPageSidebarProject';\n\n// ----- BitkitPageSidebar.GroupHeading -----\n\nexport type BitkitPageSidebarGroupHeadingProps = BitkitGroupHeadingProps;\n\nconst BitkitPageSidebarGroupHeading = forwardRef<HTMLDivElement, BitkitPageSidebarGroupHeadingProps>((props, ref) => {\n return <BitkitGroupHeading ref={ref} paddingBlockEnd=\"8\" paddingBlockStart=\"16\" paddingInline=\"24\" {...props} />;\n});\n\nBitkitPageSidebarGroupHeading.displayName = 'BitkitPageSidebarGroupHeading';\n\n// ----- BitkitPageSidebar.Divider -----\n\nexport type BitkitPageSidebarDividerProps = SeparatorProps;\n\nconst BitkitPageSidebarDivider = forwardRef<HTMLDivElement, BitkitPageSidebarDividerProps>((props, ref) => {\n const { css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return <Separator ref={ref} css={[styles.divider, css]} {...rest} />;\n});\n\nBitkitPageSidebarDivider.displayName = 'BitkitPageSidebarDivider';\n\nexport default withSubComponents(BitkitPageSidebar, {\n Body: BitkitPageSidebarBody,\n Divider: BitkitPageSidebarDivider,\n Footer: BitkitPageSidebarFooter,\n GroupHeading: BitkitPageSidebarGroupHeading,\n Item: BitkitPageSidebarItem,\n ProgressItem: BitkitPageSidebarProgressItem,\n Project: BitkitPageSidebarProject,\n Title: BitkitPageSidebarTitle,\n});\n"],"mappings":"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"}
@@ -12,7 +12,7 @@ import { Skeleton } from "@chakra-ui/react/skeleton";
12
12
  import { Switch } from "@chakra-ui/react/switch";
13
13
  //#region lib/components/BitkitSwitch/BitkitSwitch.tsx
14
14
  var BitkitSwitchDefault = forwardRef((props, ref) => {
15
- const { label, size = "lg", state = "default", ...rest } = props;
15
+ const { hideLabel, label, size = "lg", state = "default", ...rest } = props;
16
16
  return /* @__PURE__ */ jsxs(Switch.Root, {
17
17
  size,
18
18
  readOnly: state === "readOnly",
@@ -32,7 +32,10 @@ var BitkitSwitchDefault = forwardRef((props, ref) => {
32
32
  })] })
33
33
  })
34
34
  }),
35
- label && /* @__PURE__ */ jsx(Switch.Label, { children: label })
35
+ label && /* @__PURE__ */ jsx(Switch.Label, {
36
+ srOnly: hideLabel,
37
+ children: label
38
+ })
36
39
  ]
37
40
  });
38
41
  });
@@ -131,7 +134,7 @@ var BitkitSwitchFixed = forwardRef((props, ref) => {
131
134
  });
132
135
  BitkitSwitchFixed.displayName = "BitkitSwitchFixed";
133
136
  var BitkitSwitch = forwardRef((props, ref) => {
134
- const { variant, icon, tooltip, optional, valueText, helperText, ...rest } = props;
137
+ const { variant, hideLabel, icon, tooltip, optional, valueText, helperText, ...rest } = props;
135
138
  if (variant === "dynamic-text") return /* @__PURE__ */ jsx(BitkitSwitchDynamicText, {
136
139
  ref,
137
140
  tooltip,
@@ -150,6 +153,7 @@ var BitkitSwitch = forwardRef((props, ref) => {
150
153
  });
151
154
  return /* @__PURE__ */ jsx(BitkitSwitchDefault, {
152
155
  ref,
156
+ hideLabel,
153
157
  ...rest
154
158
  });
155
159
  });
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitSwitch.js","names":[],"sources":["../../../lib/components/BitkitSwitch/BitkitSwitch.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Switch } from '@chakra-ui/react/switch';\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { IconCheck, IconCross } from '../../icons';\nimport type {\n BitkitSwitchAnyVariantProps,\n BitkitSwitchDefaultProps,\n BitkitSwitchDynamicTextProps,\n BitkitSwitchFixedProps,\n BitkitSwitchProps,\n} from './BitkitSwitch.types';\nimport BitkitSwitchHelperText from './components/BitkitSwitchHelperText';\nimport BitkitSwitchLabel from './components/BitkitSwitchLabel';\nimport BitkitSwitchReadOnly from './components/BitkitSwitchReadOnly';\nimport BitkitSwitchValueText from './components/BitkitSwitchValueText';\n\nconst BitkitSwitchDefault = forwardRef<HTMLInputElement, Omit<BitkitSwitchDefaultProps, 'variant'>>((props, ref) => {\n const { label, size = 'lg', state = 'default', ...rest } = props;\n\n return (\n <Switch.Root\n size={size}\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n {label && <Switch.Label>{label}</Switch.Label>}\n </Switch.Root>\n );\n});\n\nBitkitSwitchDefault.displayName = 'BitkitSwitchDefault';\n\nconst BitkitSwitchDynamicText = forwardRef<HTMLInputElement, Omit<BitkitSwitchDynamicTextProps, 'variant'>>(\n (props, ref) => {\n const { label, optional, tooltip, helperText, valueText, size = 'lg', state = 'default', ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'switch' });\n const styles = recipe({ size });\n\n return (\n <Switch.Root\n gap=\"4\"\n size={size}\n required={!optional}\n flexDirection=\"column\"\n alignItems=\"flex-start\"\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'disabledInput' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <BitkitSwitchLabel label={label} state={state} tooltip={tooltip} optional={optional} />\n <Box css={styles.root}>\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n <BitkitSwitchValueText size={size} state={state} valueText={valueText} />\n </Box>\n <BitkitSwitchHelperText state={state} helperText={helperText} />\n </Switch.Root>\n );\n },\n);\n\nBitkitSwitchDynamicText.displayName = 'BitkitSwitchDynamicText';\n\nconst BitkitSwitchFixed = forwardRef<HTMLInputElement, Omit<BitkitSwitchFixedProps, 'variant'>>((props, ref) => {\n const { icon, label, optional, tooltip, helperText, size = 'lg', state = 'default', ...rest } = props;\n\n return (\n <Switch.Root\n gap=\"24\"\n size={size}\n width=\"100%\"\n display=\"flex\"\n required={!optional}\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'disabledInput' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <Box display=\"flex\" flex=\"1\" flexDirection=\"column\" gap=\"4\" minWidth=\"0\">\n <BitkitSwitchLabel icon={icon} label={label} state={state} tooltip={tooltip} optional={optional} />\n <BitkitSwitchHelperText state={state} helperText={helperText} />\n </Box>\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n </Switch.Root>\n );\n});\n\nBitkitSwitchFixed.displayName = 'BitkitSwitchFixed';\n\nconst BitkitSwitch = forwardRef<HTMLInputElement, BitkitSwitchProps>((props, ref) => {\n // At runtime (e.g. a shared Storybook meta) sibling-variant props may still flow in, so split them\n // off here and forward only what the chosen variant consumes — otherwise they leak to the DOM.\n const { variant, icon, tooltip, optional, valueText, helperText, ...rest } = props as BitkitSwitchAnyVariantProps;\n\n if (variant === 'dynamic-text') {\n return (\n <BitkitSwitchDynamicText\n ref={ref}\n tooltip={tooltip}\n optional={optional}\n valueText={valueText}\n helperText={helperText}\n {...rest}\n />\n );\n }\n\n if (variant === 'fixed') {\n return (\n <BitkitSwitchFixed\n ref={ref}\n icon={icon}\n tooltip={tooltip}\n optional={optional}\n helperText={helperText as ReactNode}\n {...rest}\n />\n );\n }\n\n return <BitkitSwitchDefault ref={ref} {...(rest as Omit<BitkitSwitchDefaultProps, 'variant'>)} />;\n});\n\nBitkitSwitch.displayName = 'BitkitSwitch';\n\nexport default BitkitSwitch;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BitkitSwitch.js","names":[],"sources":["../../../lib/components/BitkitSwitch/BitkitSwitch.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Switch } from '@chakra-ui/react/switch';\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { IconCheck, IconCross } from '../../icons';\nimport type {\n BitkitSwitchAnyVariantProps,\n BitkitSwitchDefaultProps,\n BitkitSwitchDynamicTextProps,\n BitkitSwitchFixedProps,\n BitkitSwitchProps,\n} from './BitkitSwitch.types';\nimport BitkitSwitchHelperText from './components/BitkitSwitchHelperText';\nimport BitkitSwitchLabel from './components/BitkitSwitchLabel';\nimport BitkitSwitchReadOnly from './components/BitkitSwitchReadOnly';\nimport BitkitSwitchValueText from './components/BitkitSwitchValueText';\n\nconst BitkitSwitchDefault = forwardRef<HTMLInputElement, Omit<BitkitSwitchDefaultProps, 'variant'>>((props, ref) => {\n const { hideLabel, label, size = 'lg', state = 'default', ...rest } = props;\n\n return (\n <Switch.Root\n size={size}\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n {/* `srOnly` rather than a hidden label passed in by the consumer: it positions the element\n absolutely, so it leaves the flex flow and the root's gap no longer reserves space for it. */}\n {label && <Switch.Label srOnly={hideLabel}>{label}</Switch.Label>}\n </Switch.Root>\n );\n});\n\nBitkitSwitchDefault.displayName = 'BitkitSwitchDefault';\n\nconst BitkitSwitchDynamicText = forwardRef<HTMLInputElement, Omit<BitkitSwitchDynamicTextProps, 'variant'>>(\n (props, ref) => {\n const { label, optional, tooltip, helperText, valueText, size = 'lg', state = 'default', ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'switch' });\n const styles = recipe({ size });\n\n return (\n <Switch.Root\n gap=\"4\"\n size={size}\n required={!optional}\n flexDirection=\"column\"\n alignItems=\"flex-start\"\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'disabledInput' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <BitkitSwitchLabel label={label} state={state} tooltip={tooltip} optional={optional} />\n <Box css={styles.root}>\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n <BitkitSwitchValueText size={size} state={state} valueText={valueText} />\n </Box>\n <BitkitSwitchHelperText state={state} helperText={helperText} />\n </Switch.Root>\n );\n },\n);\n\nBitkitSwitchDynamicText.displayName = 'BitkitSwitchDynamicText';\n\nconst BitkitSwitchFixed = forwardRef<HTMLInputElement, Omit<BitkitSwitchFixedProps, 'variant'>>((props, ref) => {\n const { icon, label, optional, tooltip, helperText, size = 'lg', state = 'default', ...rest } = props;\n\n return (\n <Switch.Root\n gap=\"24\"\n size={size}\n width=\"100%\"\n display=\"flex\"\n required={!optional}\n readOnly={state === 'readOnly'}\n disabled={state === 'disabled' || state === 'disabledInput' || state === 'skeleton'}\n {...rest}\n >\n <Switch.HiddenInput ref={ref} />\n <Box display=\"flex\" flex=\"1\" flexDirection=\"column\" gap=\"4\" minWidth=\"0\">\n <BitkitSwitchLabel icon={icon} label={label} state={state} tooltip={tooltip} optional={optional} />\n <BitkitSwitchHelperText state={state} helperText={helperText} />\n </Box>\n <BitkitSwitchReadOnly state={state}>\n <Skeleton loading={state === 'skeleton'} borderRadius=\"12\" height={size === 'md' ? '16' : '24'}>\n <Switch.Control>\n <Switch.Thumb />\n <Switch.Indicator fallback={<IconCross size={size === 'md' ? '16' : '24'} />}>\n <IconCheck size={size === 'md' ? '16' : '24'} />\n </Switch.Indicator>\n </Switch.Control>\n </Skeleton>\n </BitkitSwitchReadOnly>\n </Switch.Root>\n );\n});\n\nBitkitSwitchFixed.displayName = 'BitkitSwitchFixed';\n\nconst BitkitSwitch = forwardRef<HTMLInputElement, BitkitSwitchProps>((props, ref) => {\n // At runtime (e.g. a shared Storybook meta) sibling-variant props may still flow in, so split them\n // off here and forward only what the chosen variant consumes — otherwise they leak to the DOM.\n const { variant, hideLabel, icon, tooltip, optional, valueText, helperText, ...rest } =\n props as BitkitSwitchAnyVariantProps;\n\n if (variant === 'dynamic-text') {\n return (\n <BitkitSwitchDynamicText\n ref={ref}\n tooltip={tooltip}\n optional={optional}\n valueText={valueText}\n helperText={helperText}\n {...rest}\n />\n );\n }\n\n if (variant === 'fixed') {\n return (\n <BitkitSwitchFixed\n ref={ref}\n icon={icon}\n tooltip={tooltip}\n optional={optional}\n helperText={helperText as ReactNode}\n {...rest}\n />\n );\n }\n\n return (\n <BitkitSwitchDefault ref={ref} hideLabel={hideLabel} {...(rest as Omit<BitkitSwitchDefaultProps, 'variant'>)} />\n );\n});\n\nBitkitSwitch.displayName = 'BitkitSwitch';\n\nexport default BitkitSwitch;\n"],"mappings":";;;;;;;;;;;;;AAmBA,IAAM,sBAAsB,YAAyE,OAAO,QAAQ;CAClH,MAAM,EAAE,WAAW,OAAO,OAAO,MAAM,QAAQ,WAAW,GAAG,SAAS;CAEtE,OACE,qBAAC,OAAO,MAAR;EACQ;EACN,UAAU,UAAU;EACpB,UAAU,UAAU,cAAc,UAAU;EAC5C,GAAI;EAJN,UAAA;GAME,oBAAC,OAAO,aAAR,EAAyB,IAAM,CAAA;GAC/B,oBAAC,sBAAD;IAA6B;IAC3B,UAAA,oBAAC,UAAD;KAAU,SAAS,UAAU;KAAY,cAAa;KAAK,QAAQ,SAAS,OAAO,OAAO;KACxF,UAAA,qBAAC,OAAO,SAAR,EAAA,UAAA,CACE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,WAAR;MAAkB,UAAU,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;MACzE,UAAA,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;KAC/B,CAAA,CACJ,EAAA,CAAA;IACR,CAAA;GACU,CAAA;GAGrB,SAAS,oBAAC,OAAO,OAAR;IAAc,QAAQ;IAAY,UAAA;GAAoB,CAAA;EACrD;;AAEjB,CAAC;AAED,oBAAoB,cAAc;AAElC,IAAM,0BAA0B,YAC7B,OAAO,QAAQ;CACd,MAAM,EAAE,OAAO,UAAU,SAAS,YAAY,WAAW,OAAO,MAAM,QAAQ,WAAW,GAAG,SAAS;CAGrG,MAAM,SADS,cAAc,EAAE,KAAK,SAAS,CAC9B,CAAA,CAAO,EAAE,KAAK,CAAC;CAE9B,OACE,qBAAC,OAAO,MAAR;EACE,KAAI;EACE;EACN,UAAU,CAAC;EACX,eAAc;EACd,YAAW;EACX,UAAU,UAAU;EACpB,UAAU,UAAU,cAAc,UAAU,mBAAmB,UAAU;EACzE,GAAI;EARN,UAAA;GAUE,oBAAC,OAAO,aAAR,EAAyB,IAAM,CAAA;GAC/B,oBAAC,mBAAD;IAA0B;IAAc;IAAgB;IAAmB;GAAW,CAAA;GACtF,qBAAC,KAAD;IAAK,KAAK,OAAO;IAAjB,UAAA,CACE,oBAAC,sBAAD;KAA6B;KAC3B,UAAA,oBAAC,UAAD;MAAU,SAAS,UAAU;MAAY,cAAa;MAAK,QAAQ,SAAS,OAAO,OAAO;MACxF,UAAA,qBAAC,OAAO,SAAR,EAAA,UAAA,CACE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,WAAR;OAAkB,UAAU,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;OACzE,UAAA,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;MAC/B,CAAA,CACJ,EAAA,CAAA;KACR,CAAA;IACU,CAAA,GACtB,oBAAC,uBAAD;KAA6B;KAAa;KAAkB;IAAY,CAAA,CACrE;;GACL,oBAAC,wBAAD;IAA+B;IAAmB;GAAa,CAAA;EACpD;;AAEjB,CACF;AAEA,wBAAwB,cAAc;AAEtC,IAAM,oBAAoB,YAAuE,OAAO,QAAQ;CAC9G,MAAM,EAAE,MAAM,OAAO,UAAU,SAAS,YAAY,OAAO,MAAM,QAAQ,WAAW,GAAG,SAAS;CAEhG,OACE,qBAAC,OAAO,MAAR;EACE,KAAI;EACE;EACN,OAAM;EACN,SAAQ;EACR,UAAU,CAAC;EACX,UAAU,UAAU;EACpB,UAAU,UAAU,cAAc,UAAU,mBAAmB,UAAU;EACzE,GAAI;EARN,UAAA;GAUE,oBAAC,OAAO,aAAR,EAAyB,IAAM,CAAA;GAC/B,qBAAC,KAAD;IAAK,SAAQ;IAAO,MAAK;IAAI,eAAc;IAAS,KAAI;IAAI,UAAS;IAArE,UAAA,CACE,oBAAC,mBAAD;KAAyB;KAAa;KAAc;KAAgB;KAAmB;IAAW,CAAA,GAClG,oBAAC,wBAAD;KAA+B;KAAmB;IAAa,CAAA,CAC5D;;GACL,oBAAC,sBAAD;IAA6B;IAC3B,UAAA,oBAAC,UAAD;KAAU,SAAS,UAAU;KAAY,cAAa;KAAK,QAAQ,SAAS,OAAO,OAAO;KACxF,UAAA,qBAAC,OAAO,SAAR,EAAA,UAAA,CACE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,WAAR;MAAkB,UAAU,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;MACzE,UAAA,oBAAC,WAAD,EAAW,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA;KAC/B,CAAA,CACJ,EAAA,CAAA;IACR,CAAA;GACU,CAAA;EACX;;AAEjB,CAAC;AAED,kBAAkB,cAAc;AAEhC,IAAM,eAAe,YAAiD,OAAO,QAAQ;CAGnF,MAAM,EAAE,SAAS,WAAW,MAAM,SAAS,UAAU,WAAW,YAAY,GAAG,SAC7E;CAEF,IAAI,YAAY,gBACd,OACE,oBAAC,yBAAD;EACO;EACI;EACC;EACC;EACC;EACZ,GAAI;CACL,CAAA;CAIL,IAAI,YAAY,SACd,OACE,oBAAC,mBAAD;EACO;EACC;EACG;EACC;EACE;EACZ,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,qBAAD;EAA0B;EAAgB;EAAW,GAAK;CAAqD,CAAA;AAEnH,CAAC;AAED,aAAa,cAAc"}
@@ -7,6 +7,15 @@ export type OnOff = {
7
7
  };
8
8
  export interface BitkitSwitchDefaultProps extends Omit<SwitchRootProps, 'disabled' | 'label' | 'readOnly' | 'required'> {
9
9
  variant?: 'default';
10
+ /**
11
+ * Keeps the label as the switch's accessible name but takes it off the screen. The hidden input
12
+ * gets its name from a label element the switch owns, so neither `aria-label` nor `ids` can
13
+ * supply one from outside — this is how a switch with no visible text stays named.
14
+ *
15
+ * No effect without `label`, and that combination leaves the switch unnamed — the very thing
16
+ * this prop is here to avoid.
17
+ */
18
+ hideLabel?: boolean;
10
19
  label?: ReactNode;
11
20
  state?: 'default' | 'disabled' | 'readOnly' | 'skeleton';
12
21
  }
@@ -33,6 +42,7 @@ export interface BitkitSwitchFixedProps extends Omit<SwitchRootProps, 'disabled'
33
42
  export type BitkitSwitchProps = BitkitSwitchDefaultProps | BitkitSwitchDynamicTextProps | BitkitSwitchFixedProps;
34
43
  export type BitkitSwitchAnyVariantProps = Omit<SwitchRootProps, 'disabled' | 'label' | 'readOnly' | 'required'> & {
35
44
  variant?: BitkitSwitchProps['variant'];
45
+ hideLabel?: boolean;
36
46
  icon?: BitkitIconComponent;
37
47
  tooltip?: string;
38
48
  optional?: boolean;
@@ -8,9 +8,13 @@ export interface BitkitTextInputProps extends Omit<BitkitFieldProps, 'children'
8
8
  * known `value`.
9
9
  */
10
10
  counter?: boolean;
11
- /** Content attached to the trailing edge, outside the input border (e.g. a unit label or button). */
11
+ /**
12
+ * Content attached to the trailing edge, outside the input border. A string renders in the
13
+ * standard bordered addon box (a unit label like `USD`); any other node renders as itself — see
14
+ * `startAddon`.
15
+ */
12
16
  endAddon?: ReactNode;
13
- /** Props forwarded to the trailing `InputAddon` wrapper. */
17
+ /** Props forwarded to the trailing `InputAddon` box. Only a string addon has one. */
14
18
  endAddonProps?: InputAddonProps;
15
19
  /** Inline content rendered inside the input, at the trailing edge (e.g. an icon or reveal button). */
16
20
  endElement?: ReactNode;
@@ -33,9 +37,15 @@ export interface BitkitTextInputProps extends Omit<BitkitFieldProps, 'children'
33
37
  placeholder?: string;
34
38
  /** Field size — controls height and typography. */
35
39
  size?: 'md' | 'lg';
36
- /** Content attached to the leading edge, outside the input border (e.g. a unit label or button). */
40
+ /**
41
+ * Content attached to the leading edge, outside the input border. A string renders in the
42
+ * standard bordered addon box (a unit label like `$`); any other node keeps its own styling and
43
+ * is welded to the field instead — it shares the field's border and the corners it touches are
44
+ * squared automatically, so a `BitkitButton` / `BitkitIconButton` needs nothing but its own
45
+ * `size` and `variant`.
46
+ */
37
47
  startAddon?: ReactNode;
38
- /** Props forwarded to the leading `InputAddon` wrapper. */
48
+ /** Props forwarded to the leading `InputAddon` box. Only a string addon has one. */
39
49
  startAddonProps?: InputAddonProps;
40
50
  /** Inline content rendered inside the input, at the leading edge (e.g. an icon). */
41
51
  startElement?: ReactNode;
@@ -53,8 +63,9 @@ export interface BitkitTextInputProps extends Omit<BitkitFieldProps, 'children'
53
63
  /**
54
64
  * A single-line text field wrapping the native `<input>`, with a label and helper/error/warning
55
65
  * text. Reflect the value with `value` + `onValueChange` (or the native `onChange`); `inputProps` is
56
- * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border,
57
- * `startElement`/`endElement` inline inside it, and `counter` pairs with `maxLength`.
66
+ * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border
67
+ * (as a bordered box for text, welded to the field for a component), `startElement`/`endElement`
68
+ * inline inside it, and `counter` pairs with `maxLength`.
58
69
  */
59
70
  declare const BitkitTextInput: import('react').ForwardRefExoticComponent<BitkitTextInputProps & import('react').RefAttributes<HTMLDivElement>>;
60
71
  export default BitkitTextInput;
@@ -12,8 +12,9 @@ import { InputAddon } from "@chakra-ui/react/input-addon";
12
12
  /**
13
13
  * A single-line text field wrapping the native `<input>`, with a label and helper/error/warning
14
14
  * text. Reflect the value with `value` + `onValueChange` (or the native `onChange`); `inputProps` is
15
- * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border,
16
- * `startElement`/`endElement` inline inside it, and `counter` pairs with `maxLength`.
15
+ * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border
16
+ * (as a bordered box for text, welded to the field for a component), `startElement`/`endElement`
17
+ * inline inside it, and `counter` pairs with `maxLength`.
17
18
  */
18
19
  var BitkitTextInput = forwardRef((props, ref) => {
19
20
  const { counter, endAddon, endAddonProps, endElement, inputProps, maxLength, onChange, onValueChange, placeholder, size = "lg", startAddon, startAddonProps, startElement, state, value, ...rest } = props;
@@ -41,6 +42,13 @@ var BitkitTextInput = forwardRef((props, ref) => {
41
42
  "data-invalid": isInvalid ? "" : void 0,
42
43
  "data-readonly": state === "readOnly" ? "" : void 0
43
44
  };
45
+ const renderAddon = (addon, position, addonProps) => typeof addon === "string" || typeof addon === "number" ? /* @__PURE__ */ jsx(InputAddon, {
46
+ position,
47
+ size: addonSize,
48
+ ...stateAttrs,
49
+ ...addonProps,
50
+ children: addon
51
+ }) : addon;
44
52
  return /* @__PURE__ */ jsx(BitkitField, {
45
53
  counterText,
46
54
  ref,
@@ -50,13 +58,7 @@ var BitkitTextInput = forwardRef((props, ref) => {
50
58
  attached: true,
51
59
  width: "100%",
52
60
  children: [
53
- startAddon != null && /* @__PURE__ */ jsx(InputAddon, {
54
- position: "start",
55
- size: addonSize,
56
- ...stateAttrs,
57
- ...startAddonProps,
58
- children: startAddon
59
- }),
61
+ startAddon != null && renderAddon(startAddon, "start", startAddonProps),
60
62
  /* @__PURE__ */ jsxs(Box, {
61
63
  css: styles.field,
62
64
  "data-has-end-element": endElement != null ? "" : void 0,
@@ -89,13 +91,7 @@ var BitkitTextInput = forwardRef((props, ref) => {
89
91
  })
90
92
  ]
91
93
  }),
92
- endAddon != null && /* @__PURE__ */ jsx(InputAddon, {
93
- position: "end",
94
- size: addonSize,
95
- ...stateAttrs,
96
- ...endAddonProps,
97
- children: endAddon
98
- })
94
+ endAddon != null && renderAddon(endAddon, "end", endAddonProps)
99
95
  ]
100
96
  })
101
97
  });
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitTextInput.js","names":[],"sources":["../../../lib/components/BitkitTextInput/BitkitTextInput.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Group } from '@chakra-ui/react/group';\nimport { Input, type InputProps } from '@chakra-ui/react/input';\nimport { InputAddon, type InputAddonProps } from '@chakra-ui/react/input-addon';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { type ChangeEventHandler, forwardRef, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\n\nexport interface BitkitTextInputProps extends Omit<BitkitFieldProps, 'children' | 'onChange' | 'state' | 'value'> {\n /**\n * Show a live character counter (`length/maxLength`) next to the label. Requires `maxLength` and a\n * known `value`.\n */\n counter?: boolean;\n /** Content attached to the trailing edge, outside the input border (e.g. a unit label or button). */\n endAddon?: ReactNode;\n /** Props forwarded to the trailing `InputAddon` wrapper. */\n endAddonProps?: InputAddonProps;\n /** Inline content rendered inside the input, at the trailing edge (e.g. an icon or reveal button). */\n endElement?: ReactNode;\n /**\n * Escape hatch for the underlying Chakra `Input` — extra native attributes or a spread\n * `{...register()}`. On conflict, values here win over the top-level `value`/`onChange`.\n */\n inputProps?: InputProps;\n /** Maximum number of characters accepted; also feeds the optional `counter`. */\n maxLength?: HTMLInputElement['maxLength'];\n /**\n * Native change event — the same handler you could put on `inputProps`, promoted to the top level.\n * Reach for `onValueChange` when you only need the value. If both this and `inputProps.onChange` are\n * set, `inputProps.onChange` wins (it's the same event, so they shouldn't both be set).\n */\n onChange?: ChangeEventHandler<HTMLInputElement>;\n /** Convenience change handler that receives the value directly, without `event.target.value`. */\n onValueChange?: (value: string) => void;\n /** Placeholder text shown while the field is empty. */\n placeholder?: string;\n /** Field size — controls height and typography. */\n size?: 'md' | 'lg';\n /** Content attached to the leading edge, outside the input border (e.g. a unit label or button). */\n startAddon?: ReactNode;\n /** Props forwarded to the leading `InputAddon` wrapper. */\n startAddonProps?: InputAddonProps;\n /** Inline content rendered inside the input, at the leading edge (e.g. an icon). */\n startElement?: ReactNode;\n /**\n * Field state. `error`/`warning` are also implied by `errorText`/`warningText`; `disabled` and\n * `readOnly` gate interaction.\n */\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n /**\n * Controlled value. Pair with `onValueChange` or `onChange`. Can also be supplied via `inputProps`,\n * which wins on conflict.\n */\n value?: string;\n}\n\n/**\n * A single-line text field wrapping the native `<input>`, with a label and helper/error/warning\n * text. Reflect the value with `value` + `onValueChange` (or the native `onChange`); `inputProps` is\n * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border,\n * `startElement`/`endElement` inline inside it, and `counter` pairs with `maxLength`.\n */\nconst BitkitTextInput = forwardRef<HTMLDivElement, BitkitTextInputProps>((props, ref) => {\n const {\n counter,\n endAddon,\n endAddonProps,\n endElement,\n inputProps,\n maxLength,\n onChange,\n onValueChange,\n placeholder,\n size = 'lg',\n startAddon,\n startAddonProps,\n startElement,\n state,\n value,\n ...rest\n } = props;\n\n const recipe = useSlotRecipe({ key: 'textInput' });\n const styles = recipe({ size });\n\n const iconSize = size === 'md' ? '16' : '24';\n const addonSize = size === 'md' ? 'md' : 'lg';\n\n const hasWarning = state === 'warning' || !!rest.warningText;\n const isInvalid = state === 'error' || !!rest.errorText;\n\n let statusIcon: ReactNode = null;\n if (isInvalid) {\n statusIcon = <IconErrorCircleFilled color=\"icon/negative\" size={iconSize} />;\n } else if (hasWarning) {\n statusIcon = <IconWarningYellow size={iconSize} />;\n }\n\n // `value` / `onChange` may come in at the top level or via `inputProps` — the object wins on\n // conflict (natural for a spread `{...register()}`). `onValueChange` always fires with the value.\n const { css: inputCss, onChange: inputOnChange, value: inputValue, ...restInputProps } = inputProps ?? {};\n const resolvedValue = inputValue ?? value;\n const nativeOnChange = inputOnChange ?? onChange;\n const handleChange: ChangeEventHandler<HTMLInputElement> | undefined =\n onValueChange || nativeOnChange\n ? (event) => {\n onValueChange?.(event.target.value);\n nativeOnChange?.(event);\n }\n : undefined;\n\n const counterText =\n counter && maxLength && resolvedValue !== undefined ? `${resolvedValue.toString().length}/${maxLength}` : undefined;\n\n const stateAttrs = {\n 'data-disabled': state === 'disabled' ? '' : undefined,\n 'data-invalid': isInvalid ? '' : undefined,\n 'data-readonly': state === 'readOnly' ? '' : undefined,\n };\n\n return (\n <BitkitField counterText={counterText} ref={ref} state={state} {...rest}>\n <Group attached width=\"100%\">\n {startAddon != null && (\n <InputAddon position=\"start\" size={addonSize} {...stateAttrs} {...startAddonProps}>\n {startAddon}\n </InputAddon>\n )}\n <Box css={styles.field} data-has-end-element={endElement != null ? '' : undefined} flex=\"1\" {...stateAttrs}>\n {startElement != null && (\n <Box css={styles.element} {...stateAttrs}>\n {startElement}\n </Box>\n )}\n <Input\n css={[styles.input, inputCss]}\n maxLength={maxLength}\n onChange={handleChange}\n placeholder={placeholder}\n value={resolvedValue}\n {...restInputProps}\n unstyled\n />\n {statusIcon != null && (\n <Box css={styles.element} {...stateAttrs}>\n {statusIcon}\n </Box>\n )}\n {endElement != null && (\n <Box css={styles.element} {...stateAttrs}>\n {endElement}\n </Box>\n )}\n </Box>\n {endAddon != null && (\n <InputAddon position=\"end\" size={addonSize} {...stateAttrs} {...endAddonProps}>\n {endAddon}\n </InputAddon>\n )}\n </Group>\n </BitkitField>\n );\n});\n\nBitkitTextInput.displayName = 'BitkitTextInput';\n\nexport default BitkitTextInput;\n"],"mappings":";;;;;;;;;;;;;;;;;AAiEA,IAAM,kBAAkB,YAAkD,OAAO,QAAQ;CACvF,MAAM,EACJ,SACA,UACA,eACA,YACA,YACA,WACA,UACA,eACA,aACA,OAAO,MACP,YACA,iBACA,cACA,OACA,OACA,GAAG,SACD;CAGJ,MAAM,SADS,cAAc,EAAE,KAAK,YAAY,CACjC,CAAA,CAAO,EAAE,KAAK,CAAC;CAE9B,MAAM,WAAW,SAAS,OAAO,OAAO;CACxC,MAAM,YAAY,SAAS,OAAO,OAAO;CAEzC,MAAM,aAAa,UAAU,aAAa,CAAC,CAAC,KAAK;CACjD,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,KAAK;CAE9C,IAAI,aAAwB;CAC5B,IAAI,WACF,aAAa,oBAAC,uBAAD;EAAuB,OAAM;EAAgB,MAAM;CAAW,CAAA;MACtE,IAAI,YACT,aAAa,oBAAC,mBAAD,EAAmB,MAAM,SAAW,CAAA;CAKnD,MAAM,EAAE,KAAK,UAAU,UAAU,eAAe,OAAO,YAAY,GAAG,mBAAmB,cAAc,CAAC;CACxG,MAAM,gBAAgB,cAAc;CACpC,MAAM,iBAAiB,iBAAiB;CACxC,MAAM,eACJ,iBAAiB,kBACZ,UAAU;EACT,gBAAgB,MAAM,OAAO,KAAK;EAClC,iBAAiB,KAAK;CACxB,IACA,KAAA;CAEN,MAAM,cACJ,WAAW,aAAa,kBAAkB,KAAA,IAAY,GAAG,cAAc,SAAS,CAAC,CAAC,OAAO,GAAG,cAAc,KAAA;CAE5G,MAAM,aAAa;EACjB,iBAAiB,UAAU,aAAa,KAAK,KAAA;EAC7C,gBAAgB,YAAY,KAAK,KAAA;EACjC,iBAAiB,UAAU,aAAa,KAAK,KAAA;CAC/C;CAEA,OACE,oBAAC,aAAD;EAA0B;EAAkB;EAAY;EAAO,GAAI;EACjE,UAAA,qBAAC,OAAD;GAAO,UAAA;GAAS,OAAM;GAAtB,UAAA;IACG,cAAc,QACb,oBAAC,YAAD;KAAY,UAAS;KAAQ,MAAM;KAAW,GAAI;KAAY,GAAI;KAC/D,UAAA;IACS,CAAA;IAEd,qBAAC,KAAD;KAAK,KAAK,OAAO;KAAO,wBAAsB,cAAc,OAAO,KAAK,KAAA;KAAW,MAAK;KAAI,GAAI;KAAhG,UAAA;MACG,gBAAgB,QACf,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;MAEP,oBAAC,OAAD;OACE,KAAK,CAAC,OAAO,OAAO,QAAQ;OACjB;OACX,UAAU;OACG;OACb,OAAO;OACP,GAAI;OACJ,UAAA;MACD,CAAA;MACA,cAAc,QACb,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;MAEN,cAAc,QACb,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;KAEJ;;IACJ,YAAY,QACX,oBAAC,YAAD;KAAY,UAAS;KAAM,MAAM;KAAW,GAAI;KAAY,GAAI;KAC7D,UAAA;IACS,CAAA;GAET;;CACI,CAAA;AAEjB,CAAC;AAED,gBAAgB,cAAc"}
1
+ {"version":3,"file":"BitkitTextInput.js","names":[],"sources":["../../../lib/components/BitkitTextInput/BitkitTextInput.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Group } from '@chakra-ui/react/group';\nimport { Input, type InputProps } from '@chakra-ui/react/input';\nimport { InputAddon, type InputAddonProps } from '@chakra-ui/react/input-addon';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { type ChangeEventHandler, forwardRef, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\n\nexport interface BitkitTextInputProps extends Omit<BitkitFieldProps, 'children' | 'onChange' | 'state' | 'value'> {\n /**\n * Show a live character counter (`length/maxLength`) next to the label. Requires `maxLength` and a\n * known `value`.\n */\n counter?: boolean;\n /**\n * Content attached to the trailing edge, outside the input border. A string renders in the\n * standard bordered addon box (a unit label like `USD`); any other node renders as itself — see\n * `startAddon`.\n */\n endAddon?: ReactNode;\n /** Props forwarded to the trailing `InputAddon` box. Only a string addon has one. */\n endAddonProps?: InputAddonProps;\n /** Inline content rendered inside the input, at the trailing edge (e.g. an icon or reveal button). */\n endElement?: ReactNode;\n /**\n * Escape hatch for the underlying Chakra `Input` — extra native attributes or a spread\n * `{...register()}`. On conflict, values here win over the top-level `value`/`onChange`.\n */\n inputProps?: InputProps;\n /** Maximum number of characters accepted; also feeds the optional `counter`. */\n maxLength?: HTMLInputElement['maxLength'];\n /**\n * Native change event — the same handler you could put on `inputProps`, promoted to the top level.\n * Reach for `onValueChange` when you only need the value. If both this and `inputProps.onChange` are\n * set, `inputProps.onChange` wins (it's the same event, so they shouldn't both be set).\n */\n onChange?: ChangeEventHandler<HTMLInputElement>;\n /** Convenience change handler that receives the value directly, without `event.target.value`. */\n onValueChange?: (value: string) => void;\n /** Placeholder text shown while the field is empty. */\n placeholder?: string;\n /** Field size — controls height and typography. */\n size?: 'md' | 'lg';\n /**\n * Content attached to the leading edge, outside the input border. A string renders in the\n * standard bordered addon box (a unit label like `$`); any other node keeps its own styling and\n * is welded to the field instead — it shares the field's border and the corners it touches are\n * squared automatically, so a `BitkitButton` / `BitkitIconButton` needs nothing but its own\n * `size` and `variant`.\n */\n startAddon?: ReactNode;\n /** Props forwarded to the leading `InputAddon` box. Only a string addon has one. */\n startAddonProps?: InputAddonProps;\n /** Inline content rendered inside the input, at the leading edge (e.g. an icon). */\n startElement?: ReactNode;\n /**\n * Field state. `error`/`warning` are also implied by `errorText`/`warningText`; `disabled` and\n * `readOnly` gate interaction.\n */\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n /**\n * Controlled value. Pair with `onValueChange` or `onChange`. Can also be supplied via `inputProps`,\n * which wins on conflict.\n */\n value?: string;\n}\n\n/**\n * A single-line text field wrapping the native `<input>`, with a label and helper/error/warning\n * text. Reflect the value with `value` + `onValueChange` (or the native `onChange`); `inputProps` is\n * the escape hatch for any other native attribute. `startAddon`/`endAddon` sit outside the border\n * (as a bordered box for text, welded to the field for a component), `startElement`/`endElement`\n * inline inside it, and `counter` pairs with `maxLength`.\n */\nconst BitkitTextInput = forwardRef<HTMLDivElement, BitkitTextInputProps>((props, ref) => {\n const {\n counter,\n endAddon,\n endAddonProps,\n endElement,\n inputProps,\n maxLength,\n onChange,\n onValueChange,\n placeholder,\n size = 'lg',\n startAddon,\n startAddonProps,\n startElement,\n state,\n value,\n ...rest\n } = props;\n\n const recipe = useSlotRecipe({ key: 'textInput' });\n const styles = recipe({ size });\n\n const iconSize = size === 'md' ? '16' : '24';\n const addonSize = size === 'md' ? 'md' : 'lg';\n\n const hasWarning = state === 'warning' || !!rest.warningText;\n const isInvalid = state === 'error' || !!rest.errorText;\n\n let statusIcon: ReactNode = null;\n if (isInvalid) {\n statusIcon = <IconErrorCircleFilled color=\"icon/negative\" size={iconSize} />;\n } else if (hasWarning) {\n statusIcon = <IconWarningYellow size={iconSize} />;\n }\n\n // `value` / `onChange` may come in at the top level or via `inputProps` — the object wins on\n // conflict (natural for a spread `{...register()}`). `onValueChange` always fires with the value.\n const { css: inputCss, onChange: inputOnChange, value: inputValue, ...restInputProps } = inputProps ?? {};\n const resolvedValue = inputValue ?? value;\n const nativeOnChange = inputOnChange ?? onChange;\n const handleChange: ChangeEventHandler<HTMLInputElement> | undefined =\n onValueChange || nativeOnChange\n ? (event) => {\n onValueChange?.(event.target.value);\n nativeOnChange?.(event);\n }\n : undefined;\n\n const counterText =\n counter && maxLength && resolvedValue !== undefined ? `${resolvedValue.toString().length}/${maxLength}` : undefined;\n\n const stateAttrs = {\n 'data-disabled': state === 'disabled' ? '' : undefined,\n 'data-invalid': isInvalid ? '' : undefined,\n 'data-readonly': state === 'readOnly' ? '' : undefined,\n };\n\n const renderAddon = (addon: ReactNode, position: 'end' | 'start', addonProps?: InputAddonProps) =>\n typeof addon === 'string' || typeof addon === 'number' ? (\n <InputAddon position={position} size={addonSize} {...stateAttrs} {...addonProps}>\n {addon}\n </InputAddon>\n ) : (\n addon\n );\n\n return (\n <BitkitField counterText={counterText} ref={ref} state={state} {...rest}>\n <Group attached width=\"100%\">\n {startAddon != null && renderAddon(startAddon, 'start', startAddonProps)}\n <Box css={styles.field} data-has-end-element={endElement != null ? '' : undefined} flex=\"1\" {...stateAttrs}>\n {startElement != null && (\n <Box css={styles.element} {...stateAttrs}>\n {startElement}\n </Box>\n )}\n <Input\n css={[styles.input, inputCss]}\n maxLength={maxLength}\n onChange={handleChange}\n placeholder={placeholder}\n value={resolvedValue}\n {...restInputProps}\n unstyled\n />\n {statusIcon != null && (\n <Box css={styles.element} {...stateAttrs}>\n {statusIcon}\n </Box>\n )}\n {endElement != null && (\n <Box css={styles.element} {...stateAttrs}>\n {endElement}\n </Box>\n )}\n </Box>\n {endAddon != null && renderAddon(endAddon, 'end', endAddonProps)}\n </Group>\n </BitkitField>\n );\n});\n\nBitkitTextInput.displayName = 'BitkitTextInput';\n\nexport default BitkitTextInput;\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4EA,IAAM,kBAAkB,YAAkD,OAAO,QAAQ;CACvF,MAAM,EACJ,SACA,UACA,eACA,YACA,YACA,WACA,UACA,eACA,aACA,OAAO,MACP,YACA,iBACA,cACA,OACA,OACA,GAAG,SACD;CAGJ,MAAM,SADS,cAAc,EAAE,KAAK,YAAY,CACjC,CAAA,CAAO,EAAE,KAAK,CAAC;CAE9B,MAAM,WAAW,SAAS,OAAO,OAAO;CACxC,MAAM,YAAY,SAAS,OAAO,OAAO;CAEzC,MAAM,aAAa,UAAU,aAAa,CAAC,CAAC,KAAK;CACjD,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,KAAK;CAE9C,IAAI,aAAwB;CAC5B,IAAI,WACF,aAAa,oBAAC,uBAAD;EAAuB,OAAM;EAAgB,MAAM;CAAW,CAAA;MACtE,IAAI,YACT,aAAa,oBAAC,mBAAD,EAAmB,MAAM,SAAW,CAAA;CAKnD,MAAM,EAAE,KAAK,UAAU,UAAU,eAAe,OAAO,YAAY,GAAG,mBAAmB,cAAc,CAAC;CACxG,MAAM,gBAAgB,cAAc;CACpC,MAAM,iBAAiB,iBAAiB;CACxC,MAAM,eACJ,iBAAiB,kBACZ,UAAU;EACT,gBAAgB,MAAM,OAAO,KAAK;EAClC,iBAAiB,KAAK;CACxB,IACA,KAAA;CAEN,MAAM,cACJ,WAAW,aAAa,kBAAkB,KAAA,IAAY,GAAG,cAAc,SAAS,CAAC,CAAC,OAAO,GAAG,cAAc,KAAA;CAE5G,MAAM,aAAa;EACjB,iBAAiB,UAAU,aAAa,KAAK,KAAA;EAC7C,gBAAgB,YAAY,KAAK,KAAA;EACjC,iBAAiB,UAAU,aAAa,KAAK,KAAA;CAC/C;CAEA,MAAM,eAAe,OAAkB,UAA2B,eAChE,OAAO,UAAU,YAAY,OAAO,UAAU,WAC5C,oBAAC,YAAD;EAAsB;EAAU,MAAM;EAAW,GAAI;EAAY,GAAI;EAClE,UAAA;CACS,CAAA,IAEZ;CAGJ,OACE,oBAAC,aAAD;EAA0B;EAAkB;EAAY;EAAO,GAAI;EACjE,UAAA,qBAAC,OAAD;GAAO,UAAA;GAAS,OAAM;GAAtB,UAAA;IACG,cAAc,QAAQ,YAAY,YAAY,SAAS,eAAe;IACvE,qBAAC,KAAD;KAAK,KAAK,OAAO;KAAO,wBAAsB,cAAc,OAAO,KAAK,KAAA;KAAW,MAAK;KAAI,GAAI;KAAhG,UAAA;MACG,gBAAgB,QACf,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;MAEP,oBAAC,OAAD;OACE,KAAK,CAAC,OAAO,OAAO,QAAQ;OACjB;OACX,UAAU;OACG;OACb,OAAO;OACP,GAAI;OACJ,UAAA;MACD,CAAA;MACA,cAAc,QACb,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;MAEN,cAAc,QACb,oBAAC,KAAD;OAAK,KAAK,OAAO;OAAS,GAAI;OAC3B,UAAA;MACE,CAAA;KAEJ;;IACJ,YAAY,QAAQ,YAAY,UAAU,OAAO,aAAa;GAC1D;;CACI,CAAA;AAEjB,CAAC;AAED,gBAAgB,cAAc"}
@@ -50,7 +50,7 @@ export { default as BitkitOverflowContent, type BitkitOverflowContentProps, } fr
50
50
  export { default as BitkitOverflowTooltip, type BitkitOverflowTooltipProps, } from './BitkitOverflowTooltip/BitkitOverflowTooltip';
51
51
  export { default as BitkitPageFooter, type BitkitPageFooterItemProps, type BitkitPageFooterProps, } from './BitkitPageFooter/BitkitPageFooter';
52
52
  export { default as BitkitPageHeader, type BitkitPageHeaderProps } from './BitkitPageHeader/BitkitPageHeader';
53
- export { default as BitkitPageSidebar, type BitkitPageSidebarBodyProps, type BitkitPageSidebarDividerProps, type BitkitPageSidebarFooterProps, type BitkitPageSidebarGroupHeadingProps, type BitkitPageSidebarItemProps, type BitkitPageSidebarProjectProps, type BitkitPageSidebarProps, type BitkitPageSidebarTitleProps, } from './BitkitPageSidebar/BitkitPageSidebar';
53
+ export { default as BitkitPageSidebar, type BitkitPageSidebarBodyProps, type BitkitPageSidebarDividerProps, type BitkitPageSidebarFooterProps, type BitkitPageSidebarGroupHeadingProps, type BitkitPageSidebarItemProps, type BitkitPageSidebarProgressItemProps, type BitkitPageSidebarProjectProps, type BitkitPageSidebarProps, type BitkitPageSidebarTitleProps, } from './BitkitPageSidebar/BitkitPageSidebar';
54
54
  export { default as BitkitPagination, type BitkitPaginationLabels, type BitkitPaginationProps, } from './BitkitPagination/BitkitPagination';
55
55
  export { default as BitkitPaginationLoadMore, type BitkitPaginationLoadMoreProps, } from './BitkitPaginationLoadMore/BitkitPaginationLoadMore';
56
56
  export { default as BitkitPopover, type BitkitPopoverProps } from './BitkitPopover/BitkitPopover';
@@ -1,4 +1,4 @@
1
- declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "titleText" | "suffixIcon" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "divider" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
1
+ declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "titleText" | "suffixIcon" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "divider" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
2
2
  hasBack: {
3
3
  true: {
4
4
  title: {
@@ -43,6 +43,18 @@ declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefini
43
43
  itemLabel: {
44
44
  color: "text/disabled";
45
45
  };
46
+ progressIcon: {
47
+ color: "icon/disabled";
48
+ _groupHover: {
49
+ color: "icon/disabled";
50
+ };
51
+ };
52
+ progressLabel: {
53
+ color: "text/disabled";
54
+ };
55
+ progressSecondaryText: {
56
+ color: "text/disabled";
57
+ };
46
58
  };
47
59
  false: {};
48
60
  };
@@ -78,6 +90,44 @@ declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefini
78
90
  tablet: "body/md/semibold";
79
91
  };
80
92
  };
93
+ progressIcon: {
94
+ color: "icon/interactive";
95
+ _groupHover: {
96
+ color: "icon/interactive-hover";
97
+ };
98
+ };
99
+ progressLabel: {
100
+ textStyle: {
101
+ base: "body/lg/semibold";
102
+ tablet: "body/md/semibold";
103
+ };
104
+ };
105
+ };
106
+ false: {};
107
+ };
108
+ /**
109
+ * A stage the release does not have to clear. Everything steps down one level -- the icon to
110
+ * tertiary, the label to secondary -- so the row reads as present but not awaited. Hover and
111
+ * active take both back to the row's ordinary colours, as they do for a required stage.
112
+ *
113
+ * `selected` wins over it, resolved in the component rather than here. The design draws the
114
+ * pair (`selected=yes, notRequired=true`) and gives it the selected row's icon and label with
115
+ * the `not required` secondary text kept, which is what dropping this variant produces.
116
+ */
117
+ notRequired: {
118
+ true: {
119
+ progressIcon: {
120
+ color: "icon/tertiary";
121
+ _groupHover: {
122
+ color: "icon/primary";
123
+ };
124
+ };
125
+ progressLabel: {
126
+ color: "text/secondary";
127
+ _groupHover: {
128
+ color: "text/primary";
129
+ };
130
+ };
81
131
  };
82
132
  false: {};
83
133
  };
@@ -11,6 +11,14 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
11
11
  "item",
12
12
  "itemIcon",
13
13
  "itemLabel",
14
+ "progressBlocker",
15
+ "progressConnector",
16
+ "progressContentBlock",
17
+ "progressIcon",
18
+ "progressLabel",
19
+ "progressRow",
20
+ "progressSecondaryText",
21
+ "progressTextBlock",
14
22
  "project",
15
23
  "projectLabel",
16
24
  "projectValue",
@@ -46,7 +54,7 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
46
54
  display: "flex",
47
55
  flex: 1,
48
56
  flexDirection: "column",
49
- marginBlockEnd: "16",
57
+ marginBlockEnd: "8",
50
58
  width: "full"
51
59
  },
52
60
  title: {
@@ -154,8 +162,86 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
154
162
  display: "flex",
155
163
  flexDirection: "column",
156
164
  flexShrink: 0,
165
+ marginBlockStart: "8",
157
166
  paddingBlock: "8"
158
167
  },
168
+ /**
169
+ * The progress item's own text, rather than `itemLabel`: that slot grows to fill the row, which
170
+ * here belongs to the blocker so the connector can run to the trailing edge.
171
+ */
172
+ progressLabel: {
173
+ color: "text/primary",
174
+ minWidth: 0,
175
+ overflow: "hidden",
176
+ textOverflow: "ellipsis",
177
+ textStyle: {
178
+ base: "body/lg/regular",
179
+ tablet: "body/md/regular"
180
+ },
181
+ whiteSpace: "nowrap"
182
+ },
183
+ /** Follows the label after a middle dot, which the component renders. */
184
+ progressSecondaryText: {
185
+ color: "text/tertiary",
186
+ flexShrink: 0,
187
+ textStyle: {
188
+ base: "body/lg/regular",
189
+ tablet: "body/md/regular"
190
+ },
191
+ whiteSpace: "nowrap"
192
+ },
193
+ /**
194
+ * Badge and connector as one unit, taking the width the text leaves.
195
+ *
196
+ * `fit-content` rather than 0: the flex basis is 0, so with a shrinking text block beside it
197
+ * there is no free space to grow into and the block would be handed the whole row -- leaving
198
+ * the badge, which does not shrink, hanging off the trailing edge. The floor is the badge; the
199
+ * connector inside is basis 0 and contributes nothing to it.
200
+ */
201
+ progressBlocker: {
202
+ alignItems: "center",
203
+ display: "flex",
204
+ flex: 1,
205
+ gap: "12",
206
+ minWidth: "fit-content"
207
+ },
208
+ /**
209
+ * The status icon's own slot rather than `itemIcon`: that one brightens to `icon/primary` with
210
+ * the row, which is right for navigation and wrong here -- hovering a stage would drop the
211
+ * colour that says where it stands.
212
+ */
213
+ progressIcon: {
214
+ color: "icon/secondary",
215
+ flexShrink: 0,
216
+ _groupHover: { color: "icon/primary" }
217
+ },
218
+ /**
219
+ * Label and secondary text read as one line, so they sit closer than the row's own 12 gap.
220
+ *
221
+ * It shrinks before the blocker does: `item` clips its overflow, so without this a long stage
222
+ * name is cut mid-word and pushes the secondary text and the connector off the row. The
223
+ * blocker keeps `flex: 1`, so it still takes the slack whenever the text is short enough.
224
+ */
225
+ progressTextBlock: {
226
+ alignItems: "center",
227
+ display: "flex",
228
+ flexShrink: 1,
229
+ gap: "4",
230
+ minWidth: 0
231
+ },
232
+ /**
233
+ * The progress row's block padding, which does not follow the navigation row's to 12 on mobile:
234
+ * the design keeps this row on 8 at both widths, so it is 44 tall on mobile against a nav row's
235
+ * 48. Layered over `item` rather than replacing it -- everything else about the row is shared.
236
+ */
237
+ progressRow: { paddingBlock: "8" },
238
+ /** With the row above: 2 either side of the line box at both widths, so the block is 28. */
239
+ progressContentBlock: { paddingBlock: "2" },
240
+ progressConnector: {
241
+ borderColor: "border/minimal",
242
+ borderStyle: "dashed",
243
+ flex: 1
244
+ },
159
245
  project: {
160
246
  display: "flex",
161
247
  flexDirection: "column",
@@ -232,7 +318,13 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
232
318
  color: "icon/disabled",
233
319
  _groupHover: { color: "icon/disabled" }
234
320
  },
235
- itemLabel: { color: "text/disabled" }
321
+ itemLabel: { color: "text/disabled" },
322
+ progressIcon: {
323
+ color: "icon/disabled",
324
+ _groupHover: { color: "icon/disabled" }
325
+ },
326
+ progressLabel: { color: "text/disabled" },
327
+ progressSecondaryText: { color: "text/disabled" }
236
328
  },
237
329
  false: {}
238
330
  },
@@ -259,14 +351,45 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
259
351
  itemLabel: { textStyle: {
260
352
  base: "body/lg/semibold",
261
353
  tablet: "body/md/semibold"
354
+ } },
355
+ progressIcon: {
356
+ color: "icon/interactive",
357
+ _groupHover: { color: "icon/interactive-hover" }
358
+ },
359
+ progressLabel: { textStyle: {
360
+ base: "body/lg/semibold",
361
+ tablet: "body/md/semibold"
262
362
  } }
263
363
  },
264
364
  false: {}
365
+ },
366
+ /**
367
+ * A stage the release does not have to clear. Everything steps down one level -- the icon to
368
+ * tertiary, the label to secondary -- so the row reads as present but not awaited. Hover and
369
+ * active take both back to the row's ordinary colours, as they do for a required stage.
370
+ *
371
+ * `selected` wins over it, resolved in the component rather than here. The design draws the
372
+ * pair (`selected=yes, notRequired=true`) and gives it the selected row's icon and label with
373
+ * the `not required` secondary text kept, which is what dropping this variant produces.
374
+ */
375
+ notRequired: {
376
+ true: {
377
+ progressIcon: {
378
+ color: "icon/tertiary",
379
+ _groupHover: { color: "icon/primary" }
380
+ },
381
+ progressLabel: {
382
+ color: "text/secondary",
383
+ _groupHover: { color: "text/primary" }
384
+ }
385
+ },
386
+ false: {}
265
387
  }
266
388
  },
267
389
  defaultVariants: {
268
390
  hasBack: false,
269
391
  isDisabled: false,
392
+ notRequired: false,
270
393
  selected: false
271
394
  }
272
395
  });
@@ -1 +1 @@
1
- {"version":3,"file":"PageSidebar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/PageSidebar.recipe.ts"],"sourcesContent":["import { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nconst pageSidebarSlotRecipe = defineSlotRecipe({\n className: 'page-sidebar',\n slots: [\n 'body',\n 'contentBlock',\n 'divider',\n 'footer',\n 'item',\n 'itemIcon',\n 'itemLabel',\n 'project',\n 'projectLabel',\n 'projectValue',\n 'projectValueWrapper',\n 'root',\n 'selectionMarker',\n 'suffixIcon',\n 'title',\n 'titleBlock',\n 'titleText',\n ],\n base: {\n root: {\n background: 'background/primary',\n // Longhands, not the `borderInlineEnd: '1px solid'` shorthand: that shorthand carries no\n // colour, so it resets it to `currentColor` if it lands after `borderColor` — which is what\n // sorting these keys alphabetically did, turning the rule dark.\n borderInlineEndColor: 'border/regular',\n borderInlineEndStyle: 'solid',\n borderInlineEndWidth: '1',\n display: 'flex',\n flexDirection: 'column',\n // `minHeight` rather than `height`: on a short navigation the sidebar still reaches the\n // bottom of the viewport, but a long one grows past it and scrolls with the page as one\n // block — the footer is part of that scroll, not pinned to the bottom.\n minHeight: '100dvh',\n // Below `tablet` the sidebar is the whole view — Figma's mobile frame (`23056:50745`) is the\n // full 375 of the phone, not a 240 column beside a page.\n maxWidth: { base: 'none', tablet: rem(320) },\n minWidth: rem(240),\n paddingBlockStart: '16',\n width: { base: 'full', tablet: rem(240) },\n },\n body: {\n display: 'flex',\n // Absorbs the slack so the footer sits at the bottom when the navigation is short, and\n // simply grows when it is long.\n flex: 1,\n flexDirection: 'column',\n // The minimum gap between the navigation and the footer block. It is a margin so it stays\n // outside the items' own box, and `flex: 1` above means any extra space lands in the body\n // rather than widening this gap.\n marginBlockEnd: '16',\n width: 'full',\n },\n title: {\n alignItems: 'center',\n color: 'text/primary',\n display: 'flex',\n flexShrink: 0,\n overflow: 'clip',\n paddingInlineEnd: '32',\n },\n titleBlock: {\n alignItems: 'center',\n display: 'flex',\n minWidth: 0,\n },\n titleText: {\n textStyle: 'heading/h3',\n whiteSpace: 'nowrap',\n },\n item: {\n alignItems: 'center',\n cursor: 'pointer',\n display: 'flex',\n focusVisibleRing: 'inside',\n gap: '12',\n overflow: 'clip',\n // 48 tall on mobile against 40 on desktop — the row is a touch target there.\n paddingBlock: { base: '12', tablet: '8' },\n paddingInline: '24',\n position: 'relative',\n width: 'full',\n // Mobile reaches for `background/hover` / `background/active` where desktop uses the\n // `secondary` / `tertiary` surfaces. The two happen to resolve close, but they are separate\n // tokens in the design and the mobile item (`9221:4406`) binds these.\n _hover: {\n background: { base: 'background/hover', tablet: 'background/secondary' },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n // `focusVisibleRing: 'inside'` still resolves to `outline-offset: 0`, which draws the ring\n // just outside the border box. The item spans the sidebar's full width, so that would bleed\n // past the sidebar's edges — pull the whole ring inside the item instead.\n _focusVisible: {\n outlineOffset: 'calc(var(--focus-ring-width) * -1)',\n },\n },\n contentBlock: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 0,\n // Pads the 16px icon out to the 24px line box on desktop. The mobile icon is already 24, so\n // there is nothing to make up — the row would just grow past 48.\n paddingBlock: { base: '0', tablet: '2' },\n },\n itemIcon: {\n color: 'icon/secondary',\n flexShrink: 0,\n _groupHover: {\n color: 'icon/primary',\n },\n },\n itemLabel: {\n color: 'text/primary',\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textAlign: 'start',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n suffixIcon: {\n color: 'icon/tertiary',\n flexShrink: 0,\n },\n selectionMarker: {\n background: 'border/selected',\n // Mobile draws the marker as a plain 4px edge (`9221:4417`); desktop as a 2px rounded rule.\n borderEndStartRadius: { base: '0', tablet: '2' },\n borderStartStartRadius: { base: '0', tablet: '2' },\n height: 'full',\n insetBlockStart: 0,\n insetInlineEnd: 0,\n position: 'absolute',\n width: { base: '4', tablet: '2' },\n },\n footer: {\n borderBlockStart: '1px solid',\n borderColor: 'border/minimal',\n display: 'flex',\n flexDirection: 'column',\n // The body above absorbs the free space, so the footer needs no positioning of its own —\n // it just must not be squashed by a long list.\n flexShrink: 0,\n paddingBlock: '8',\n },\n project: {\n display: 'flex',\n flexDirection: 'column',\n gap: '4',\n justifyContent: 'center',\n overflow: 'clip',\n paddingBlockEnd: { base: '12', tablet: '8' },\n paddingBlockStart: '8',\n paddingInlineEnd: { base: '24', tablet: '32' },\n paddingInlineStart: '24',\n whiteSpace: 'nowrap',\n },\n projectLabel: {\n color: 'text/tertiary',\n textStyle: 'heading/h6',\n },\n projectValue: {\n color: 'text/body',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: 'body/lg/semibold',\n },\n projectValueWrapper: {\n display: 'flex',\n minWidth: 0,\n },\n divider: {\n // Both of the sidebar's separator roles are `border/minimal` — the group header\n // (`20014:6508`) and this plain rule (`20014:6511`) — against `border/regular` for the general\n // Separator component. The override is per-slot for that reason, not to limit blast radius.\n borderColor: 'border/minimal',\n // Mobile's separator row is 40 tall, which centres the rule at 19.5 a side; 20 is the token\n // next to it and the resulting 1px lands nowhere the eye can find it.\n marginBlock: { base: '20', tablet: '16' },\n marginInline: '24',\n width: 'auto',\n },\n },\n variants: {\n hasBack: {\n // Redlines on the sub view (Figma `- page sidebar - interactions`): the title block sits at\n // x/y 16, is 40 tall, and the 32px back button sits at y 20 — i.e. the 4px padding belongs to\n // the block wrapping button + text, not to the text. Header totals 16 + 40 + 8 = 64.\n true: {\n title: {\n paddingBlockEnd: '8',\n paddingInlineStart: '16',\n },\n titleBlock: {\n gap: '4',\n paddingBlock: '4',\n },\n },\n // Main view: no button, so the text alone is the block — 6 + 28 + 6 = 40, header 16+40+16 = 72.\n false: {\n title: {\n paddingBlockEnd: '16',\n paddingInlineStart: '24',\n },\n titleBlock: {\n paddingBlock: '6',\n },\n },\n },\n isDisabled: {\n true: {\n item: {\n cursor: 'not-allowed',\n _hover: {\n background: 'transparent',\n _active: {\n background: 'transparent',\n },\n },\n _active: {\n background: 'transparent',\n },\n },\n itemIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n itemLabel: {\n color: 'text/disabled',\n },\n },\n false: {},\n },\n selected: {\n true: {\n item: {\n background: 'background/selected',\n _hover: {\n background: 'background/selected-hover',\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n itemIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n itemLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n },\n false: {},\n },\n },\n defaultVariants: {\n hasBack: false,\n isDisabled: false,\n selected: false,\n },\n});\n\nexport default pageSidebarSlotRecipe;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PageSidebar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/PageSidebar.recipe.ts"],"sourcesContent":["import { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nconst pageSidebarSlotRecipe = defineSlotRecipe({\n className: 'page-sidebar',\n slots: [\n 'body',\n 'contentBlock',\n 'divider',\n 'footer',\n 'item',\n 'itemIcon',\n 'itemLabel',\n 'progressBlocker',\n 'progressConnector',\n 'progressContentBlock',\n 'progressIcon',\n 'progressLabel',\n 'progressRow',\n 'progressSecondaryText',\n 'progressTextBlock',\n 'project',\n 'projectLabel',\n 'projectValue',\n 'projectValueWrapper',\n 'root',\n 'selectionMarker',\n 'suffixIcon',\n 'title',\n 'titleBlock',\n 'titleText',\n ],\n base: {\n root: {\n background: 'background/primary',\n // Longhands, not the `borderInlineEnd: '1px solid'` shorthand: that shorthand carries no\n // colour, so it resets it to `currentColor` if it lands after `borderColor` — which is what\n // sorting these keys alphabetically did, turning the rule dark.\n borderInlineEndColor: 'border/regular',\n borderInlineEndStyle: 'solid',\n borderInlineEndWidth: '1',\n display: 'flex',\n flexDirection: 'column',\n // `minHeight` rather than `height`: on a short navigation the sidebar still reaches the\n // bottom of the viewport, but a long one grows past it and scrolls with the page as one\n // block — the footer is part of that scroll, not pinned to the bottom.\n minHeight: '100dvh',\n // Below `tablet` the sidebar is the whole view — Figma's mobile frame (`23056:50745`) is the\n // full 375 of the phone, not a 240 column beside a page.\n maxWidth: { base: 'none', tablet: rem(320) },\n minWidth: rem(240),\n paddingBlockStart: '16',\n width: { base: 'full', tablet: rem(240) },\n },\n body: {\n display: 'flex',\n // Absorbs the slack so the footer sits at the bottom when the navigation is short, and\n // simply grows when it is long.\n flex: 1,\n flexDirection: 'column',\n // Half of the gap to the footer block; the footer carries the other half. Split that way so\n // this one is also the sidebar's bottom padding when there is no footer -- 8 either way,\n // rather than the body's whole 16 becoming the bottom edge. It is a margin so it stays\n // outside the items' own box, and `flex: 1` above means any extra space lands in the body\n // rather than widening the gap. Margins do not collapse in a flex column, so the two add up.\n marginBlockEnd: '8',\n width: 'full',\n },\n title: {\n alignItems: 'center',\n color: 'text/primary',\n display: 'flex',\n flexShrink: 0,\n overflow: 'clip',\n paddingInlineEnd: '32',\n },\n titleBlock: {\n alignItems: 'center',\n display: 'flex',\n minWidth: 0,\n },\n titleText: {\n textStyle: 'heading/h3',\n whiteSpace: 'nowrap',\n },\n item: {\n alignItems: 'center',\n cursor: 'pointer',\n display: 'flex',\n focusVisibleRing: 'inside',\n gap: '12',\n overflow: 'clip',\n // 48 tall on mobile against 40 on desktop — the row is a touch target there.\n paddingBlock: { base: '12', tablet: '8' },\n paddingInline: '24',\n position: 'relative',\n width: 'full',\n // Mobile reaches for `background/hover` / `background/active` where desktop uses the\n // `secondary` / `tertiary` surfaces. The two happen to resolve close, but they are separate\n // tokens in the design and the mobile item (`9221:4406`) binds these.\n _hover: {\n background: { base: 'background/hover', tablet: 'background/secondary' },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n // `focusVisibleRing: 'inside'` still resolves to `outline-offset: 0`, which draws the ring\n // just outside the border box. The item spans the sidebar's full width, so that would bleed\n // past the sidebar's edges — pull the whole ring inside the item instead.\n _focusVisible: {\n outlineOffset: 'calc(var(--focus-ring-width) * -1)',\n },\n },\n contentBlock: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 0,\n // Pads the 16px icon out to the 24px line box on desktop. The mobile icon is already 24, so\n // there is nothing to make up — the row would just grow past 48.\n paddingBlock: { base: '0', tablet: '2' },\n },\n itemIcon: {\n color: 'icon/secondary',\n flexShrink: 0,\n _groupHover: {\n color: 'icon/primary',\n },\n },\n itemLabel: {\n color: 'text/primary',\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textAlign: 'start',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n suffixIcon: {\n color: 'icon/tertiary',\n flexShrink: 0,\n },\n selectionMarker: {\n background: 'border/selected',\n // Mobile draws the marker as a plain 4px edge (`9221:4417`); desktop as a 2px rounded rule.\n borderEndStartRadius: { base: '0', tablet: '2' },\n borderStartStartRadius: { base: '0', tablet: '2' },\n height: 'full',\n insetBlockStart: 0,\n insetInlineEnd: 0,\n position: 'absolute',\n width: { base: '4', tablet: '2' },\n },\n footer: {\n borderBlockStart: '1px solid',\n borderColor: 'border/minimal',\n display: 'flex',\n flexDirection: 'column',\n // The body above absorbs the free space, so the footer needs no positioning of its own —\n // it just must not be squashed by a long list.\n flexShrink: 0,\n // The other half of the gap to the body — see its `marginBlockEnd`.\n marginBlockStart: '8',\n paddingBlock: '8',\n },\n /**\n * The progress item's own text, rather than `itemLabel`: that slot grows to fill the row, which\n * here belongs to the blocker so the connector can run to the trailing edge.\n */\n progressLabel: {\n color: 'text/primary',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /** Follows the label after a middle dot, which the component renders. */\n progressSecondaryText: {\n color: 'text/tertiary',\n flexShrink: 0,\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /**\n * Badge and connector as one unit, taking the width the text leaves.\n *\n * `fit-content` rather than 0: the flex basis is 0, so with a shrinking text block beside it\n * there is no free space to grow into and the block would be handed the whole row -- leaving\n * the badge, which does not shrink, hanging off the trailing edge. The floor is the badge; the\n * connector inside is basis 0 and contributes nothing to it.\n */\n progressBlocker: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 'fit-content',\n },\n /**\n * The status icon's own slot rather than `itemIcon`: that one brightens to `icon/primary` with\n * the row, which is right for navigation and wrong here -- hovering a stage would drop the\n * colour that says where it stands.\n */\n progressIcon: {\n // The colour a status-less icon takes -- the approvals step's, which the design draws in the\n // same `icon/secondary` as the navigation icons. `iconColor` overrides it per stage.\n color: 'icon/secondary',\n flexShrink: 0,\n // Its own slot rather than `itemIcon`, but it does brighten with the row: the design moves the\n // icon to `icon/primary` on hover and active. That only ever reaches a colour this recipe\n // supplied -- a consumer's `iconColor` is an inline, unlayered `color` and beats it -- so a\n // stage's status survives the hover while a status-less icon follows the row.\n _groupHover: {\n color: 'icon/primary',\n },\n },\n /**\n * Label and secondary text read as one line, so they sit closer than the row's own 12 gap.\n *\n * It shrinks before the blocker does: `item` clips its overflow, so without this a long stage\n * name is cut mid-word and pushes the secondary text and the connector off the row. The\n * blocker keeps `flex: 1`, so it still takes the slack whenever the text is short enough.\n */\n progressTextBlock: {\n alignItems: 'center',\n display: 'flex',\n flexShrink: 1,\n gap: '4',\n minWidth: 0,\n },\n /**\n * The progress row's block padding, which does not follow the navigation row's to 12 on mobile:\n * the design keeps this row on 8 at both widths, so it is 44 tall on mobile against a nav row's\n * 48. Layered over `item` rather than replacing it -- everything else about the row is shared.\n */\n progressRow: {\n paddingBlock: '8',\n },\n /** With the row above: 2 either side of the line box at both widths, so the block is 28. */\n progressContentBlock: {\n paddingBlock: '2',\n },\n progressConnector: {\n borderColor: 'border/minimal',\n borderStyle: 'dashed',\n flex: 1,\n },\n project: {\n display: 'flex',\n flexDirection: 'column',\n gap: '4',\n justifyContent: 'center',\n overflow: 'clip',\n paddingBlockEnd: { base: '12', tablet: '8' },\n paddingBlockStart: '8',\n paddingInlineEnd: { base: '24', tablet: '32' },\n paddingInlineStart: '24',\n whiteSpace: 'nowrap',\n },\n projectLabel: {\n color: 'text/tertiary',\n textStyle: 'heading/h6',\n },\n projectValue: {\n color: 'text/body',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: 'body/lg/semibold',\n },\n projectValueWrapper: {\n display: 'flex',\n minWidth: 0,\n },\n divider: {\n // Both of the sidebar's separator roles are `border/minimal` — the group header\n // (`20014:6508`) and this plain rule (`20014:6511`) — against `border/regular` for the general\n // Separator component. The override is per-slot for that reason, not to limit blast radius.\n borderColor: 'border/minimal',\n // Mobile's separator row is 40 tall, which centres the rule at 19.5 a side; 20 is the token\n // next to it and the resulting 1px lands nowhere the eye can find it.\n marginBlock: { base: '20', tablet: '16' },\n marginInline: '24',\n width: 'auto',\n },\n },\n variants: {\n hasBack: {\n // Redlines on the sub view (Figma `- page sidebar - interactions`): the title block sits at\n // x/y 16, is 40 tall, and the 32px back button sits at y 20 — i.e. the 4px padding belongs to\n // the block wrapping button + text, not to the text. Header totals 16 + 40 + 8 = 64.\n true: {\n title: {\n paddingBlockEnd: '8',\n paddingInlineStart: '16',\n },\n titleBlock: {\n gap: '4',\n paddingBlock: '4',\n },\n },\n // Main view: no button, so the text alone is the block — 6 + 28 + 6 = 40, header 16+40+16 = 72.\n false: {\n title: {\n paddingBlockEnd: '16',\n paddingInlineStart: '24',\n },\n titleBlock: {\n paddingBlock: '6',\n },\n },\n },\n isDisabled: {\n true: {\n item: {\n cursor: 'not-allowed',\n _hover: {\n background: 'transparent',\n _active: {\n background: 'transparent',\n },\n },\n _active: {\n background: 'transparent',\n },\n },\n itemIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n itemLabel: {\n color: 'text/disabled',\n },\n progressIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n progressLabel: {\n color: 'text/disabled',\n },\n progressSecondaryText: {\n color: 'text/disabled',\n },\n },\n false: {},\n },\n selected: {\n true: {\n item: {\n background: 'background/selected',\n _hover: {\n background: 'background/selected-hover',\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n itemIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n itemLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n progressIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n progressLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n },\n false: {},\n },\n /**\n * A stage the release does not have to clear. Everything steps down one level -- the icon to\n * tertiary, the label to secondary -- so the row reads as present but not awaited. Hover and\n * active take both back to the row's ordinary colours, as they do for a required stage.\n *\n * `selected` wins over it, resolved in the component rather than here. The design draws the\n * pair (`selected=yes, notRequired=true`) and gives it the selected row's icon and label with\n * the `not required` secondary text kept, which is what dropping this variant produces.\n */\n notRequired: {\n true: {\n progressIcon: {\n color: 'icon/tertiary',\n _groupHover: { color: 'icon/primary' },\n },\n progressLabel: {\n color: 'text/secondary',\n _groupHover: { color: 'text/primary' },\n },\n },\n false: {},\n },\n },\n defaultVariants: {\n hasBack: false,\n isDisabled: false,\n notRequired: false,\n selected: false,\n },\n});\n\nexport default pageSidebarSlotRecipe;\n"],"mappings":"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"}
@@ -1631,7 +1631,7 @@ declare const slotRecipes: {
1631
1631
  false: {};
1632
1632
  };
1633
1633
  }>;
1634
- pageSidebar: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "titleText" | "suffixIcon" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "divider" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
1634
+ pageSidebar: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "titleText" | "suffixIcon" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "divider" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
1635
1635
  hasBack: {
1636
1636
  true: {
1637
1637
  title: {
@@ -1676,6 +1676,18 @@ declare const slotRecipes: {
1676
1676
  itemLabel: {
1677
1677
  color: "text/disabled";
1678
1678
  };
1679
+ progressIcon: {
1680
+ color: "icon/disabled";
1681
+ _groupHover: {
1682
+ color: "icon/disabled";
1683
+ };
1684
+ };
1685
+ progressLabel: {
1686
+ color: "text/disabled";
1687
+ };
1688
+ progressSecondaryText: {
1689
+ color: "text/disabled";
1690
+ };
1679
1691
  };
1680
1692
  false: {};
1681
1693
  };
@@ -1711,6 +1723,35 @@ declare const slotRecipes: {
1711
1723
  tablet: "body/md/semibold";
1712
1724
  };
1713
1725
  };
1726
+ progressIcon: {
1727
+ color: "icon/interactive";
1728
+ _groupHover: {
1729
+ color: "icon/interactive-hover";
1730
+ };
1731
+ };
1732
+ progressLabel: {
1733
+ textStyle: {
1734
+ base: "body/lg/semibold";
1735
+ tablet: "body/md/semibold";
1736
+ };
1737
+ };
1738
+ };
1739
+ false: {};
1740
+ };
1741
+ notRequired: {
1742
+ true: {
1743
+ progressIcon: {
1744
+ color: "icon/tertiary";
1745
+ _groupHover: {
1746
+ color: "icon/primary";
1747
+ };
1748
+ };
1749
+ progressLabel: {
1750
+ color: "text/secondary";
1751
+ _groupHover: {
1752
+ color: "text/primary";
1753
+ };
1754
+ };
1714
1755
  };
1715
1756
  false: {};
1716
1757
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitrise/bitkit-v2",
3
3
  "private": false,
4
- "version": "0.3.428",
4
+ "version": "0.3.430-beta.2742",
5
5
  "description": "Bitrise Design System Components built with Chakra UI V3",
6
6
  "keywords": [
7
7
  "react",