@allxsmith/bestax-bulma 5.62.0 → 5.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/EmptyState.js +2 -6
  4. package/dist/esm/components/EmptyState.js.map +1 -1
  5. package/dist/esm/components/Timeline.js +5 -9
  6. package/dist/esm/components/Timeline.js.map +1 -1
  7. package/dist/esm/components/TreeView.js +3 -7
  8. package/dist/esm/components/TreeView.js.map +1 -1
  9. package/dist/esm/elements/Buttons.js +2 -0
  10. package/dist/esm/elements/Buttons.js.map +1 -1
  11. package/dist/esm/elements/CopyButton.js +132 -0
  12. package/dist/esm/elements/CopyButton.js.map +1 -0
  13. package/dist/esm/elements/DescriptionList.js +1 -5
  14. package/dist/esm/elements/DescriptionList.js.map +1 -1
  15. package/dist/esm/elements/Stat.js +196 -0
  16. package/dist/esm/elements/Stat.js.map +1 -0
  17. package/dist/esm/elements/Stats.js +48 -0
  18. package/dist/esm/elements/Stats.js.map +1 -0
  19. package/dist/esm/elements/statContext.js +10 -0
  20. package/dist/esm/elements/statContext.js.map +1 -0
  21. package/dist/esm/form/Combobox.js +2 -1
  22. package/dist/esm/form/Combobox.js.map +1 -1
  23. package/dist/esm/helpers/checkIcon.js +20 -0
  24. package/dist/esm/helpers/checkIcon.js.map +1 -0
  25. package/dist/esm/helpers/isGiven.js +13 -0
  26. package/dist/esm/helpers/isGiven.js.map +1 -0
  27. package/dist/esm/helpers/statusRegion.js +3 -3
  28. package/dist/esm/helpers/useClipboard.js +176 -0
  29. package/dist/esm/helpers/useClipboard.js.map +1 -0
  30. package/dist/extras.css +1 -1
  31. package/dist/extras.css.map +1 -1
  32. package/dist/index.cjs +4946 -4428
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.esm.js +4 -0
  35. package/dist/index.esm.js.map +1 -1
  36. package/dist/types/elements/Buttons.d.ts +1 -0
  37. package/dist/types/elements/CopyButton.d.ts +105 -0
  38. package/dist/types/elements/Stat.d.ts +242 -0
  39. package/dist/types/elements/Stats.d.ts +40 -0
  40. package/dist/types/elements/statContext.d.ts +18 -0
  41. package/dist/types/helpers/checkIcon.d.ts +10 -0
  42. package/dist/types/helpers/isGiven.d.ts +7 -0
  43. package/dist/types/helpers/useClipboard.d.ts +65 -0
  44. package/dist/types/index.d.ts +5 -0
  45. package/dist/types-cjs/elements/Buttons.d.ts +1 -0
  46. package/dist/types-cjs/elements/CopyButton.d.ts +105 -0
  47. package/dist/types-cjs/elements/Stat.d.ts +242 -0
  48. package/dist/types-cjs/elements/Stats.d.ts +40 -0
  49. package/dist/types-cjs/elements/statContext.d.ts +18 -0
  50. package/dist/types-cjs/helpers/checkIcon.d.ts +10 -0
  51. package/dist/types-cjs/helpers/isGiven.d.ts +7 -0
  52. package/dist/types-cjs/helpers/useClipboard.d.ts +65 -0
  53. package/dist/types-cjs/index.d.ts +5 -0
  54. package/dist/versions/bestax-no-dark-mode.css +1 -1
  55. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  56. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  57. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  58. package/dist/versions/bestax-no-helpers.css +1 -1
  59. package/dist/versions/bestax-no-helpers.css.map +1 -1
  60. package/dist/versions/bestax-prefixed.css +1 -1
  61. package/dist/versions/bestax-prefixed.css.map +1 -1
  62. package/package.json +1 -1
  63. package/src/scss/elements/_index.scss +1 -0
  64. package/src/scss/elements/_stat.scss +153 -0
@@ -9,6 +9,7 @@ import { Buttons } from '../elements/Buttons.js';
9
9
  import { Icon } from '../elements/Icon.js';
10
10
  import { Paragraph } from '../elements/Paragraph.js';
11
11
  import { Title } from '../elements/Title.js';
12
+ import { isGiven } from '../helpers/isGiven.js';
12
13
 
13
14
  const validEmptyStateColors = [
14
15
  'primary',
@@ -79,11 +80,6 @@ const EmptyStateActions = ({ className, ...props }) => {
79
80
  return jsx(Buttons, { className: classNames(actionsClass, className), ...props });
80
81
  };
81
82
  EmptyStateActions.displayName = 'EmptyState.Actions';
82
- /** Whether a shorthand prop was given something to render. */
83
- const isGiven$3 = (node) => node !== undefined &&
84
- node !== null &&
85
- typeof node !== 'boolean' &&
86
- node !== '';
87
83
  /**
88
84
  * The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen.
89
85
  *
@@ -127,7 +123,7 @@ const EmptyStateRoot = forwardRef(({ className, icon, title, titleAs = 'h2', des
127
123
  });
128
124
  // The props' parts first, each only when it's given, then the children
129
125
  // exactly as they were written: nothing here looks at them.
130
- return (jsxs("div", { ref: ref, className: classNames(rootClass, bulmaHelperClasses, className), ...rest, children: [isGiven$3(icon) && (jsx(EmptyStateIndicator, { children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), isGiven$3(title) && (jsx(EmptyStateTitle, { as: titleAs, children: title })), isGiven$3(description) && (jsx(EmptyStateDescription, { children: description })), children] }));
126
+ return (jsxs("div", { ref: ref, className: classNames(rootClass, bulmaHelperClasses, className), ...rest, children: [isGiven(icon) && (jsx(EmptyStateIndicator, { children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), isGiven(title) && (jsx(EmptyStateTitle, { as: titleAs, children: title })), isGiven(description) && (jsx(EmptyStateDescription, { children: description })), children] }));
131
127
  });
132
128
  const EmptyState = withSubComponents(EmptyStateRoot, {
133
129
  Indicator: EmptyStateIndicator,
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Buttons, ButtonsProps } from '../elements/Buttons';\nimport { Icon } from '../elements/Icon';\nimport { Paragraph, ParagraphProps } from '../elements/Paragraph';\nimport { Title, TitleProps } from '../elements/Title';\n\nconst validEmptyStateColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n/** The Bulma colors the indicator takes. */\nexport type EmptyStateColor = (typeof validEmptyStateColors)[number];\n\nconst validEmptyStateHeadings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;\n/** A title's heading level. It's always a heading, so there's no `p`. */\nexport type EmptyStateHeading = (typeof validEmptyStateHeadings)[number];\n\nconst validEmptyStateSizes = ['small', 'medium', 'large'] as const;\n\n/**\n * Props for the EmptyState component. The helper props, the other attributes\n * and the `ref` land on the root `<div>`. The native `title` attribute isn't\n * one of them, since `title` here is the heading.\n *\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root `<div>`.\n */\nexport interface EmptyStateProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * The picture in the indicator's circle. A string is an `Icon` name, drawn\n * from the icon library `ConfigProvider` sets. Anything else (an `<Icon>`\n * with its own `variant` or `library`, an SVG, an `<img>`) renders as it is.\n * It's decorative and hidden from assistive tech, so the title says what\n * it means.\n */\n icon?: React.ReactNode;\n /**\n * The heading, rendered as `EmptyState.Title`. It's always a real heading,\n * at the level `titleAs` sets.\n */\n title?: React.ReactNode;\n /**\n * The heading level for `title`: the level under the heading of the list\n * it stands in for, such as `h3` for a list under an `h2`. Only this sets\n * the level, and the size comes from `size`.\n */\n titleAs?: EmptyStateHeading;\n /** A sentence or two under the title, rendered as `EmptyState.Description`. */\n description?: React.ReactNode;\n /**\n * Rendered as written, after whatever `icon`, `title` and `description`\n * render. One button can go straight in, and it sits centered under the\n * text. Group two or more in `EmptyState.Actions`, or they stack. Without\n * the props, write the parts here in the order they're shown:\n * `EmptyState.Indicator`, `.Title`, `.Description`, then the actions.\n */\n children?: React.ReactNode;\n /**\n * The indicator's color. It colors the circle and its icon, not the text.\n * Without it the circle is neutral, since an empty list isn't a status.\n */\n color?: EmptyStateColor;\n /**\n * `light` is a soft tint of `color` behind the icon in the color. `filled`\n * is the color itself, with the icon in its invert.\n */\n variant?: 'light' | 'filled';\n /** Sizes the indicator, the title, the description and the spacing together. */\n size?: 'small' | 'normal' | 'medium' | 'large';\n /**\n * `center` stacks everything in a centered column. `left` puts the\n * indicator beside the text, at the start of the line, so on the right in\n * a right-to-left page, and keeps the block at least as tall as the circle\n * whatever block padding is in effect. Without an indicator, it only puts\n * the text at the start of the line. In `left`, the padding at the start\n * of the line is what makes room for the indicator, so pad it with `py`\n * rather than `p` or `px`.\n */\n align?: 'center' | 'left';\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/** Props for EmptyState.Indicator, the circle the picture sits in. */\nexport interface EmptyStateIndicatorProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * The picture: an `Icon`, an SVG or an `<img>`. The indicator is hidden\n * from assistive tech, an `Icon` with an `ariaLabel` included, so anything\n * it means goes in the title or the description.\n */\n children?: React.ReactNode;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * Props for EmptyState.Title. It renders `Title` with `as` and never `size`,\n * so the level is `as` alone and the size comes from the EmptyState.\n */\nexport interface EmptyStateTitleProps extends Omit<\n TitleProps,\n 'as' | 'size' | 'isSpaced'\n> {\n /**\n * The heading level: the level under the heading of the list the empty\n * state stands in for.\n */\n as?: EmptyStateHeading;\n}\n\n/** Props for EmptyState.Description, a `<p>` under the title. */\nexport type EmptyStateDescriptionProps = ParagraphProps;\n\n/**\n * Props for EmptyState.Actions, the row of buttons. It renders `Buttons`,\n * and the EmptyState aligns it, so `isCentered` and `isRight` are left out.\n */\nexport type EmptyStateActionsProps = Omit<\n ButtonsProps,\n 'isCentered' | 'isRight'\n>;\n\n/**\n * The circle the picture sits in, hidden from assistive tech whatever is in it.\n *\n * @function\n * @param {EmptyStateIndicatorProps} props - Props for EmptyState.Indicator.\n * @returns {JSX.Element} The rendered indicator.\n */\nexport const EmptyStateIndicator: React.FC<EmptyStateIndicatorProps> = ({\n className,\n textColor,\n bgColor,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const indicatorClass = usePrefixedClassNames('empty-state-indicator');\n\n // Hidden after the rest of the props, so nothing passed in can expose the\n // picture: the title says what it means.\n return (\n <div\n className={classNames(indicatorClass, bulmaHelperClasses, className)}\n {...rest}\n aria-hidden=\"true\"\n >\n {children}\n </div>\n );\n};\n\nEmptyStateIndicator.displayName = 'EmptyState.Indicator';\n\n/**\n * The heading, a Bulma `Title` at the level `as` sets, `h2` by default, and at the EmptyState's size.\n *\n * @function\n * @param {EmptyStateTitleProps} props - Props for EmptyState.Title.\n * @returns {JSX.Element} The rendered heading.\n */\nexport const EmptyStateTitle: React.FC<EmptyStateTitleProps> = ({\n as = 'h2',\n className,\n ...props\n}) => {\n // `size` isn't in the type, but on `Title` it picks the tag, so it's kept\n // off even when it's passed anyway. The level is `as` alone.\n const { size: _size, ...rest } = props as typeof props & { size?: unknown };\n const titleClass = usePrefixedClassNames('empty-state-title');\n const level = validEmptyStateHeadings.includes(as) ? as : 'h2';\n\n return (\n <Title as={level} className={classNames(titleClass, className)} {...rest} />\n );\n};\n\nEmptyStateTitle.displayName = 'EmptyState.Title';\n\n/**\n * A sentence or two under the title, in the color of the text around it.\n *\n * @function\n * @param {EmptyStateDescriptionProps} props - Props for EmptyState.Description.\n * @returns {JSX.Element} The rendered description.\n */\nexport const EmptyStateDescription: React.FC<EmptyStateDescriptionProps> = ({\n className,\n ...props\n}) => {\n const descriptionClass = usePrefixedClassNames('empty-state-description');\n return (\n <Paragraph className={classNames(descriptionClass, className)} {...props} />\n );\n};\n\nEmptyStateDescription.displayName = 'EmptyState.Description';\n\n/**\n * A row of buttons, centered under the text or at the start of the line beside the indicator.\n *\n * @function\n * @param {EmptyStateActionsProps} props - Props for EmptyState.Actions.\n * @returns {JSX.Element} The rendered row of buttons.\n */\nexport const EmptyStateActions: React.FC<EmptyStateActionsProps> = ({\n className,\n ...props\n}) => {\n const actionsClass = usePrefixedClassNames('empty-state-actions');\n return <Buttons className={classNames(actionsClass, className)} {...props} />;\n};\n\nEmptyStateActions.displayName = 'EmptyState.Actions';\n\n/** Whether a shorthand prop was given something to render. */\nconst isGiven = (node: React.ReactNode) =>\n node !== undefined &&\n node !== null &&\n typeof node !== 'boolean' &&\n node !== '';\n\n/**\n * The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen.\n *\n * It's a column of a picture in a circle, a heading, a line of text and the\n * actions, with one layout whether it's written with the `icon`, `title` and\n * `description` props or with the parts. The children always render as\n * written, after the parts the props render.\n *\n * It has no role and no live region. It arrives already filled and goes away\n * when results come back, so it can't announce a search that matched\n * nothing: keep a `role=\"status\"` region beside the search field for that,\n * in the page the whole time. While the data loads, show a `Skeleton` or a\n * `Loader` instead, so \"No projects yet\" doesn't flash first, and show a\n * load that failed in a `Message` or a `Notification`.\n *\n * @function\n * @param {EmptyStateProps} props - Props for the EmptyState component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root `<div>`.\n * @returns {JSX.Element} The rendered empty state.\n *\n * @example\n * <EmptyState\n * icon=\"folder-open\"\n * title=\"No projects yet\"\n * description=\"Projects you create or join show up here.\"\n * >\n * <Button color=\"primary\">New project</Button>\n * </EmptyState>\n */\nconst EmptyStateRoot = forwardRef<HTMLDivElement, EmptyStateProps>(\n (\n {\n className,\n icon,\n title,\n titleAs = 'h2',\n description,\n children,\n color,\n variant = 'light',\n size = 'normal',\n align = 'center',\n textColor,\n bgColor,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const rootClass = usePrefixedClassNames('empty-state', {\n [`is-${size}`]: (validEmptyStateSizes as readonly string[]).includes(\n size\n ),\n 'is-left': align === 'left',\n [`is-${color}`]:\n !!color && (validEmptyStateColors as readonly string[]).includes(color),\n 'is-filled': variant === 'filled',\n });\n\n // The props' parts first, each only when it's given, then the children\n // exactly as they were written: nothing here looks at them.\n return (\n <div\n ref={ref}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n {...rest}\n >\n {isGiven(icon) && (\n <EmptyStateIndicator>\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </EmptyStateIndicator>\n )}\n {isGiven(title) && (\n <EmptyStateTitle as={titleAs}>{title}</EmptyStateTitle>\n )}\n {isGiven(description) && (\n <EmptyStateDescription>{description}</EmptyStateDescription>\n )}\n {children}\n </div>\n );\n }\n);\n\nexport const EmptyState = withSubComponents(\n EmptyStateRoot,\n {\n Indicator: EmptyStateIndicator,\n Title: EmptyStateTitle,\n Description: EmptyStateDescription,\n Actions: EmptyStateActions,\n },\n 'EmptyState'\n);\n\nexport default EmptyState;\n"],"names":["_jsx","isGiven","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"EmptyState.js","sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Buttons, ButtonsProps } from '../elements/Buttons';\nimport { Icon } from '../elements/Icon';\nimport { Paragraph, ParagraphProps } from '../elements/Paragraph';\nimport { Title, TitleProps } from '../elements/Title';\nimport { isGiven } from '../helpers/isGiven';\n\nconst validEmptyStateColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n/** The Bulma colors the indicator takes. */\nexport type EmptyStateColor = (typeof validEmptyStateColors)[number];\n\nconst validEmptyStateHeadings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;\n/** A title's heading level. It's always a heading, so there's no `p`. */\nexport type EmptyStateHeading = (typeof validEmptyStateHeadings)[number];\n\nconst validEmptyStateSizes = ['small', 'medium', 'large'] as const;\n\n/**\n * Props for the EmptyState component. The helper props, the other attributes\n * and the `ref` land on the root `<div>`. The native `title` attribute isn't\n * one of them, since `title` here is the heading.\n *\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root `<div>`.\n */\nexport interface EmptyStateProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * The picture in the indicator's circle. A string is an `Icon` name, drawn\n * from the icon library `ConfigProvider` sets. Anything else (an `<Icon>`\n * with its own `variant` or `library`, an SVG, an `<img>`) renders as it is.\n * It's decorative and hidden from assistive tech, so the title says what\n * it means.\n */\n icon?: React.ReactNode;\n /**\n * The heading, rendered as `EmptyState.Title`. It's always a real heading,\n * at the level `titleAs` sets.\n */\n title?: React.ReactNode;\n /**\n * The heading level for `title`: the level under the heading of the list\n * it stands in for, such as `h3` for a list under an `h2`. Only this sets\n * the level, and the size comes from `size`.\n */\n titleAs?: EmptyStateHeading;\n /** A sentence or two under the title, rendered as `EmptyState.Description`. */\n description?: React.ReactNode;\n /**\n * Rendered as written, after whatever `icon`, `title` and `description`\n * render. One button can go straight in, and it sits centered under the\n * text. Group two or more in `EmptyState.Actions`, or they stack. Without\n * the props, write the parts here in the order they're shown:\n * `EmptyState.Indicator`, `.Title`, `.Description`, then the actions.\n */\n children?: React.ReactNode;\n /**\n * The indicator's color. It colors the circle and its icon, not the text.\n * Without it the circle is neutral, since an empty list isn't a status.\n */\n color?: EmptyStateColor;\n /**\n * `light` is a soft tint of `color` behind the icon in the color. `filled`\n * is the color itself, with the icon in its invert.\n */\n variant?: 'light' | 'filled';\n /** Sizes the indicator, the title, the description and the spacing together. */\n size?: 'small' | 'normal' | 'medium' | 'large';\n /**\n * `center` stacks everything in a centered column. `left` puts the\n * indicator beside the text, at the start of the line, so on the right in\n * a right-to-left page, and keeps the block at least as tall as the circle\n * whatever block padding is in effect. Without an indicator, it only puts\n * the text at the start of the line. In `left`, the padding at the start\n * of the line is what makes room for the indicator, so pad it with `py`\n * rather than `p` or `px`.\n */\n align?: 'center' | 'left';\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/** Props for EmptyState.Indicator, the circle the picture sits in. */\nexport interface EmptyStateIndicatorProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * The picture: an `Icon`, an SVG or an `<img>`. The indicator is hidden\n * from assistive tech, an `Icon` with an `ariaLabel` included, so anything\n * it means goes in the title or the description.\n */\n children?: React.ReactNode;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * Props for EmptyState.Title. It renders `Title` with `as` and never `size`,\n * so the level is `as` alone and the size comes from the EmptyState.\n */\nexport interface EmptyStateTitleProps extends Omit<\n TitleProps,\n 'as' | 'size' | 'isSpaced'\n> {\n /**\n * The heading level: the level under the heading of the list the empty\n * state stands in for.\n */\n as?: EmptyStateHeading;\n}\n\n/** Props for EmptyState.Description, a `<p>` under the title. */\nexport type EmptyStateDescriptionProps = ParagraphProps;\n\n/**\n * Props for EmptyState.Actions, the row of buttons. It renders `Buttons`,\n * and the EmptyState aligns it, so `isCentered` and `isRight` are left out.\n */\nexport type EmptyStateActionsProps = Omit<\n ButtonsProps,\n 'isCentered' | 'isRight'\n>;\n\n/**\n * The circle the picture sits in, hidden from assistive tech whatever is in it.\n *\n * @function\n * @param {EmptyStateIndicatorProps} props - Props for EmptyState.Indicator.\n * @returns {JSX.Element} The rendered indicator.\n */\nexport const EmptyStateIndicator: React.FC<EmptyStateIndicatorProps> = ({\n className,\n textColor,\n bgColor,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const indicatorClass = usePrefixedClassNames('empty-state-indicator');\n\n // Hidden after the rest of the props, so nothing passed in can expose the\n // picture: the title says what it means.\n return (\n <div\n className={classNames(indicatorClass, bulmaHelperClasses, className)}\n {...rest}\n aria-hidden=\"true\"\n >\n {children}\n </div>\n );\n};\n\nEmptyStateIndicator.displayName = 'EmptyState.Indicator';\n\n/**\n * The heading, a Bulma `Title` at the level `as` sets, `h2` by default, and at the EmptyState's size.\n *\n * @function\n * @param {EmptyStateTitleProps} props - Props for EmptyState.Title.\n * @returns {JSX.Element} The rendered heading.\n */\nexport const EmptyStateTitle: React.FC<EmptyStateTitleProps> = ({\n as = 'h2',\n className,\n ...props\n}) => {\n // `size` isn't in the type, but on `Title` it picks the tag, so it's kept\n // off even when it's passed anyway. The level is `as` alone.\n const { size: _size, ...rest } = props as typeof props & { size?: unknown };\n const titleClass = usePrefixedClassNames('empty-state-title');\n const level = validEmptyStateHeadings.includes(as) ? as : 'h2';\n\n return (\n <Title as={level} className={classNames(titleClass, className)} {...rest} />\n );\n};\n\nEmptyStateTitle.displayName = 'EmptyState.Title';\n\n/**\n * A sentence or two under the title, in the color of the text around it.\n *\n * @function\n * @param {EmptyStateDescriptionProps} props - Props for EmptyState.Description.\n * @returns {JSX.Element} The rendered description.\n */\nexport const EmptyStateDescription: React.FC<EmptyStateDescriptionProps> = ({\n className,\n ...props\n}) => {\n const descriptionClass = usePrefixedClassNames('empty-state-description');\n return (\n <Paragraph className={classNames(descriptionClass, className)} {...props} />\n );\n};\n\nEmptyStateDescription.displayName = 'EmptyState.Description';\n\n/**\n * A row of buttons, centered under the text or at the start of the line beside the indicator.\n *\n * @function\n * @param {EmptyStateActionsProps} props - Props for EmptyState.Actions.\n * @returns {JSX.Element} The rendered row of buttons.\n */\nexport const EmptyStateActions: React.FC<EmptyStateActionsProps> = ({\n className,\n ...props\n}) => {\n const actionsClass = usePrefixedClassNames('empty-state-actions');\n return <Buttons className={classNames(actionsClass, className)} {...props} />;\n};\n\nEmptyStateActions.displayName = 'EmptyState.Actions';\n\n/**\n * The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen.\n *\n * It's a column of a picture in a circle, a heading, a line of text and the\n * actions, with one layout whether it's written with the `icon`, `title` and\n * `description` props or with the parts. The children always render as\n * written, after the parts the props render.\n *\n * It has no role and no live region. It arrives already filled and goes away\n * when results come back, so it can't announce a search that matched\n * nothing: keep a `role=\"status\"` region beside the search field for that,\n * in the page the whole time. While the data loads, show a `Skeleton` or a\n * `Loader` instead, so \"No projects yet\" doesn't flash first, and show a\n * load that failed in a `Message` or a `Notification`.\n *\n * @function\n * @param {EmptyStateProps} props - Props for the EmptyState component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root `<div>`.\n * @returns {JSX.Element} The rendered empty state.\n *\n * @example\n * <EmptyState\n * icon=\"folder-open\"\n * title=\"No projects yet\"\n * description=\"Projects you create or join show up here.\"\n * >\n * <Button color=\"primary\">New project</Button>\n * </EmptyState>\n */\nconst EmptyStateRoot = forwardRef<HTMLDivElement, EmptyStateProps>(\n (\n {\n className,\n icon,\n title,\n titleAs = 'h2',\n description,\n children,\n color,\n variant = 'light',\n size = 'normal',\n align = 'center',\n textColor,\n bgColor,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const rootClass = usePrefixedClassNames('empty-state', {\n [`is-${size}`]: (validEmptyStateSizes as readonly string[]).includes(\n size\n ),\n 'is-left': align === 'left',\n [`is-${color}`]:\n !!color && (validEmptyStateColors as readonly string[]).includes(color),\n 'is-filled': variant === 'filled',\n });\n\n // The props' parts first, each only when it's given, then the children\n // exactly as they were written: nothing here looks at them.\n return (\n <div\n ref={ref}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n {...rest}\n >\n {isGiven(icon) && (\n <EmptyStateIndicator>\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </EmptyStateIndicator>\n )}\n {isGiven(title) && (\n <EmptyStateTitle as={titleAs}>{title}</EmptyStateTitle>\n )}\n {isGiven(description) && (\n <EmptyStateDescription>{description}</EmptyStateDescription>\n )}\n {children}\n </div>\n );\n }\n);\n\nexport const EmptyState = withSubComponents(\n EmptyStateRoot,\n {\n Indicator: EmptyStateIndicator,\n Title: EmptyStateTitle,\n Description: EmptyStateDescription,\n Actions: EmptyStateActions,\n },\n 'EmptyState'\n);\n\nexport default EmptyState;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -8,6 +8,7 @@ import { flattenChildren } from '../helpers/flattenChildren.js';
8
8
  import { visuallyHidden } from '../helpers/statusRegion.js';
9
9
  import { withSubComponents } from '../helpers/withSubComponents.js';
10
10
  import { Icon } from '../elements/Icon.js';
11
+ import { isGiven } from '../helpers/isGiven.js';
11
12
 
12
13
  const validTimelineColors = [
13
14
  'primary',
@@ -22,11 +23,6 @@ const validTimelineTitleElements = ['h2', 'h3', 'h4', 'h5', 'h6', 'p'];
22
23
  const TimelineItemContext = createContext({
23
24
  titleAs: 'h2',
24
25
  });
25
- /** Whether a prop was given something to render. */
26
- const isGiven$2 = (node) => node !== undefined &&
27
- node !== null &&
28
- typeof node !== 'boolean' &&
29
- node !== '';
30
26
  const isTimelineColor = (color) => !!color && validTimelineColors.includes(color);
31
27
  /**
32
28
  * One event: a marker on the rail, then its title, its time and anything else about it.
@@ -56,7 +52,7 @@ const TimelineItem = forwardRef(({ className, title, time, dateTime, icon, color
56
52
  [`is-${color}`]: isTimelineColor(color),
57
53
  });
58
54
  const markerClass = usePrefixedClassNames('timeline-marker', {
59
- 'is-icon': isGiven$2(icon),
55
+ 'is-icon': isGiven(icon),
60
56
  });
61
57
  const contentClass = usePrefixedClassNames('timeline-content');
62
58
  const titleClass = usePrefixedClassNames('timeline-title');
@@ -68,8 +64,8 @@ const TimelineItem = forwardRef(({ className, title, time, dateTime, icon, color
68
64
  const words = label ? (jsx("span", { style: visuallyHidden, children: ` ${label}` })) : null;
69
65
  return (jsxs("li", { ref: ref, className: classNames(itemClass, bulmaHelperClasses, className), ...rest, ...(state && {
70
66
  'aria-current': state === 'active' ? 'step' : undefined,
71
- }), children: [jsx("div", { className: markerClass, "aria-hidden": "true", children: isGiven$2(icon) &&
72
- (typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon) }), jsxs("div", { className: contentClass, children: [isGiven$2(title) ? (jsxs(TitleTag, { className: titleClass, children: [title, words] })) : (words), isGiven$2(time) &&
67
+ }), children: [jsx("div", { className: markerClass, "aria-hidden": "true", children: isGiven(icon) &&
68
+ (typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon) }), jsxs("div", { className: contentClass, children: [isGiven(title) ? (jsxs(TitleTag, { className: titleClass, children: [title, words] })) : (words), isGiven(time) &&
73
69
  (dateTime ? (jsx("time", { className: timeClass, dateTime: dateTime, children: time })) : (jsx("span", { className: timeClass, children: time }))), children] })] }));
74
70
  });
75
71
  TimelineItem.displayName = 'Timeline.Item';
@@ -143,7 +139,7 @@ const TimelineRoot = forwardRef(({ className, children, active, pending, align =
143
139
  // Each child gets its state through context rather than a clone, so an
144
140
  // app's own component around a Timeline.Item still gets it. Fragments
145
141
  // and arrays are opened up first, so each item inside one counts.
146
- return (jsxs("ol", { ref: ref, className: classNames(rootClass, bulmaHelperClasses, className), ...rest, role: "list", children: [flattenChildren(children).map((child, index) => (jsx(TimelineItemContext.Provider, { value: contextFor(stateAt(index)), children: child }, React.isValidElement(child) ? child.key : index))), isGiven$2(pending) && (jsx(TimelineItemContext.Provider, { value: contextFor('pending'), children: jsx(TimelineItem, { title: pending }) }))] }));
142
+ return (jsxs("ol", { ref: ref, className: classNames(rootClass, bulmaHelperClasses, className), ...rest, role: "list", children: [flattenChildren(children).map((child, index) => (jsx(TimelineItemContext.Provider, { value: contextFor(stateAt(index)), children: child }, React.isValidElement(child) ? child.key : index))), isGiven(pending) && (jsx(TimelineItemContext.Provider, { value: contextFor('pending'), children: jsx(TimelineItem, { title: pending }) }))] }));
147
143
  });
148
144
  const Timeline = withSubComponents(TimelineRoot, { Item: TimelineItem }, 'Timeline');
149
145
 
@@ -1 +1 @@
1
- {"version":3,"file":"Timeline.js","sources":["../../../src/components/Timeline.tsx"],"sourcesContent":["import React, { createContext, forwardRef, useContext } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { flattenChildren } from '../helpers/flattenChildren';\nimport { visuallyHidden } from '../helpers/statusRegion';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Icon } from '../elements/Icon';\n\nconst validTimelineColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n/** The Bulma colors a marker takes. */\nexport type TimelineColor = (typeof validTimelineColors)[number];\n\nconst validTimelineTitleElements = ['h2', 'h3', 'h4', 'h5', 'h6', 'p'] as const;\n/** What each item's title renders as: a heading level, or `p` for a plain line. */\nexport type TimelineTitleElement = (typeof validTimelineTitleElements)[number];\n\n/** Where the rail goes. */\nexport type TimelineAlign = 'start' | 'end' | 'alternate';\n\n/** Where an item is in a progress timeline. */\ntype TimelineState = 'completed' | 'active' | 'upcoming' | 'pending';\n\n/**\n * What the root hands each of its items: the title's element, and in a\n * progress timeline, the item's state and the words read after its title.\n */\ninterface TimelineItemContextValue {\n titleAs: TimelineTitleElement;\n state?: TimelineState;\n label?: string;\n}\n\n// An item outside a Timeline is a record item with an h2 title.\nconst TimelineItemContext = createContext<TimelineItemContextValue>({\n titleAs: 'h2',\n});\n\n/** Whether a prop was given something to render. */\nconst isGiven = (node: React.ReactNode) =>\n node !== undefined &&\n node !== null &&\n typeof node !== 'boolean' &&\n node !== '';\n\nconst isTimelineColor = (color?: string): color is TimelineColor =>\n !!color && (validTimelineColors as readonly string[]).includes(color);\n\n/**\n * Props for the Timeline component. The helper props, the other attributes\n * and the `ref` land on the `<ol>`.\n *\n * @extraProp {React.Ref<HTMLOListElement>} [ref] - Ref forwarded to the `<ol>`.\n */\nexport interface TimelineProps\n extends\n Omit<React.OlHTMLAttributes<HTMLOListElement>, 'color' | 'role'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * `Timeline.Item`s, in the order they're read: newest first or oldest\n * first for a record, oldest first with `active` or `pending`.\n */\n children?: React.ReactNode;\n /**\n * Marks progress. The item at this index, counting the children from 0, is\n * current; the ones before it are completed and the ones after it are\n * upcoming. Leave it out for a record, where nothing is marked. `-1` marks\n * every item upcoming, and an index past the last marks them all completed.\n * A fraction counts as the item it has reached, so `2.5` marks the third\n * item current. Each child counts as one item, with Fragments and arrays opened up, so\n * render one item per child. A component of your own around a\n * `Timeline.Item` still gets its state, but one that renders nothing still\n * counts.\n */\n active?: number;\n /**\n * What's under way, as a last item after the children: its title, read\n * with `pendingLabel`. Write it as words that say so (\"Out for delivery\").\n */\n pending?: React.ReactNode;\n /**\n * `start`: the rail at the start of the line. `end`: at the end, with the\n * text against it. `alternate`: down the middle, the items taking turns and\n * each time across the rail; below Bulma's tablet breakpoint it's `start`.\n */\n align?: TimelineAlign;\n /**\n * What every item's title renders as: a heading at the level under the\n * heading the timeline sits beneath, or `p` for a busy feed.\n */\n titleAs?: TimelineTitleElement;\n /**\n * The markers' color, and the color of progress with `active`. Neutral\n * without it, and Bulma's `link` for progress. The markers are hidden from\n * assistive tech, so say what a color means in the words too.\n */\n color?: TimelineColor;\n /** Read after a completed item's title, visually hidden. In your app's language. */\n completedLabel?: string;\n /** Read after an upcoming item's title, visually hidden. In your app's language. */\n upcomingLabel?: string;\n /** Read after the pending item's title, visually hidden. In your app's language. */\n pendingLabel?: string;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * Props for Timeline.Item, one event. The helper props, the other attributes\n * and the `ref` land on its `<li>`. The native `title` attribute isn't one of\n * them, since `title` here is the event's title.\n *\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TimelineItemProps\n extends\n Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /** What happened, in a line. It renders as the root's `titleAs`. */\n title?: React.ReactNode;\n /**\n * When it happened, as the reader sees it: \"14 October 2026\", \"2 hours\n * ago\". Put the whole date in the words, since screen readers mostly read\n * the text.\n */\n time?: React.ReactNode;\n /**\n * The same moment for machines, as HTML's `datetime` takes it:\n * \"2026-10-14\", \"2026-10-14T08:12\", \"2026-10\". With it, `time` renders in\n * a `<time>`. Keep it the same moment as `time`, since some readers speak it.\n */\n dateTime?: string;\n /**\n * A picture in the marker. A string is an `Icon` name, drawn from the icon\n * library `ConfigProvider` sets, and anything else renders as it is.\n * Without it, the marker is a dot. It's hidden from assistive tech, so\n * what it means goes in the title.\n */\n icon?: React.ReactNode;\n /** This item's marker color, over the root's. Say what it means in the words too. */\n color?: TimelineColor;\n /** Anything else about the event, under the title and the time, as written. */\n children?: React.ReactNode;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * One event: a marker on the rail, then its title, its time and anything else about it.\n *\n * Outside a `Timeline` it's a record item with an `h2` title, though the\n * styles are registered on `.timeline`, so the rail and the marker need one.\n *\n * @function\n * @param {TimelineItemProps} props - Props for Timeline.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element} The rendered event.\n *\n * @example\n * <Timeline.Item title=\"Shipped\" time=\"14 October 2026\" dateTime=\"2026-10-14\">\n * Left the warehouse in Leeds.\n * </Timeline.Item>\n */\nexport const TimelineItem = forwardRef<HTMLLIElement, TimelineItemProps>(\n (\n {\n className,\n title,\n time,\n dateTime,\n icon,\n color,\n textColor,\n bgColor,\n children,\n ...props\n },\n ref\n ) => {\n const { titleAs: TitleTag, state, label } = useContext(TimelineItemContext);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const itemClass = usePrefixedClassNames('timeline-item', {\n [`is-${state}`]: !!state,\n [`is-${color}`]: isTimelineColor(color),\n });\n const markerClass = usePrefixedClassNames('timeline-marker', {\n 'is-icon': isGiven(icon),\n });\n const contentClass = usePrefixedClassNames('timeline-content');\n const titleClass = usePrefixedClassNames('timeline-title');\n const timeClass = usePrefixedClassNames('timeline-time');\n\n // The state in words, read after the title so it's in the heading too:\n // \"Packed completed\". The current item has none, since aria-current\n // says it. The styles are inline, so the words stay hidden in a modular\n // build that leaves out Bulma's helper classes.\n const words = label ? (\n <span style={visuallyHidden}>{` ${label}`}</span>\n ) : null;\n\n return (\n <li\n ref={ref}\n className={classNames(itemClass, bulmaHelperClasses, className)}\n {...rest}\n // In a progress timeline the state decides, whatever was passed.\n {...(state && {\n 'aria-current': state === 'active' ? 'step' : undefined,\n })}\n >\n {/* Decoration, hidden with whatever is in it, an Icon's own label\n included: the words say what a color, an icon or a state means. */}\n <div className={markerClass} aria-hidden=\"true\">\n {isGiven(icon) &&\n (typeof icon === 'string' ? <Icon name={icon} /> : icon)}\n </div>\n <div className={contentClass}>\n {isGiven(title) ? (\n <TitleTag className={titleClass}>\n {title}\n {words}\n </TitleTag>\n ) : (\n words\n )}\n {isGiven(time) &&\n (dateTime ? (\n <time className={timeClass} dateTime={dateTime}>\n {time}\n </time>\n ) : (\n <span className={timeClass}>{time}</span>\n ))}\n {children}\n </div>\n </li>\n );\n }\n);\n\nTimelineItem.displayName = 'Timeline.Item';\n\n/**\n * The `Timeline` component renders a list of events in the order they happened, each with a marker on a line down the side.\n *\n * By default it's a record, an order's history, a ticket's activity or a\n * changelog, and it marks nothing. With `active` it marks progress, for\n * something that moves along on its own and is reported to the user: a\n * parcel, a deployment, a claim. That reads oldest first, and `pending` ends\n * it on what's under way. A journey the user moves through themselves, like\n * a wizard or a checkout, is `Steps`.\n *\n * It's an `<ol role=\"list\">`, so it stays a list in Safari with its numbers\n * hidden, and each title is a heading at the level `titleAs` sets. The\n * markers are decoration and hidden from assistive tech, so the states are\n * read as words: `aria-current=\"step\"` on the current item, and \"completed\",\n * \"upcoming\" or \"in progress\" after the other titles, in the language the\n * label props set. Nothing here is a control or a live region, so a timeline\n * that changes on screen keeps a `role=\"status\"` region beside it.\n *\n * @function\n * @param {TimelineProps} props - Props for the Timeline component.\n * @param {React.Ref<HTMLOListElement>} ref - Forwarded ref to the `<ol>`.\n * @returns {JSX.Element} The rendered timeline.\n *\n * @example\n * <Timeline titleAs=\"h3\">\n * <Timeline.Item title=\"Delivered\" time=\"16 October 2026\" dateTime=\"2026-10-16\" />\n * <Timeline.Item title=\"Order placed\" time=\"12 October 2026\" dateTime=\"2026-10-12\" />\n * </Timeline>\n *\n * @example\n * <Timeline titleAs=\"h3\" active={1} pending=\"Out for delivery\">\n * <Timeline.Item title=\"Order placed\" />\n * <Timeline.Item title=\"Shipped\" />\n * </Timeline>\n */\nconst TimelineRoot = forwardRef<HTMLOListElement, TimelineProps>(\n (\n {\n className,\n children,\n active,\n pending,\n align = 'start',\n titleAs = 'h2',\n color,\n completedLabel = 'completed',\n upcomingLabel = 'upcoming',\n pendingLabel = 'in progress',\n textColor,\n bgColor,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const rootClass = usePrefixedClassNames('timeline', {\n 'is-end': align === 'end',\n 'is-alternate': align === 'alternate',\n [`is-${color}`]: isTimelineColor(color),\n });\n const level = validTimelineTitleElements.includes(titleAs) ? titleAs : 'h2';\n const labels: Record<TimelineState, string | undefined> = {\n completed: completedLabel,\n active: undefined,\n upcoming: upcomingLabel,\n pending: pendingLabel,\n };\n const contextFor = (state?: TimelineState) => ({\n titleAs: level,\n state,\n label: state && labels[state],\n });\n // A fraction counts as the item it has reached, so one item is current.\n const reached = typeof active === 'number' ? Math.floor(active) : undefined;\n const stateAt = (index: number): TimelineState | undefined => {\n if (reached === undefined) return undefined;\n if (index === reached) return 'active';\n return index < reached ? 'completed' : 'upcoming';\n };\n\n // Each child gets its state through context rather than a clone, so an\n // app's own component around a Timeline.Item still gets it. Fragments\n // and arrays are opened up first, so each item inside one counts.\n return (\n <ol\n ref={ref}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n {...rest}\n role=\"list\"\n >\n {flattenChildren(children).map((child, index) => (\n <TimelineItemContext.Provider\n key={React.isValidElement(child) ? child.key : index}\n value={contextFor(stateAt(index))}\n >\n {child}\n </TimelineItemContext.Provider>\n ))}\n {isGiven(pending) && (\n <TimelineItemContext.Provider value={contextFor('pending')}>\n <TimelineItem title={pending} />\n </TimelineItemContext.Provider>\n )}\n </ol>\n );\n }\n);\n\nexport const Timeline = withSubComponents(\n TimelineRoot,\n { Item: TimelineItem },\n 'Timeline'\n);\n\nexport default Timeline;\n"],"names":["isGiven","_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Timeline.js","sources":["../../../src/components/Timeline.tsx"],"sourcesContent":["import React, { createContext, forwardRef, useContext } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { flattenChildren } from '../helpers/flattenChildren';\nimport { visuallyHidden } from '../helpers/statusRegion';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Icon } from '../elements/Icon';\nimport { isGiven } from '../helpers/isGiven';\n\nconst validTimelineColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n/** The Bulma colors a marker takes. */\nexport type TimelineColor = (typeof validTimelineColors)[number];\n\nconst validTimelineTitleElements = ['h2', 'h3', 'h4', 'h5', 'h6', 'p'] as const;\n/** What each item's title renders as: a heading level, or `p` for a plain line. */\nexport type TimelineTitleElement = (typeof validTimelineTitleElements)[number];\n\n/** Where the rail goes. */\nexport type TimelineAlign = 'start' | 'end' | 'alternate';\n\n/** Where an item is in a progress timeline. */\ntype TimelineState = 'completed' | 'active' | 'upcoming' | 'pending';\n\n/**\n * What the root hands each of its items: the title's element, and in a\n * progress timeline, the item's state and the words read after its title.\n */\ninterface TimelineItemContextValue {\n titleAs: TimelineTitleElement;\n state?: TimelineState;\n label?: string;\n}\n\n// An item outside a Timeline is a record item with an h2 title.\nconst TimelineItemContext = createContext<TimelineItemContextValue>({\n titleAs: 'h2',\n});\n\nconst isTimelineColor = (color?: string): color is TimelineColor =>\n !!color && (validTimelineColors as readonly string[]).includes(color);\n\n/**\n * Props for the Timeline component. The helper props, the other attributes\n * and the `ref` land on the `<ol>`.\n *\n * @extraProp {React.Ref<HTMLOListElement>} [ref] - Ref forwarded to the `<ol>`.\n */\nexport interface TimelineProps\n extends\n Omit<React.OlHTMLAttributes<HTMLOListElement>, 'color' | 'role'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * `Timeline.Item`s, in the order they're read: newest first or oldest\n * first for a record, oldest first with `active` or `pending`.\n */\n children?: React.ReactNode;\n /**\n * Marks progress. The item at this index, counting the children from 0, is\n * current; the ones before it are completed and the ones after it are\n * upcoming. Leave it out for a record, where nothing is marked. `-1` marks\n * every item upcoming, and an index past the last marks them all completed.\n * A fraction counts as the item it has reached, so `2.5` marks the third\n * item current. Each child counts as one item, with Fragments and arrays opened up, so\n * render one item per child. A component of your own around a\n * `Timeline.Item` still gets its state, but one that renders nothing still\n * counts.\n */\n active?: number;\n /**\n * What's under way, as a last item after the children: its title, read\n * with `pendingLabel`. Write it as words that say so (\"Out for delivery\").\n */\n pending?: React.ReactNode;\n /**\n * `start`: the rail at the start of the line. `end`: at the end, with the\n * text against it. `alternate`: down the middle, the items taking turns and\n * each time across the rail; below Bulma's tablet breakpoint it's `start`.\n */\n align?: TimelineAlign;\n /**\n * What every item's title renders as: a heading at the level under the\n * heading the timeline sits beneath, or `p` for a busy feed.\n */\n titleAs?: TimelineTitleElement;\n /**\n * The markers' color, and the color of progress with `active`. Neutral\n * without it, and Bulma's `link` for progress. The markers are hidden from\n * assistive tech, so say what a color means in the words too.\n */\n color?: TimelineColor;\n /** Read after a completed item's title, visually hidden. In your app's language. */\n completedLabel?: string;\n /** Read after an upcoming item's title, visually hidden. In your app's language. */\n upcomingLabel?: string;\n /** Read after the pending item's title, visually hidden. In your app's language. */\n pendingLabel?: string;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * Props for Timeline.Item, one event. The helper props, the other attributes\n * and the `ref` land on its `<li>`. The native `title` attribute isn't one of\n * them, since `title` here is the event's title.\n *\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TimelineItemProps\n extends\n Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /** What happened, in a line. It renders as the root's `titleAs`. */\n title?: React.ReactNode;\n /**\n * When it happened, as the reader sees it: \"14 October 2026\", \"2 hours\n * ago\". Put the whole date in the words, since screen readers mostly read\n * the text.\n */\n time?: React.ReactNode;\n /**\n * The same moment for machines, as HTML's `datetime` takes it:\n * \"2026-10-14\", \"2026-10-14T08:12\", \"2026-10\". With it, `time` renders in\n * a `<time>`. Keep it the same moment as `time`, since some readers speak it.\n */\n dateTime?: string;\n /**\n * A picture in the marker. A string is an `Icon` name, drawn from the icon\n * library `ConfigProvider` sets, and anything else renders as it is.\n * Without it, the marker is a dot. It's hidden from assistive tech, so\n * what it means goes in the title.\n */\n icon?: React.ReactNode;\n /** This item's marker color, over the root's. Say what it means in the words too. */\n color?: TimelineColor;\n /** Anything else about the event, under the title and the time, as written. */\n children?: React.ReactNode;\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n}\n\n/**\n * One event: a marker on the rail, then its title, its time and anything else about it.\n *\n * Outside a `Timeline` it's a record item with an `h2` title, though the\n * styles are registered on `.timeline`, so the rail and the marker need one.\n *\n * @function\n * @param {TimelineItemProps} props - Props for Timeline.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element} The rendered event.\n *\n * @example\n * <Timeline.Item title=\"Shipped\" time=\"14 October 2026\" dateTime=\"2026-10-14\">\n * Left the warehouse in Leeds.\n * </Timeline.Item>\n */\nexport const TimelineItem = forwardRef<HTMLLIElement, TimelineItemProps>(\n (\n {\n className,\n title,\n time,\n dateTime,\n icon,\n color,\n textColor,\n bgColor,\n children,\n ...props\n },\n ref\n ) => {\n const { titleAs: TitleTag, state, label } = useContext(TimelineItemContext);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const itemClass = usePrefixedClassNames('timeline-item', {\n [`is-${state}`]: !!state,\n [`is-${color}`]: isTimelineColor(color),\n });\n const markerClass = usePrefixedClassNames('timeline-marker', {\n 'is-icon': isGiven(icon),\n });\n const contentClass = usePrefixedClassNames('timeline-content');\n const titleClass = usePrefixedClassNames('timeline-title');\n const timeClass = usePrefixedClassNames('timeline-time');\n\n // The state in words, read after the title so it's in the heading too:\n // \"Packed completed\". The current item has none, since aria-current\n // says it. The styles are inline, so the words stay hidden in a modular\n // build that leaves out Bulma's helper classes.\n const words = label ? (\n <span style={visuallyHidden}>{` ${label}`}</span>\n ) : null;\n\n return (\n <li\n ref={ref}\n className={classNames(itemClass, bulmaHelperClasses, className)}\n {...rest}\n // In a progress timeline the state decides, whatever was passed.\n {...(state && {\n 'aria-current': state === 'active' ? 'step' : undefined,\n })}\n >\n {/* Decoration, hidden with whatever is in it, an Icon's own label\n included: the words say what a color, an icon or a state means. */}\n <div className={markerClass} aria-hidden=\"true\">\n {isGiven(icon) &&\n (typeof icon === 'string' ? <Icon name={icon} /> : icon)}\n </div>\n <div className={contentClass}>\n {isGiven(title) ? (\n <TitleTag className={titleClass}>\n {title}\n {words}\n </TitleTag>\n ) : (\n words\n )}\n {isGiven(time) &&\n (dateTime ? (\n <time className={timeClass} dateTime={dateTime}>\n {time}\n </time>\n ) : (\n <span className={timeClass}>{time}</span>\n ))}\n {children}\n </div>\n </li>\n );\n }\n);\n\nTimelineItem.displayName = 'Timeline.Item';\n\n/**\n * The `Timeline` component renders a list of events in the order they happened, each with a marker on a line down the side.\n *\n * By default it's a record, an order's history, a ticket's activity or a\n * changelog, and it marks nothing. With `active` it marks progress, for\n * something that moves along on its own and is reported to the user: a\n * parcel, a deployment, a claim. That reads oldest first, and `pending` ends\n * it on what's under way. A journey the user moves through themselves, like\n * a wizard or a checkout, is `Steps`.\n *\n * It's an `<ol role=\"list\">`, so it stays a list in Safari with its numbers\n * hidden, and each title is a heading at the level `titleAs` sets. The\n * markers are decoration and hidden from assistive tech, so the states are\n * read as words: `aria-current=\"step\"` on the current item, and \"completed\",\n * \"upcoming\" or \"in progress\" after the other titles, in the language the\n * label props set. Nothing here is a control or a live region, so a timeline\n * that changes on screen keeps a `role=\"status\"` region beside it.\n *\n * @function\n * @param {TimelineProps} props - Props for the Timeline component.\n * @param {React.Ref<HTMLOListElement>} ref - Forwarded ref to the `<ol>`.\n * @returns {JSX.Element} The rendered timeline.\n *\n * @example\n * <Timeline titleAs=\"h3\">\n * <Timeline.Item title=\"Delivered\" time=\"16 October 2026\" dateTime=\"2026-10-16\" />\n * <Timeline.Item title=\"Order placed\" time=\"12 October 2026\" dateTime=\"2026-10-12\" />\n * </Timeline>\n *\n * @example\n * <Timeline titleAs=\"h3\" active={1} pending=\"Out for delivery\">\n * <Timeline.Item title=\"Order placed\" />\n * <Timeline.Item title=\"Shipped\" />\n * </Timeline>\n */\nconst TimelineRoot = forwardRef<HTMLOListElement, TimelineProps>(\n (\n {\n className,\n children,\n active,\n pending,\n align = 'start',\n titleAs = 'h2',\n color,\n completedLabel = 'completed',\n upcomingLabel = 'upcoming',\n pendingLabel = 'in progress',\n textColor,\n bgColor,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n const rootClass = usePrefixedClassNames('timeline', {\n 'is-end': align === 'end',\n 'is-alternate': align === 'alternate',\n [`is-${color}`]: isTimelineColor(color),\n });\n const level = validTimelineTitleElements.includes(titleAs) ? titleAs : 'h2';\n const labels: Record<TimelineState, string | undefined> = {\n completed: completedLabel,\n active: undefined,\n upcoming: upcomingLabel,\n pending: pendingLabel,\n };\n const contextFor = (state?: TimelineState) => ({\n titleAs: level,\n state,\n label: state && labels[state],\n });\n // A fraction counts as the item it has reached, so one item is current.\n const reached = typeof active === 'number' ? Math.floor(active) : undefined;\n const stateAt = (index: number): TimelineState | undefined => {\n if (reached === undefined) return undefined;\n if (index === reached) return 'active';\n return index < reached ? 'completed' : 'upcoming';\n };\n\n // Each child gets its state through context rather than a clone, so an\n // app's own component around a Timeline.Item still gets it. Fragments\n // and arrays are opened up first, so each item inside one counts.\n return (\n <ol\n ref={ref}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n {...rest}\n role=\"list\"\n >\n {flattenChildren(children).map((child, index) => (\n <TimelineItemContext.Provider\n key={React.isValidElement(child) ? child.key : index}\n value={contextFor(stateAt(index))}\n >\n {child}\n </TimelineItemContext.Provider>\n ))}\n {isGiven(pending) && (\n <TimelineItemContext.Provider value={contextFor('pending')}>\n <TimelineItem title={pending} />\n </TimelineItemContext.Provider>\n )}\n </ol>\n );\n }\n);\n\nexport const Timeline = withSubComponents(\n TimelineRoot,\n { Item: TimelineItem },\n 'Timeline'\n);\n\nexport default Timeline;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -11,6 +11,7 @@ import { useTreeView, TreeViewHiddenContext } from '../helpers/useTreeView.js';
11
11
  import { StatusRegion, spokenText } from '../helpers/statusRegion.js';
12
12
  import { Checkbox } from '../form/Checkbox.js';
13
13
  import { Icon } from '../elements/Icon.js';
14
+ import { isGiven } from '../helpers/isGiven.js';
14
15
 
15
16
  const validTreeViewSizes = ['small', 'medium', 'large'];
16
17
  // Not exported, so they stay out of the public API that `index.ts` re-exports.
@@ -21,11 +22,6 @@ const TOP = { path: [], hidden: false };
21
22
  const BranchContext = createContext(TOP);
22
23
  /** The box's input lets the row's click toggle it, so a change on its own does nothing. */
23
24
  const ignoreChange$1 = () => { };
24
- /** Whether an `icon` was given something to render. */
25
- const isGiven$1 = (node) => node !== undefined &&
26
- node !== null &&
27
- typeof node !== 'boolean' &&
28
- node !== '';
29
25
  /**
30
26
  * The `TreeView` component renders a tree of items you browse and pick from, the way a file explorer works: one tab stop, the arrow keys to move, and Right and Left to open and close.
31
27
  *
@@ -144,7 +140,7 @@ const TreeViewItem = forwardRef(function TreeViewItem({ value, label, icon, chil
144
140
  ? null
145
141
  : isLoading
146
142
  ? 'loading'
147
- : isGiven$1(loadError)
143
+ : isGiven(loadError)
148
144
  ? 'error'
149
145
  : null;
150
146
  const labelRef = useRef(null);
@@ -253,7 +249,7 @@ const TreeViewItem = forwardRef(function TreeViewItem({ value, label, icon, chil
253
249
  if (!(event.target instanceof HTMLInputElement)) {
254
250
  event.preventDefault();
255
251
  }
256
- }, children: jsx(Checkbox, { tabIndex: -1, checked: checked === true, indeterminate: checked === 'mixed', disabled: disabled, onChange: ignoreChange$1 }) })), isGiven$1(icon) && (jsx("span", { className: iconClass, "aria-hidden": "true", children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), jsx("span", { className: labelClass, id: labelId, ref: labelRef, children: label })] }), open && (hasItems || status) ? (jsxs("ul", { className: groupClass, role: "group", children: [items, status && (jsx(StatusRow, { kind: status, parent: value, level: branch.path.length + 2, message: loadError, onRetry: onRetry, labelRef: statusLabelRef }))] })) : (items)] }));
252
+ }, children: jsx(Checkbox, { tabIndex: -1, checked: checked === true, indeterminate: checked === 'mixed', disabled: disabled, onChange: ignoreChange$1 }) })), isGiven(icon) && (jsx("span", { className: iconClass, "aria-hidden": "true", children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), jsx("span", { className: labelClass, id: labelId, ref: labelRef, children: label })] }), open && (hasItems || status) ? (jsxs("ul", { className: groupClass, role: "group", children: [items, status && (jsx(StatusRow, { kind: status, parent: value, level: branch.path.length + 2, message: loadError, onRetry: onRetry, labelRef: statusLabelRef }))] })) : (items)] }));
257
253
  });
258
254
  TreeViewItem.displayName = 'TreeView.Item';
259
255
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TreeView.js","sources":["../../../src/components/TreeView.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n TreeViewHiddenContext,\n useTreeView,\n type TreeViewEngine,\n} from '../helpers/useTreeView';\nimport { StatusRegion, spokenText } from '../helpers/statusRegion';\nimport { Checkbox } from '../form/Checkbox';\nimport { Icon } from '../elements/Icon';\n\n/**\n * How items are picked: `none`, nothing is; `single`, one item at a time;\n * `checkbox`, any number, with a box on every item and mixed parents;\n * `checkbox-independent`, any number, with a box on every item that checks\n * that item alone.\n */\nexport type TreeViewSelectionMode =\n 'none' | 'single' | 'checkbox' | 'checkbox-independent';\n\nconst validTreeViewSizes = ['small', 'medium', 'large'] as const;\n\n/** What an open item's load says in the tree's live region. */\ninterface LoadAnnouncement {\n /** The item's key, so what it says next replaces this. */\n key: string;\n /** The key and the kind: the region says it once each time it appears. */\n id: string;\n kind: 'loading' | 'loaded' | 'error';\n /** The item's name, read off its label. */\n name: string;\n /** A failed load's message, read off its row. */\n message: string;\n}\n\n/** What the root hands its items: the engine, the live region, and the rows' words. */\ninterface TreeContextValue extends TreeViewEngine {\n /** Puts what an item's load says in the live region, or takes it out with `null`. */\n announce: (key: string, announcement: LoadAnnouncement | null) => void;\n loadingLabel: string;\n retryLabel: string;\n}\n\n// Not exported, so they stay out of the public API that `index.ts` re-exports.\nconst TreeViewContext = createContext<TreeContextValue | null>(null);\n\nconst sayLoading = (name: string) => `Loading ${name}`;\nconst sayLoaded = (name: string) => `${name} loaded`;\n\n/** Where an item sits: the values of the items above it, and whether one of them is closed. */\ninterface Branch {\n path: string[];\n hidden: boolean;\n}\n\nconst TOP: Branch = { path: [], hidden: false };\nconst BranchContext = createContext<Branch>(TOP);\n\n/** The box's input lets the row's click toggle it, so a change on its own does nothing. */\nconst ignoreChange = () => {};\n\n/** Whether an `icon` was given something to render. */\nconst isGiven = (node: React.ReactNode) =>\n node !== undefined &&\n node !== null &&\n typeof node !== 'boolean' &&\n node !== '';\n\n/**\n * Props for the TreeView component. The helper props, the other attributes\n * and the `ref` land on the `<ul role=\"tree\">`.\n *\n * @extraProp {string} [aria-label] - Names the tree, such as \"Files\". A tree needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.\n */\nexport interface TreeViewProps\n extends\n Omit<\n React.HTMLAttributes<HTMLUListElement>,\n | keyof BulmaClassesProps\n | 'role'\n | 'onSelect'\n | 'defaultValue'\n | 'defaultChecked'\n >,\n BulmaClassesProps {\n /**\n * `TreeView.Item`s, nested inside each other for their children. Render\n * an item's children whenever you have them, open or not: the tree hides\n * them while it's closed.\n */\n children?: React.ReactNode;\n /**\n * `none`: nothing is picked, and Enter and Space open and close a parent.\n * `single`: one item, picked with Enter, Space or a click.\n * `checkbox`: any number, checked with Space or a click. A check reaches\n * every enabled item under it, and a parent with some of them checked is mixed.\n * `checkbox-independent`: any number, checked with Space or a click, each\n * box for its own item. A check reaches nothing under it, and no parent is\n * mixed (Mantine's and Ant Design's `checkStrictly`).\n */\n selectionMode?: TreeViewSelectionMode;\n /**\n * The selected item's value when you hold the state, or `null` for none.\n * Read with `single` only. Picking an item then only calls\n * `onSelectedChange`, and nothing changes until you pass the new value.\n */\n selected?: string | null;\n /** The item selected to begin with, when the tree holds its own state. Read with `single` only. */\n defaultSelected?: string | null;\n /**\n * Called with the value of the item picked. Not called for the one\n * already selected, and moving focus never calls it.\n */\n onSelectedChange?: (value: string) => void;\n /**\n * The checked items' values when you hold the state. Read with `checkbox`\n * and `checkbox-independent` only. A value checks its item. In `checkbox`,\n * an enabled item also counts as checked when any item above it is in the\n * list, so a parent's value stands for its whole branch, loaded or not, and\n * a disabled item is checked only by its own value. In\n * `checkbox-independent`, a value checks its own item and nothing else.\n */\n checked?: string[];\n /** The values checked to begin with, when the tree holds its own state. Read with `checkbox` and `checkbox-independent` only. */\n defaultChecked?: string[];\n /**\n * Called after a check or an uncheck. In `checkbox`, with every item that\n * now shows checked, parents included, plus any earlier value that matches\n * no item the tree knows, left as it was, and the order means nothing. In\n * `checkbox-independent`, with the list as it was, the item's value added\n * at the end or every copy of it taken out, and everything else in the\n * same order. Passed back as `checked`, the list shows the same boxes.\n */\n onCheckedChange?: (checked: string[]) => void;\n /**\n * The open items' values when you hold the state. A value stays in the\n * list while its item's parent is closed, so the item reopens as it was.\n */\n expanded?: string[];\n /** The items open to begin with, when the tree holds its own state. */\n defaultExpanded?: string[];\n /** Called with the new list whenever an item opens or closes, `*` included. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */\n size?: 'small' | 'medium' | 'large';\n /** What the row in a loading item's group says. In your app's language. */\n loadingLabel?: string;\n /** The Retry button's text on a failed load's row. In your app's language. */\n retryLabel?: string;\n /**\n * What the live region says when an open item starts loading, built from\n * the item's name. In your app's language. Default: `` `Loading ${name}` ``.\n */\n loadingAnnouncement?: (name: string) => string;\n /**\n * What the live region says when that load finishes. In your app's\n * language. Default: `` `${name} loaded` ``.\n */\n loadedAnnouncement?: (name: string) => string;\n}\n\n/**\n * Props for TreeView.Item, one row and, nested in it, its children. The other\n * attributes and the `ref` land on its `<li role=\"treeitem\">`.\n *\n * @extraProp {number} [aria-posinset] - The item's number among the items beside it. The tree declares it, and `aria-setsize`, from the items on the page once it mounts. When the page holds only part of a set, such as the first page of a long folder, pass both on every item of that set: yours win, and the tree's own stay on any item without them.\n * @extraProp {number} [aria-setsize] - How many items sit beside it, itself included. Declared by the tree like `aria-posinset`, and `-1` says the count isn't known.\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TreeViewItemProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'role' | 'value' | 'onSelect' | 'children'\n> {\n /** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */\n value: string;\n /**\n * **Required.** What the row shows, and the item's name for assistive\n * tech. Nothing in it should be a link or a button: a tree item does one\n * thing, and nothing else in its row takes focus.\n */\n label: React.ReactNode;\n /** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */\n icon?: React.ReactNode;\n /**\n * `TreeView.Item`s under this one. Render them whenever you have them,\n * open or not: the tree hides them while it's closed, and a `checkbox` tree\n * needs them to know what a check reaches.\n */\n children?: React.ReactNode;\n /** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */\n hasChildren?: boolean;\n /**\n * Its children are on their way. While it's open, its group ends in a row\n * that says so, and the tree's live region says it's loading, then that\n * it's loaded once this goes back to `false`. A parent only: pair it with\n * `hasChildren`, or with the children it already has.\n */\n isLoading?: boolean;\n /**\n * Its children didn't load. While it's open, its group ends in a row with\n * this message, and a Retry button when there's an `onRetry`, and the live\n * region reads the message out, so name the item in it (\"Couldn't load\n * src\"), then says it's loaded once this goes with the item still open. A\n * parent only, like `isLoading`. Nothing in it should be a link or a\n * button: the row is what's pressed. `isLoading` wins while both are given.\n */\n loadError?: React.ReactNode;\n /**\n * Called by the Retry button on a failed load's row, and by Enter or Space\n * there. Set `isLoading` while the retry runs, so the live region says it's\n * loading, and reads the message out again if it fails again. The same\n * message passed a second time with no loading between is no change the\n * tree can see.\n */\n onRetry?: () => void;\n /**\n * Reachable with the arrow keys, Home, End and type-ahead, so a screen\n * reader finds it, but never selected, checked, opened or closed. One\n * that's already open stays open.\n */\n disabled?: boolean;\n}\n\n/**\n * The `TreeView` component renders a tree of items you browse and pick from, the way a file explorer works: one tab stop, the arrow keys to move, and Right and Left to open and close.\n *\n * It's the APG Tree View pattern, drawn to look like Bulma's menu. It isn't\n * for site navigation: items aren't links, and a sidebar whose sections open\n * and close is `Menu`'s job. The root owns which items are open, through\n * `expanded`, `defaultExpanded` and `onExpandedChange`.\n *\n * `selectionMode` picks the kind of tree. With `none`, nothing is picked.\n * With `single`, one item is, and `selected` says which. With `checkbox`,\n * each item has a box, a check reaches every enabled item under it, closed\n * branches included, and a parent with some of its items checked is mixed.\n * With `checkbox-independent`, each item has a box that checks that item\n * alone, so a parent means only itself and is never mixed. `selected` is\n * read in a `single` tree only, and `checked` in the two checkbox trees only.\n * Selection never follows focus.\n *\n * Disabled items stay reachable from the keys, so a screen reader finds\n * them. The tree needs a name, from `aria-label` or `aria-labelledby`, and a\n * development build warns when it has neither.\n *\n * @function\n * @param {TreeViewProps} props - Props for the TreeView component.\n * @param {React.Ref<HTMLUListElement>} ref - Forwarded ref to the `<ul>`.\n * @returns {JSX.Element} The rendered tree.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ | APG Tree View Pattern}\n *\n * @example\n * <TreeView aria-label=\"Files\" selectionMode=\"single\" defaultExpanded={['src']}>\n * <TreeView.Item value=\"src\" label=\"src\" icon=\"folder\">\n * <TreeView.Item value=\"src/index.ts\" label=\"index.ts\" icon=\"file\" />\n * </TreeView.Item>\n * <TreeView.Item value=\"package.json\" label=\"package.json\" icon=\"file\" />\n * </TreeView>\n */\nconst TreeViewRoot = forwardRef<HTMLUListElement, TreeViewProps>(\n function TreeView(\n {\n children,\n selectionMode = 'none',\n selected,\n defaultSelected = null,\n onSelectedChange,\n checked,\n defaultChecked = [],\n onCheckedChange,\n expanded,\n defaultExpanded = [],\n onExpandedChange,\n size,\n loadingLabel = 'Loading…',\n retryLabel = 'Retry',\n loadingAnnouncement,\n loadedAnnouncement,\n className,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n const engine = useTreeView({\n mode: selectionMode,\n selected,\n defaultSelected,\n onSelectedChange,\n checked,\n defaultChecked,\n onCheckedChange,\n expanded,\n defaultExpanded,\n onExpandedChange,\n });\n\n const { treeRef } = engine;\n const setRefs = useCallback(\n (node: HTMLUListElement | null) => {\n treeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref, treeRef]\n );\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'TreeView:unnamed',\n '[bestax-bulma] <TreeView> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the tree holds.'\n );\n }\n }, [named]);\n\n const rootClass = usePrefixedClassNames('tree-view', {\n [`is-${size}`]:\n !!size && (validTreeViewSizes as readonly string[]).includes(size),\n });\n\n // What each open item's load says, in the order they started saying it.\n const [announcements, setAnnouncements] = useState<LoadAnnouncement[]>([]);\n const announce = useCallback(\n (key: string, announcement: LoadAnnouncement | null) => {\n setAnnouncements(current => {\n const others = current.filter(said => said.key !== key);\n return announcement ? [...others, announcement] : others;\n });\n },\n []\n );\n const describe = useCallback(\n ({ kind, name, message }: LoadAnnouncement) => {\n if (kind === 'error') return message;\n const say =\n kind === 'loading'\n ? (loadingAnnouncement ?? sayLoading)\n : (loadedAnnouncement ?? sayLoaded);\n return say(name);\n },\n [loadingAnnouncement, loadedAnnouncement]\n );\n\n // The props are spread first, so the role and the attributes the tree\n // owns win over anything a caller passes along. The live region sits\n // beside the tree, since a tree holds items and groups only, and it's\n // there from the start, so a screen reader is listening to it before\n // anything is written into it.\n return (\n <TreeViewContext.Provider\n value={{ ...engine, announce, loadingLabel, retryLabel }}\n >\n <BranchContext.Provider value={TOP}>\n <ul\n {...rest}\n ref={setRefs}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n role=\"tree\"\n aria-multiselectable={engine.multiselectable || undefined}\n >\n {children}\n </ul>\n </BranchContext.Provider>\n <StatusRegion items={announcements} describe={describe} />\n </TreeViewContext.Provider>\n );\n }\n);\n\n/**\n * One item in the tree: a row with its chevron, its box, its icon and its label, and, while it's open, a group of the items under it.\n *\n * @function\n * @param {TreeViewItemProps} props - Props for TreeView.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element | null} The rendered item, or nothing under a closed one.\n */\nexport const TreeViewItem = forwardRef<HTMLLIElement, TreeViewItemProps>(\n function TreeViewItem(\n {\n value,\n label,\n icon,\n children,\n hasChildren = false,\n isLoading = false,\n loadError,\n onRetry,\n disabled = false,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const tree = useContext(TreeViewContext);\n const branch = useContext(BranchContext);\n // Hidden by a component around the tree, such as TreeSelect's search,\n // it renders as an item under a closed parent does.\n const hiddenItems = useContext(TreeViewHiddenContext);\n const hiddenHere = branch.hidden || hiddenItems.has(value);\n // Also the item's key in the live region.\n const labelId = useId();\n const hasItems = React.Children.toArray(children).length > 0;\n const isParent = hasItems || hasChildren;\n const open = isParent && !!tree?.isOpen(value);\n const parent = branch.path[branch.path.length - 1] ?? null;\n\n // The row at the end of its group, while it's open and on the page.\n const shown = open && !hiddenHere;\n const status = !shown\n ? null\n : isLoading\n ? 'loading'\n : isGiven(loadError)\n ? 'error'\n : null;\n const labelRef = useRef<HTMLSpanElement | null>(null);\n const statusLabelRef = useRef<HTMLSpanElement | null>(null);\n\n // What the live region says follows the row: it's loading, or it failed,\n // while the row says so, and it's loaded once the row goes with the item\n // still open, whichever row it was, until the item closes or loads again.\n // A closed item says nothing, loading or not.\n const phase = shown ? (status ?? 'open') : 'closed';\n const lastPhaseRef = useRef(phase);\n const announce = tree?.announce;\n useEffect(() => {\n const was = lastPhaseRef.current;\n lastPhaseRef.current = phase;\n const kind =\n phase === 'loading' || phase === 'error'\n ? phase\n : phase === 'open' && (was === 'loading' || was === 'error')\n ? 'loaded'\n : null;\n if (!kind) return undefined;\n // Only an item inside a tree can be open.\n announce!(labelId, {\n key: labelId,\n id: `${labelId}:${kind}`,\n kind,\n name: spokenText(labelRef.current!),\n message: kind === 'error' ? spokenText(statusLabelRef.current!) : '',\n });\n return () => announce!(labelId, null);\n }, [phase, announce, labelId]);\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const groupClass = usePrefixedClassNames('tree-view-group');\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const checkClass = usePrefixedClassNames('tree-view-check');\n const iconClass = usePrefixedClassNames('tree-view-icon');\n const labelClass = usePrefixedClassNames('tree-view-label');\n\n const register = tree?.register;\n useClientLayoutEffect(() => {\n if (!register) {\n warnOnce(\n 'TreeView.Item:outside',\n '[bestax-bulma] <TreeView.Item> is outside a <TreeView>, so it ' +\n 'renders nothing. Put it inside one.'\n );\n return undefined;\n }\n return register(value, { parent, disabled, isParent });\n }, [register, value, parent, disabled, isParent]);\n\n const setElement = tree?.setElement;\n const setRefs = useCallback(\n (node: HTMLLIElement | null) => {\n // Only an item inside a tree renders an element to hand over.\n setElement!(value, node);\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [setElement, value, ref]\n );\n const rowRef = useRef<HTMLDivElement | null>(null);\n const toggleRef = useRef<HTMLSpanElement | null>(null);\n\n const childBranch = useMemo(\n () => ({\n path: [...branch.path, value],\n hidden: hiddenHere || !open,\n }),\n [branch, value, hiddenHere, open]\n );\n\n const { selected, checked } =\n tree?.stateOf(value, branch.path, disabled) ?? {};\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-selected': selected,\n 'is-disabled': disabled,\n });\n\n if (!tree) return null;\n\n // While it's open the children render in its group. In a `checkbox` tree\n // they render while it's closed or hidden too, drawing nothing, so a\n // check knows what's under it.\n const items = (shown || tree.rendersClosed) && (\n <BranchContext.Provider value={childBranch}>\n {children}\n </BranchContext.Provider>\n );\n if (hiddenHere) return <>{items}</>;\n\n const info = { value, parent, disabled, isParent, open };\n // A position the caller gives wins, for a set the page holds only part of.\n const position = tree.positionOf(value);\n\n return (\n <li\n {...props}\n ref={setRefs}\n className={classNames(itemClass, className)}\n role=\"treeitem\"\n aria-labelledby={labelId}\n aria-level={branch.path.length + 1}\n aria-posinset={props['aria-posinset'] ?? position?.posinset}\n aria-setsize={props['aria-setsize'] ?? position?.setsize}\n aria-expanded={isParent ? open : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={selected}\n aria-checked={checked}\n tabIndex={tree.tabStop === value ? 0 : -1}\n onKeyDown={event => {\n onKeyDown?.(event);\n tree.onKeyDown(event, info);\n }}\n onFocus={event => {\n onFocus?.(event);\n if (event.target === event.currentTarget) {\n tree.onFocus(value, event.currentTarget);\n }\n }}\n onBlur={event => {\n onBlur?.(event);\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => {\n onClick?.(event);\n // A click in its row is its own, and so is one on the item itself,\n // as a test's click on the treeitem is. One in its group belongs\n // to the item inside it, or to nothing. The chevron's box is on\n // every row, but it's a chevron only on a parent: on a leaf it's\n // more of the row.\n const target = event.target as Node;\n if (\n target === event.currentTarget ||\n rowRef.current!.contains(target)\n ) {\n tree.onClick(\n event.currentTarget,\n info,\n isParent && toggleRef.current!.contains(target)\n );\n }\n }}\n >\n <div className={rowClass} ref={rowRef}>\n <span className={toggleClass} aria-hidden=\"true\" ref={toggleRef} />\n {checked !== undefined && (\n <span\n className={checkClass}\n aria-hidden=\"true\"\n onClick={event => {\n // A click on the box's label is followed by one on its\n // input, and both reach the item. The label's is cancelled,\n // so the item toggles once.\n if (!(event.target instanceof HTMLInputElement)) {\n event.preventDefault();\n }\n }}\n >\n <Checkbox\n tabIndex={-1}\n checked={checked === true}\n indeterminate={checked === 'mixed'}\n disabled={disabled}\n onChange={ignoreChange}\n />\n </span>\n )}\n {isGiven(icon) && (\n <span className={iconClass} aria-hidden=\"true\">\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </span>\n )}\n <span className={labelClass} id={labelId} ref={labelRef}>\n {label}\n </span>\n </div>\n {open && (hasItems || status) ? (\n <ul className={groupClass} role=\"group\">\n {items}\n {status && (\n <StatusRow\n kind={status}\n parent={value}\n level={branch.path.length + 2}\n message={loadError}\n onRetry={onRetry}\n labelRef={statusLabelRef}\n />\n )}\n </ul>\n ) : (\n items\n )}\n </li>\n );\n }\n);\n\nTreeViewItem.displayName = 'TreeView.Item';\n\n/** Props for the row at the end of a loading item's group, or a failed load's. */\ninterface StatusRowProps {\n /** `loading`, or `error` for a load that failed. */\n kind: 'loading' | 'error';\n /** The value of the item it's in. */\n parent: string;\n /** Its `aria-level`, one under the item it's in. */\n level: number;\n /** A failed load's message. */\n message: React.ReactNode;\n /** Retries a failed load. */\n onRetry?: () => void;\n /** For its label, which the item reads a failed load's message off. */\n labelRef: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * The row at the end of a loading item's group, or of one whose load failed.\n * It's a `treeitem` the keys reach, the way they reach a disabled item, so a\n * screen reader finds it. It has no value and no record, so it's never\n * selected or checked, and a check never counts it. A failed load's row with\n * `onRetry` retries with Enter, Space or a click, and any other is disabled.\n * The Retry button is drawn, hidden from assistive tech and out of the tab\n * order, the way an item's box is: the row is what's pressed, and its name\n * says so. Rendered in one place, a failed load's row that starts loading\n * again is the same element, so focus stays on it.\n */\nfunction StatusRow({\n kind,\n parent,\n level,\n message,\n onRetry,\n labelRef,\n}: StatusRowProps) {\n // Only an item inside a tree renders a group.\n const tree = useContext(TreeViewContext)!;\n // Also its key in the registry and for the tab stop, where an item has its value.\n const labelId = useId();\n const retryId = useId();\n const retry = kind === 'error' ? onRetry : undefined;\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-disabled': !retry,\n });\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const labelClass = usePrefixedClassNames('tree-view-label');\n const loaderClass = usePrefixedClassNames('loader');\n const retryClass = usePrefixedClassNames('button', { 'is-small': true });\n\n const { setElement } = tree;\n const setRef = useCallback(\n (node: HTMLLIElement | null) => setElement(labelId, node),\n [setElement, labelId]\n );\n const info = {\n value: labelId,\n parent,\n disabled: !retry,\n isParent: false,\n open: false,\n retry,\n };\n const position = tree.positionOf(labelId);\n\n return (\n <li\n ref={setRef}\n className={itemClass}\n role=\"treeitem\"\n aria-labelledby={retry ? `${labelId} ${retryId}` : labelId}\n aria-level={level}\n aria-posinset={position?.posinset}\n aria-setsize={position?.setsize}\n aria-disabled={!retry || undefined}\n tabIndex={tree.tabStop === labelId ? 0 : -1}\n onKeyDown={event => tree.onKeyDown(event, info)}\n onFocus={event => {\n // Focus in something the message holds isn't the row's.\n if (event.target === event.currentTarget) {\n tree.onFocus(labelId, event.currentTarget);\n }\n }}\n onBlur={event => {\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => tree.onClick(event.currentTarget, info, false)}\n >\n <div className={rowClass}>\n <span className={toggleClass} aria-hidden=\"true\">\n {kind === 'loading' && <span className={loaderClass} />}\n </span>\n <span className={labelClass} id={labelId} ref={labelRef}>\n {kind === 'loading' ? tree.loadingLabel : message}\n </span>\n {retry && (\n <span className={retryClass} id={retryId} aria-hidden=\"true\">\n {tree.retryLabel}\n </span>\n )}\n </div>\n </li>\n );\n}\n\nexport const TreeView = withSubComponents(\n TreeViewRoot,\n { Item: TreeViewItem },\n 'TreeView'\n);\n\nexport default TreeView;\n"],"names":["ignoreChange","isGiven","_jsxs","_jsx","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"TreeView.js","sources":["../../../src/components/TreeView.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n TreeViewHiddenContext,\n useTreeView,\n type TreeViewEngine,\n} from '../helpers/useTreeView';\nimport { StatusRegion, spokenText } from '../helpers/statusRegion';\nimport { Checkbox } from '../form/Checkbox';\nimport { Icon } from '../elements/Icon';\nimport { isGiven } from '../helpers/isGiven';\n\n/**\n * How items are picked: `none`, nothing is; `single`, one item at a time;\n * `checkbox`, any number, with a box on every item and mixed parents;\n * `checkbox-independent`, any number, with a box on every item that checks\n * that item alone.\n */\nexport type TreeViewSelectionMode =\n 'none' | 'single' | 'checkbox' | 'checkbox-independent';\n\nconst validTreeViewSizes = ['small', 'medium', 'large'] as const;\n\n/** What an open item's load says in the tree's live region. */\ninterface LoadAnnouncement {\n /** The item's key, so what it says next replaces this. */\n key: string;\n /** The key and the kind: the region says it once each time it appears. */\n id: string;\n kind: 'loading' | 'loaded' | 'error';\n /** The item's name, read off its label. */\n name: string;\n /** A failed load's message, read off its row. */\n message: string;\n}\n\n/** What the root hands its items: the engine, the live region, and the rows' words. */\ninterface TreeContextValue extends TreeViewEngine {\n /** Puts what an item's load says in the live region, or takes it out with `null`. */\n announce: (key: string, announcement: LoadAnnouncement | null) => void;\n loadingLabel: string;\n retryLabel: string;\n}\n\n// Not exported, so they stay out of the public API that `index.ts` re-exports.\nconst TreeViewContext = createContext<TreeContextValue | null>(null);\n\nconst sayLoading = (name: string) => `Loading ${name}`;\nconst sayLoaded = (name: string) => `${name} loaded`;\n\n/** Where an item sits: the values of the items above it, and whether one of them is closed. */\ninterface Branch {\n path: string[];\n hidden: boolean;\n}\n\nconst TOP: Branch = { path: [], hidden: false };\nconst BranchContext = createContext<Branch>(TOP);\n\n/** The box's input lets the row's click toggle it, so a change on its own does nothing. */\nconst ignoreChange = () => {};\n\n/**\n * Props for the TreeView component. The helper props, the other attributes\n * and the `ref` land on the `<ul role=\"tree\">`.\n *\n * @extraProp {string} [aria-label] - Names the tree, such as \"Files\". A tree needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.\n */\nexport interface TreeViewProps\n extends\n Omit<\n React.HTMLAttributes<HTMLUListElement>,\n | keyof BulmaClassesProps\n | 'role'\n | 'onSelect'\n | 'defaultValue'\n | 'defaultChecked'\n >,\n BulmaClassesProps {\n /**\n * `TreeView.Item`s, nested inside each other for their children. Render\n * an item's children whenever you have them, open or not: the tree hides\n * them while it's closed.\n */\n children?: React.ReactNode;\n /**\n * `none`: nothing is picked, and Enter and Space open and close a parent.\n * `single`: one item, picked with Enter, Space or a click.\n * `checkbox`: any number, checked with Space or a click. A check reaches\n * every enabled item under it, and a parent with some of them checked is mixed.\n * `checkbox-independent`: any number, checked with Space or a click, each\n * box for its own item. A check reaches nothing under it, and no parent is\n * mixed (Mantine's and Ant Design's `checkStrictly`).\n */\n selectionMode?: TreeViewSelectionMode;\n /**\n * The selected item's value when you hold the state, or `null` for none.\n * Read with `single` only. Picking an item then only calls\n * `onSelectedChange`, and nothing changes until you pass the new value.\n */\n selected?: string | null;\n /** The item selected to begin with, when the tree holds its own state. Read with `single` only. */\n defaultSelected?: string | null;\n /**\n * Called with the value of the item picked. Not called for the one\n * already selected, and moving focus never calls it.\n */\n onSelectedChange?: (value: string) => void;\n /**\n * The checked items' values when you hold the state. Read with `checkbox`\n * and `checkbox-independent` only. A value checks its item. In `checkbox`,\n * an enabled item also counts as checked when any item above it is in the\n * list, so a parent's value stands for its whole branch, loaded or not, and\n * a disabled item is checked only by its own value. In\n * `checkbox-independent`, a value checks its own item and nothing else.\n */\n checked?: string[];\n /** The values checked to begin with, when the tree holds its own state. Read with `checkbox` and `checkbox-independent` only. */\n defaultChecked?: string[];\n /**\n * Called after a check or an uncheck. In `checkbox`, with every item that\n * now shows checked, parents included, plus any earlier value that matches\n * no item the tree knows, left as it was, and the order means nothing. In\n * `checkbox-independent`, with the list as it was, the item's value added\n * at the end or every copy of it taken out, and everything else in the\n * same order. Passed back as `checked`, the list shows the same boxes.\n */\n onCheckedChange?: (checked: string[]) => void;\n /**\n * The open items' values when you hold the state. A value stays in the\n * list while its item's parent is closed, so the item reopens as it was.\n */\n expanded?: string[];\n /** The items open to begin with, when the tree holds its own state. */\n defaultExpanded?: string[];\n /** Called with the new list whenever an item opens or closes, `*` included. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */\n size?: 'small' | 'medium' | 'large';\n /** What the row in a loading item's group says. In your app's language. */\n loadingLabel?: string;\n /** The Retry button's text on a failed load's row. In your app's language. */\n retryLabel?: string;\n /**\n * What the live region says when an open item starts loading, built from\n * the item's name. In your app's language. Default: `` `Loading ${name}` ``.\n */\n loadingAnnouncement?: (name: string) => string;\n /**\n * What the live region says when that load finishes. In your app's\n * language. Default: `` `${name} loaded` ``.\n */\n loadedAnnouncement?: (name: string) => string;\n}\n\n/**\n * Props for TreeView.Item, one row and, nested in it, its children. The other\n * attributes and the `ref` land on its `<li role=\"treeitem\">`.\n *\n * @extraProp {number} [aria-posinset] - The item's number among the items beside it. The tree declares it, and `aria-setsize`, from the items on the page once it mounts. When the page holds only part of a set, such as the first page of a long folder, pass both on every item of that set: yours win, and the tree's own stay on any item without them.\n * @extraProp {number} [aria-setsize] - How many items sit beside it, itself included. Declared by the tree like `aria-posinset`, and `-1` says the count isn't known.\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TreeViewItemProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'role' | 'value' | 'onSelect' | 'children'\n> {\n /** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */\n value: string;\n /**\n * **Required.** What the row shows, and the item's name for assistive\n * tech. Nothing in it should be a link or a button: a tree item does one\n * thing, and nothing else in its row takes focus.\n */\n label: React.ReactNode;\n /** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */\n icon?: React.ReactNode;\n /**\n * `TreeView.Item`s under this one. Render them whenever you have them,\n * open or not: the tree hides them while it's closed, and a `checkbox` tree\n * needs them to know what a check reaches.\n */\n children?: React.ReactNode;\n /** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */\n hasChildren?: boolean;\n /**\n * Its children are on their way. While it's open, its group ends in a row\n * that says so, and the tree's live region says it's loading, then that\n * it's loaded once this goes back to `false`. A parent only: pair it with\n * `hasChildren`, or with the children it already has.\n */\n isLoading?: boolean;\n /**\n * Its children didn't load. While it's open, its group ends in a row with\n * this message, and a Retry button when there's an `onRetry`, and the live\n * region reads the message out, so name the item in it (\"Couldn't load\n * src\"), then says it's loaded once this goes with the item still open. A\n * parent only, like `isLoading`. Nothing in it should be a link or a\n * button: the row is what's pressed. `isLoading` wins while both are given.\n */\n loadError?: React.ReactNode;\n /**\n * Called by the Retry button on a failed load's row, and by Enter or Space\n * there. Set `isLoading` while the retry runs, so the live region says it's\n * loading, and reads the message out again if it fails again. The same\n * message passed a second time with no loading between is no change the\n * tree can see.\n */\n onRetry?: () => void;\n /**\n * Reachable with the arrow keys, Home, End and type-ahead, so a screen\n * reader finds it, but never selected, checked, opened or closed. One\n * that's already open stays open.\n */\n disabled?: boolean;\n}\n\n/**\n * The `TreeView` component renders a tree of items you browse and pick from, the way a file explorer works: one tab stop, the arrow keys to move, and Right and Left to open and close.\n *\n * It's the APG Tree View pattern, drawn to look like Bulma's menu. It isn't\n * for site navigation: items aren't links, and a sidebar whose sections open\n * and close is `Menu`'s job. The root owns which items are open, through\n * `expanded`, `defaultExpanded` and `onExpandedChange`.\n *\n * `selectionMode` picks the kind of tree. With `none`, nothing is picked.\n * With `single`, one item is, and `selected` says which. With `checkbox`,\n * each item has a box, a check reaches every enabled item under it, closed\n * branches included, and a parent with some of its items checked is mixed.\n * With `checkbox-independent`, each item has a box that checks that item\n * alone, so a parent means only itself and is never mixed. `selected` is\n * read in a `single` tree only, and `checked` in the two checkbox trees only.\n * Selection never follows focus.\n *\n * Disabled items stay reachable from the keys, so a screen reader finds\n * them. The tree needs a name, from `aria-label` or `aria-labelledby`, and a\n * development build warns when it has neither.\n *\n * @function\n * @param {TreeViewProps} props - Props for the TreeView component.\n * @param {React.Ref<HTMLUListElement>} ref - Forwarded ref to the `<ul>`.\n * @returns {JSX.Element} The rendered tree.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ | APG Tree View Pattern}\n *\n * @example\n * <TreeView aria-label=\"Files\" selectionMode=\"single\" defaultExpanded={['src']}>\n * <TreeView.Item value=\"src\" label=\"src\" icon=\"folder\">\n * <TreeView.Item value=\"src/index.ts\" label=\"index.ts\" icon=\"file\" />\n * </TreeView.Item>\n * <TreeView.Item value=\"package.json\" label=\"package.json\" icon=\"file\" />\n * </TreeView>\n */\nconst TreeViewRoot = forwardRef<HTMLUListElement, TreeViewProps>(\n function TreeView(\n {\n children,\n selectionMode = 'none',\n selected,\n defaultSelected = null,\n onSelectedChange,\n checked,\n defaultChecked = [],\n onCheckedChange,\n expanded,\n defaultExpanded = [],\n onExpandedChange,\n size,\n loadingLabel = 'Loading…',\n retryLabel = 'Retry',\n loadingAnnouncement,\n loadedAnnouncement,\n className,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n const engine = useTreeView({\n mode: selectionMode,\n selected,\n defaultSelected,\n onSelectedChange,\n checked,\n defaultChecked,\n onCheckedChange,\n expanded,\n defaultExpanded,\n onExpandedChange,\n });\n\n const { treeRef } = engine;\n const setRefs = useCallback(\n (node: HTMLUListElement | null) => {\n treeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref, treeRef]\n );\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'TreeView:unnamed',\n '[bestax-bulma] <TreeView> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the tree holds.'\n );\n }\n }, [named]);\n\n const rootClass = usePrefixedClassNames('tree-view', {\n [`is-${size}`]:\n !!size && (validTreeViewSizes as readonly string[]).includes(size),\n });\n\n // What each open item's load says, in the order they started saying it.\n const [announcements, setAnnouncements] = useState<LoadAnnouncement[]>([]);\n const announce = useCallback(\n (key: string, announcement: LoadAnnouncement | null) => {\n setAnnouncements(current => {\n const others = current.filter(said => said.key !== key);\n return announcement ? [...others, announcement] : others;\n });\n },\n []\n );\n const describe = useCallback(\n ({ kind, name, message }: LoadAnnouncement) => {\n if (kind === 'error') return message;\n const say =\n kind === 'loading'\n ? (loadingAnnouncement ?? sayLoading)\n : (loadedAnnouncement ?? sayLoaded);\n return say(name);\n },\n [loadingAnnouncement, loadedAnnouncement]\n );\n\n // The props are spread first, so the role and the attributes the tree\n // owns win over anything a caller passes along. The live region sits\n // beside the tree, since a tree holds items and groups only, and it's\n // there from the start, so a screen reader is listening to it before\n // anything is written into it.\n return (\n <TreeViewContext.Provider\n value={{ ...engine, announce, loadingLabel, retryLabel }}\n >\n <BranchContext.Provider value={TOP}>\n <ul\n {...rest}\n ref={setRefs}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n role=\"tree\"\n aria-multiselectable={engine.multiselectable || undefined}\n >\n {children}\n </ul>\n </BranchContext.Provider>\n <StatusRegion items={announcements} describe={describe} />\n </TreeViewContext.Provider>\n );\n }\n);\n\n/**\n * One item in the tree: a row with its chevron, its box, its icon and its label, and, while it's open, a group of the items under it.\n *\n * @function\n * @param {TreeViewItemProps} props - Props for TreeView.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element | null} The rendered item, or nothing under a closed one.\n */\nexport const TreeViewItem = forwardRef<HTMLLIElement, TreeViewItemProps>(\n function TreeViewItem(\n {\n value,\n label,\n icon,\n children,\n hasChildren = false,\n isLoading = false,\n loadError,\n onRetry,\n disabled = false,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const tree = useContext(TreeViewContext);\n const branch = useContext(BranchContext);\n // Hidden by a component around the tree, such as TreeSelect's search,\n // it renders as an item under a closed parent does.\n const hiddenItems = useContext(TreeViewHiddenContext);\n const hiddenHere = branch.hidden || hiddenItems.has(value);\n // Also the item's key in the live region.\n const labelId = useId();\n const hasItems = React.Children.toArray(children).length > 0;\n const isParent = hasItems || hasChildren;\n const open = isParent && !!tree?.isOpen(value);\n const parent = branch.path[branch.path.length - 1] ?? null;\n\n // The row at the end of its group, while it's open and on the page.\n const shown = open && !hiddenHere;\n const status = !shown\n ? null\n : isLoading\n ? 'loading'\n : isGiven(loadError)\n ? 'error'\n : null;\n const labelRef = useRef<HTMLSpanElement | null>(null);\n const statusLabelRef = useRef<HTMLSpanElement | null>(null);\n\n // What the live region says follows the row: it's loading, or it failed,\n // while the row says so, and it's loaded once the row goes with the item\n // still open, whichever row it was, until the item closes or loads again.\n // A closed item says nothing, loading or not.\n const phase = shown ? (status ?? 'open') : 'closed';\n const lastPhaseRef = useRef(phase);\n const announce = tree?.announce;\n useEffect(() => {\n const was = lastPhaseRef.current;\n lastPhaseRef.current = phase;\n const kind =\n phase === 'loading' || phase === 'error'\n ? phase\n : phase === 'open' && (was === 'loading' || was === 'error')\n ? 'loaded'\n : null;\n if (!kind) return undefined;\n // Only an item inside a tree can be open.\n announce!(labelId, {\n key: labelId,\n id: `${labelId}:${kind}`,\n kind,\n name: spokenText(labelRef.current!),\n message: kind === 'error' ? spokenText(statusLabelRef.current!) : '',\n });\n return () => announce!(labelId, null);\n }, [phase, announce, labelId]);\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const groupClass = usePrefixedClassNames('tree-view-group');\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const checkClass = usePrefixedClassNames('tree-view-check');\n const iconClass = usePrefixedClassNames('tree-view-icon');\n const labelClass = usePrefixedClassNames('tree-view-label');\n\n const register = tree?.register;\n useClientLayoutEffect(() => {\n if (!register) {\n warnOnce(\n 'TreeView.Item:outside',\n '[bestax-bulma] <TreeView.Item> is outside a <TreeView>, so it ' +\n 'renders nothing. Put it inside one.'\n );\n return undefined;\n }\n return register(value, { parent, disabled, isParent });\n }, [register, value, parent, disabled, isParent]);\n\n const setElement = tree?.setElement;\n const setRefs = useCallback(\n (node: HTMLLIElement | null) => {\n // Only an item inside a tree renders an element to hand over.\n setElement!(value, node);\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [setElement, value, ref]\n );\n const rowRef = useRef<HTMLDivElement | null>(null);\n const toggleRef = useRef<HTMLSpanElement | null>(null);\n\n const childBranch = useMemo(\n () => ({\n path: [...branch.path, value],\n hidden: hiddenHere || !open,\n }),\n [branch, value, hiddenHere, open]\n );\n\n const { selected, checked } =\n tree?.stateOf(value, branch.path, disabled) ?? {};\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-selected': selected,\n 'is-disabled': disabled,\n });\n\n if (!tree) return null;\n\n // While it's open the children render in its group. In a `checkbox` tree\n // they render while it's closed or hidden too, drawing nothing, so a\n // check knows what's under it.\n const items = (shown || tree.rendersClosed) && (\n <BranchContext.Provider value={childBranch}>\n {children}\n </BranchContext.Provider>\n );\n if (hiddenHere) return <>{items}</>;\n\n const info = { value, parent, disabled, isParent, open };\n // A position the caller gives wins, for a set the page holds only part of.\n const position = tree.positionOf(value);\n\n return (\n <li\n {...props}\n ref={setRefs}\n className={classNames(itemClass, className)}\n role=\"treeitem\"\n aria-labelledby={labelId}\n aria-level={branch.path.length + 1}\n aria-posinset={props['aria-posinset'] ?? position?.posinset}\n aria-setsize={props['aria-setsize'] ?? position?.setsize}\n aria-expanded={isParent ? open : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={selected}\n aria-checked={checked}\n tabIndex={tree.tabStop === value ? 0 : -1}\n onKeyDown={event => {\n onKeyDown?.(event);\n tree.onKeyDown(event, info);\n }}\n onFocus={event => {\n onFocus?.(event);\n if (event.target === event.currentTarget) {\n tree.onFocus(value, event.currentTarget);\n }\n }}\n onBlur={event => {\n onBlur?.(event);\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => {\n onClick?.(event);\n // A click in its row is its own, and so is one on the item itself,\n // as a test's click on the treeitem is. One in its group belongs\n // to the item inside it, or to nothing. The chevron's box is on\n // every row, but it's a chevron only on a parent: on a leaf it's\n // more of the row.\n const target = event.target as Node;\n if (\n target === event.currentTarget ||\n rowRef.current!.contains(target)\n ) {\n tree.onClick(\n event.currentTarget,\n info,\n isParent && toggleRef.current!.contains(target)\n );\n }\n }}\n >\n <div className={rowClass} ref={rowRef}>\n <span className={toggleClass} aria-hidden=\"true\" ref={toggleRef} />\n {checked !== undefined && (\n <span\n className={checkClass}\n aria-hidden=\"true\"\n onClick={event => {\n // A click on the box's label is followed by one on its\n // input, and both reach the item. The label's is cancelled,\n // so the item toggles once.\n if (!(event.target instanceof HTMLInputElement)) {\n event.preventDefault();\n }\n }}\n >\n <Checkbox\n tabIndex={-1}\n checked={checked === true}\n indeterminate={checked === 'mixed'}\n disabled={disabled}\n onChange={ignoreChange}\n />\n </span>\n )}\n {isGiven(icon) && (\n <span className={iconClass} aria-hidden=\"true\">\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </span>\n )}\n <span className={labelClass} id={labelId} ref={labelRef}>\n {label}\n </span>\n </div>\n {open && (hasItems || status) ? (\n <ul className={groupClass} role=\"group\">\n {items}\n {status && (\n <StatusRow\n kind={status}\n parent={value}\n level={branch.path.length + 2}\n message={loadError}\n onRetry={onRetry}\n labelRef={statusLabelRef}\n />\n )}\n </ul>\n ) : (\n items\n )}\n </li>\n );\n }\n);\n\nTreeViewItem.displayName = 'TreeView.Item';\n\n/** Props for the row at the end of a loading item's group, or a failed load's. */\ninterface StatusRowProps {\n /** `loading`, or `error` for a load that failed. */\n kind: 'loading' | 'error';\n /** The value of the item it's in. */\n parent: string;\n /** Its `aria-level`, one under the item it's in. */\n level: number;\n /** A failed load's message. */\n message: React.ReactNode;\n /** Retries a failed load. */\n onRetry?: () => void;\n /** For its label, which the item reads a failed load's message off. */\n labelRef: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * The row at the end of a loading item's group, or of one whose load failed.\n * It's a `treeitem` the keys reach, the way they reach a disabled item, so a\n * screen reader finds it. It has no value and no record, so it's never\n * selected or checked, and a check never counts it. A failed load's row with\n * `onRetry` retries with Enter, Space or a click, and any other is disabled.\n * The Retry button is drawn, hidden from assistive tech and out of the tab\n * order, the way an item's box is: the row is what's pressed, and its name\n * says so. Rendered in one place, a failed load's row that starts loading\n * again is the same element, so focus stays on it.\n */\nfunction StatusRow({\n kind,\n parent,\n level,\n message,\n onRetry,\n labelRef,\n}: StatusRowProps) {\n // Only an item inside a tree renders a group.\n const tree = useContext(TreeViewContext)!;\n // Also its key in the registry and for the tab stop, where an item has its value.\n const labelId = useId();\n const retryId = useId();\n const retry = kind === 'error' ? onRetry : undefined;\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-disabled': !retry,\n });\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const labelClass = usePrefixedClassNames('tree-view-label');\n const loaderClass = usePrefixedClassNames('loader');\n const retryClass = usePrefixedClassNames('button', { 'is-small': true });\n\n const { setElement } = tree;\n const setRef = useCallback(\n (node: HTMLLIElement | null) => setElement(labelId, node),\n [setElement, labelId]\n );\n const info = {\n value: labelId,\n parent,\n disabled: !retry,\n isParent: false,\n open: false,\n retry,\n };\n const position = tree.positionOf(labelId);\n\n return (\n <li\n ref={setRef}\n className={itemClass}\n role=\"treeitem\"\n aria-labelledby={retry ? `${labelId} ${retryId}` : labelId}\n aria-level={level}\n aria-posinset={position?.posinset}\n aria-setsize={position?.setsize}\n aria-disabled={!retry || undefined}\n tabIndex={tree.tabStop === labelId ? 0 : -1}\n onKeyDown={event => tree.onKeyDown(event, info)}\n onFocus={event => {\n // Focus in something the message holds isn't the row's.\n if (event.target === event.currentTarget) {\n tree.onFocus(labelId, event.currentTarget);\n }\n }}\n onBlur={event => {\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => tree.onClick(event.currentTarget, info, false)}\n >\n <div className={rowClass}>\n <span className={toggleClass} aria-hidden=\"true\">\n {kind === 'loading' && <span className={loaderClass} />}\n </span>\n <span className={labelClass} id={labelId} ref={labelRef}>\n {kind === 'loading' ? tree.loadingLabel : message}\n </span>\n {retry && (\n <span className={retryClass} id={retryId} aria-hidden=\"true\">\n {tree.retryLabel}\n </span>\n )}\n </div>\n </li>\n );\n}\n\nexport const TreeView = withSubComponents(\n TreeViewRoot,\n { Item: TreeViewItem },\n 'TreeView'\n);\n\nexport default TreeView;\n"],"names":["ignoreChange","_jsxs","_jsx","_Fragment"],"mappings":"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"}
@@ -4,6 +4,7 @@ import { jsx } from 'react/jsx-runtime';
4
4
  import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
5
5
  import { withSubComponents } from '../helpers/withSubComponents.js';
6
6
  import { Button } from './Button.js';
7
+ import { CopyButton } from './CopyButton.js';
7
8
  import { IconButton } from './IconButton.js';
8
9
  import { LinkButton } from './LinkButton.js';
9
10
  import { ToggleButton } from './ToggleButton.js';
@@ -41,6 +42,7 @@ const Buttons = withSubComponents(ButtonsComponent, {
41
42
  LinkButton,
42
43
  ToggleButton,
43
44
  IconButton,
45
+ CopyButton,
44
46
  }, 'Buttons');
45
47
 
46
48
  export { Buttons };
@@ -1 +1 @@
1
- {"version":3,"file":"Buttons.js","sources":["../../../src/elements/Buttons.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Button } from './Button';\nimport { IconButton } from './IconButton';\nimport { LinkButton } from './LinkButton';\nimport { ToggleButton } from './ToggleButton';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\n\nconst validButtonsSizes = ['small', 'medium', 'large'] as const;\n/**\n * Valid size values for the Buttons component (Bulma button group sizes).\n */\nexport type ButtonsSize = (typeof validButtonsSizes)[number];\n\n/**\n * Props for the Buttons component.\n */\nexport interface ButtonsProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'size'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /** Text color helper for the button group. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /**\n * Text color alias: renders `has-text-<color>`, exactly like `textColor`.\n * Not a filled variant (no `.buttons.is-<color>` CSS exists; color the\n * individual `Button`s instead). Prefer `textColor`, which takes precedence\n * when both are set; use `bgColor` for a colored surface.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color helper for the button group. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Center the group of buttons. */\n isCentered?: boolean;\n /** Align the group of buttons to the right. */\n isRight?: boolean;\n /** Group buttons together as addons (removes spacing between them). */\n hasAddons?: boolean;\n /** Size of the button group. */\n size?: ButtonsSize;\n /** The button elements to render inside the group. */\n children: React.ReactNode;\n}\n\n/**\n * The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.\n *\n * @function\n * @param {ButtonsProps} props - Props for the Buttons component.\n * @returns {JSX.Element} The rendered group of buttons.\n * @see {@link https://bulma.io/documentation/elements/button/#group | Bulma Button Group documentation}\n */\nconst ButtonsComponent: React.FC<ButtonsProps> = ({\n className,\n textColor,\n color,\n bgColor,\n isCentered,\n isRight,\n hasAddons,\n size,\n children,\n ...props\n}) => {\n const buttonsClasses = usePrefixedClassNames('buttons', {\n 'is-centered': isCentered,\n 'is-right': isRight,\n 'has-addons': hasAddons,\n [`are-${size}`]: size && validButtonsSizes.includes(size),\n });\n\n /**\n * Generates Bulma helper classes and separates out remaining props.\n */\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n\n const combinedClasses = classNames(\n buttonsClasses,\n className,\n bulmaHelperClasses\n );\n\n return (\n <div className={combinedClasses} {...rest}>\n {children}\n </div>\n );\n};\n\nexport const Buttons = withSubComponents(\n ButtonsComponent,\n {\n Button,\n LinkButton,\n ToggleButton,\n IconButton,\n },\n 'Buttons'\n);\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;AAaA,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAU;AAsC/D;;;;;;;AAOG;AACH,MAAM,gBAAgB,GAA2B,CAAC,EAChD,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,UAAU,EACV,OAAO,EACP,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,EAAE;AACtD,QAAA,aAAa,EAAE,UAAU;AACzB,QAAA,UAAU,EAAE,OAAO;AACnB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,CAAC,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE,GAAG,IAAI,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC1D,KAAA,CAAC;AAEF;;AAEG;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK,EAAE,SAAS,IAAI,KAAK;AACzB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;IAEF,MAAM,eAAe,GAAG,UAAU,CAChC,cAAc,EACd,SAAS,EACT,kBAAkB,CACnB;IAED,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,eAAe,EAAA,GAAM,IAAI,EAAA,QAAA,EACtC,QAAQ,EAAA,CACL;AAEV,CAAC;AAEM,MAAM,OAAO,GAAG,iBAAiB,CACtC,gBAAgB,EAChB;IACE,MAAM;IACN,UAAU;IACV,YAAY;IACZ,UAAU;CACX,EACD,SAAS;;"}
1
+ {"version":3,"file":"Buttons.js","sources":["../../../src/elements/Buttons.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { Button } from './Button';\nimport { CopyButton } from './CopyButton';\nimport { IconButton } from './IconButton';\nimport { LinkButton } from './LinkButton';\nimport { ToggleButton } from './ToggleButton';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\n\nconst validButtonsSizes = ['small', 'medium', 'large'] as const;\n/**\n * Valid size values for the Buttons component (Bulma button group sizes).\n */\nexport type ButtonsSize = (typeof validButtonsSizes)[number];\n\n/**\n * Props for the Buttons component.\n */\nexport interface ButtonsProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'size'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /** Text color helper for the button group. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /**\n * Text color alias: renders `has-text-<color>`, exactly like `textColor`.\n * Not a filled variant (no `.buttons.is-<color>` CSS exists; color the\n * individual `Button`s instead). Prefer `textColor`, which takes precedence\n * when both are set; use `bgColor` for a colored surface.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color helper for the button group. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Center the group of buttons. */\n isCentered?: boolean;\n /** Align the group of buttons to the right. */\n isRight?: boolean;\n /** Group buttons together as addons (removes spacing between them). */\n hasAddons?: boolean;\n /** Size of the button group. */\n size?: ButtonsSize;\n /** The button elements to render inside the group. */\n children: React.ReactNode;\n}\n\n/**\n * The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.\n *\n * @function\n * @param {ButtonsProps} props - Props for the Buttons component.\n * @returns {JSX.Element} The rendered group of buttons.\n * @see {@link https://bulma.io/documentation/elements/button/#group | Bulma Button Group documentation}\n */\nconst ButtonsComponent: React.FC<ButtonsProps> = ({\n className,\n textColor,\n color,\n bgColor,\n isCentered,\n isRight,\n hasAddons,\n size,\n children,\n ...props\n}) => {\n const buttonsClasses = usePrefixedClassNames('buttons', {\n 'is-centered': isCentered,\n 'is-right': isRight,\n 'has-addons': hasAddons,\n [`are-${size}`]: size && validButtonsSizes.includes(size),\n });\n\n /**\n * Generates Bulma helper classes and separates out remaining props.\n */\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n\n const combinedClasses = classNames(\n buttonsClasses,\n className,\n bulmaHelperClasses\n );\n\n return (\n <div className={combinedClasses} {...rest}>\n {children}\n </div>\n );\n};\n\nexport const Buttons = withSubComponents(\n ButtonsComponent,\n {\n Button,\n LinkButton,\n ToggleButton,\n IconButton,\n CopyButton,\n },\n 'Buttons'\n);\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;;AAcA,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAU;AAsC/D;;;;;;;AAOG;AACH,MAAM,gBAAgB,GAA2B,CAAC,EAChD,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,UAAU,EACV,OAAO,EACP,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,EAAE;AACtD,QAAA,aAAa,EAAE,UAAU;AACzB,QAAA,UAAU,EAAE,OAAO;AACnB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,CAAC,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE,GAAG,IAAI,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC1D,KAAA,CAAC;AAEF;;AAEG;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK,EAAE,SAAS,IAAI,KAAK;AACzB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;IAEF,MAAM,eAAe,GAAG,UAAU,CAChC,cAAc,EACd,SAAS,EACT,kBAAkB,CACnB;IAED,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,eAAe,EAAA,GAAM,IAAI,EAAA,QAAA,EACtC,QAAQ,EAAA,CACL;AAEV,CAAC;AAEM,MAAM,OAAO,GAAG,iBAAiB,CACtC,gBAAgB,EAChB;IACE,MAAM;IACN,UAAU;IACV,YAAY;IACZ,UAAU;IACV,UAAU;CACX,EACD,SAAS;;"}