@carbon-labs/react-animated-header 0.34.0 → 0.36.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 (33) hide show
  1. package/es/__stories__/AnimatedHeader.stories.d.ts +94 -4
  2. package/es/__stories__/data/index.d.ts +7 -0
  3. package/es/components/AnimatedHeader/AnimatedHeader.d.ts +4 -1
  4. package/es/components/AnimatedHeader/AnimatedHeader.js +72 -12
  5. package/es/components/ContentSwitcherSelector/ContentSwitcherSelector.d.ts +30 -0
  6. package/es/components/ContentSwitcherSelector/ContentSwitcherSelector.js +70 -0
  7. package/es/components/HeaderAction/HeaderAction.d.ts +15 -0
  8. package/es/components/HeaderAction/HeaderAction.js +69 -0
  9. package/es/components/HeaderAction/header-action.types.d.ts +32 -0
  10. package/es/components/HeaderTitle/HeaderTitle.js +2 -3
  11. package/es/components/TasksController/TasksController.d.ts +4 -1
  12. package/es/components/TasksController/TasksController.js +33 -23
  13. package/es/index.d.ts +4 -1
  14. package/es/index.js +1 -0
  15. package/lib/__stories__/AnimatedHeader.stories.d.ts +94 -4
  16. package/lib/__stories__/data/index.d.ts +7 -0
  17. package/lib/components/AnimatedHeader/AnimatedHeader.d.ts +4 -1
  18. package/lib/components/AnimatedHeader/AnimatedHeader.js +72 -12
  19. package/lib/components/ContentSwitcherSelector/ContentSwitcherSelector.d.ts +30 -0
  20. package/lib/components/ContentSwitcherSelector/ContentSwitcherSelector.js +74 -0
  21. package/lib/components/HeaderAction/HeaderAction.d.ts +15 -0
  22. package/lib/components/HeaderAction/HeaderAction.js +73 -0
  23. package/lib/components/HeaderAction/header-action.types.d.ts +32 -0
  24. package/lib/components/HeaderTitle/HeaderTitle.js +2 -3
  25. package/lib/components/TasksController/TasksController.d.ts +4 -1
  26. package/lib/components/TasksController/TasksController.js +33 -23
  27. package/lib/index.d.ts +4 -1
  28. package/lib/index.js +2 -0
  29. package/package.json +2 -2
  30. package/scss/AnimatedHeader/animated-header.scss +82 -0
  31. package/scss/HeaderAction/header-action.scss +54 -0
  32. package/scss/HeaderTitle/header-title.scss +18 -12
  33. package/scss/animated-header.scss +1 -0
@@ -6,8 +6,8 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import { SkeletonPlaceholder, Button, Dropdown } from '@carbon/react';
10
9
  import React, { useMemo } from 'react';
10
+ import { SkeletonPlaceholder, Button, Dropdown } from '@carbon/react';
11
11
  import { usePrefix } from '../../node_modules/@carbon-labs/utilities/es/usePrefix.js';
12
12
 
13
13
  const TasksController = ({
@@ -17,54 +17,64 @@ const TasksController = ({
17
17
  selectedTileGroup,
18
18
  setSelectedTileGroup
19
19
  }) => {
20
+ const prefix = usePrefix();
21
+ const blockClass = `${prefix}--animated-header`;
22
+
23
+ /** Button overrides */
20
24
  const {
21
25
  className: buttonCustomClass,
22
26
  ...buttonOverrideProps
23
27
  } = tasksControllerConfig?.button?.propsOverrides || {};
28
+
29
+ /** Dropdown overrides */
24
30
  const {
25
31
  className: dropdownCustomClass,
26
32
  onChange: dropdownCustomOnChange,
27
33
  ...dropdownOverrideProps
28
34
  } = tasksControllerConfig?.dropdown?.propsOverrides || {};
29
- const prefix = usePrefix();
30
- const blockClass = `${prefix}--animated-header`;
35
+
36
+ /** Early outs */
37
+ if (!tasksControllerConfig?.type) return null;
38
+ if (isLoading || tasksControllerConfig?.isLoading) {
39
+ return /*#__PURE__*/React.createElement(SkeletonPlaceholder, {
40
+ className: `${blockClass}__task-controller-skeleton`
41
+ });
42
+ }
43
+
44
+ /** Button mode */
45
+ if (tasksControllerConfig?.type === 'button' && tasksControllerConfig?.button?.text) {
46
+ return /*#__PURE__*/React.createElement(Button, _extends({
47
+ className: `${blockClass}__button${buttonCustomClass ? ` ${buttonCustomClass}` : ''}`
48
+ }, buttonOverrideProps), tasksControllerConfig.button.text);
49
+ }
50
+
51
+ /** Build Dropdown props (uses top-level list/selection/setter) */
31
52
  const dropdownProps = useMemo(() => {
32
- if (!allTileGroups?.length) {
33
- return null;
34
- }
53
+ if (!allTileGroups?.length) return null;
35
54
  return {
36
55
  id: `${blockClass}__header-dropdown`,
37
56
  className: `${blockClass}__header-dropdown${dropdownCustomClass ? ` ${dropdownCustomClass}` : ''}`,
38
57
  size: 'md',
39
58
  titleText: 'Label',
40
- label: allTileGroups[0]?.label ?? '',
59
+ label: tasksControllerConfig?.dropdown?.label ?? allTileGroups[0]?.label ?? '',
41
60
  hideLabel: true,
42
61
  type: 'inline',
43
62
  items: allTileGroups,
44
63
  selectedItem: selectedTileGroup ?? undefined,
45
64
  onChange: e => {
46
- setSelectedTileGroup?.(e);
65
+ if (e.selectedItem) {
66
+ setSelectedTileGroup?.({
67
+ selectedItem: e.selectedItem
68
+ });
69
+ }
47
70
  dropdownCustomOnChange?.(e);
48
71
  },
49
72
  'aria-label': tasksControllerConfig?.dropdown?.ariaLabel ?? 'Select a task group',
50
73
  ...dropdownOverrideProps
51
74
  };
52
- }, [allTileGroups, blockClass, dropdownCustomClass, selectedTileGroup, tasksControllerConfig?.dropdown?.ariaLabel, dropdownOverrideProps, setSelectedTileGroup, dropdownCustomOnChange]);
53
- if (!tasksControllerConfig?.type) {
54
- return null;
55
- }
56
- if (isLoading || tasksControllerConfig?.isLoading) {
57
- return /*#__PURE__*/React.createElement(SkeletonPlaceholder, {
58
- className: `${blockClass}__task-controller-skeleton`
59
- });
60
- }
75
+ }, [allTileGroups, selectedTileGroup, setSelectedTileGroup, blockClass, dropdownCustomClass, dropdownOverrideProps, dropdownCustomOnChange, tasksControllerConfig?.dropdown?.label, tasksControllerConfig?.dropdown?.ariaLabel]);
61
76
 
62
- // Button
63
- if (tasksControllerConfig?.type === 'button' && tasksControllerConfig?.button?.text) {
64
- return /*#__PURE__*/React.createElement(Button, _extends({
65
- className: `${blockClass}__button${buttonCustomClass ? ` ${buttonCustomClass}` : ''}`
66
- }, buttonOverrideProps), tasksControllerConfig.button.text);
67
- }
77
+ /** Dropdown mode */
68
78
  if (tasksControllerConfig?.type === 'dropdown' && dropdownProps) {
69
79
  return /*#__PURE__*/React.createElement("div", {
70
80
  className: `${blockClass}__header-dropdown--container`
package/es/index.d.ts CHANGED
@@ -8,9 +8,12 @@
8
8
  */
9
9
  import AnimatedHeader from './components/AnimatedHeader/AnimatedHeader';
10
10
  import { AriaLabels, TileGroup } from './components/AnimatedHeader/types';
11
+ import HeaderAction from './components/HeaderAction/HeaderAction';
11
12
  import HeaderTitle from './components/HeaderTitle/HeaderTitle';
12
13
  import { BaseTile } from './components/Tiles/index';
13
14
  export * from './assets';
14
15
  export type { Workspace, WorkspaceSelectorConfig, } from './components/WorkspaceSelector/WorkspaceSelector';
15
16
  export type { TasksControllerConfig } from './components/TasksController/TasksController';
16
- export { AnimatedHeader, BaseTile, HeaderTitle, type AriaLabels, type TileGroup, };
17
+ export type { HeaderActionConfig } from './components/HeaderAction/header-action.types';
18
+ export type { ContentSwitcherConfig } from './components/ContentSwitcherSelector/ContentSwitcherSelector';
19
+ export { AnimatedHeader, BaseTile, HeaderAction, HeaderTitle, type AriaLabels, type TileGroup, };
package/es/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  export { default as AnimatedHeader } from './components/AnimatedHeader/AnimatedHeader.js';
9
+ export { default as HeaderAction } from './components/HeaderAction/HeaderAction.js';
9
10
  export { default as HeaderTitle } from './components/HeaderTitle/HeaderTitle.js';
10
11
  import 'react';
11
12
  import '@carbon/react';
@@ -1,3 +1,11 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright IBM Corp. 2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
1
9
  import AnimatedHeader from '../components/AnimatedHeader/AnimatedHeader';
2
10
  import type { Meta } from '@storybook/react-webpack5';
3
11
  import '../components/animated-header.scss';
@@ -15124,11 +15132,49 @@ export declare const ThemeG10: {
15124
15132
  };
15125
15133
  expandButtonLabel: {
15126
15134
  description: string;
15127
- type: string;
15128
15135
  };
15129
15136
  collapseButtonLabel: {
15130
15137
  description: string;
15131
- type: string;
15138
+ };
15139
+ headerActionConfig: {
15140
+ description: string;
15141
+ control: {
15142
+ type: string;
15143
+ labels: {
15144
+ 0: string;
15145
+ 1: string;
15146
+ 2: string;
15147
+ };
15148
+ };
15149
+ options: number[];
15150
+ };
15151
+ contentSwitcherConfig: {
15152
+ description: string;
15153
+ control: {
15154
+ type: string;
15155
+ labels: {
15156
+ 0: string;
15157
+ 1: string;
15158
+ 2: string;
15159
+ 3: string;
15160
+ };
15161
+ };
15162
+ options: number[];
15163
+ mapping: {
15164
+ 0: null;
15165
+ 1: import("..").ContentSwitcherConfig;
15166
+ 2: import("..").ContentSwitcherConfig;
15167
+ 3: import("..").ContentSwitcherConfig;
15168
+ };
15169
+ };
15170
+ contentSwitcherLowContrast: {
15171
+ description: string;
15172
+ control: {
15173
+ type: string;
15174
+ };
15175
+ table: {
15176
+ category: string;
15177
+ };
15132
15178
  };
15133
15179
  };
15134
15180
  args: {
@@ -15152,6 +15198,9 @@ export declare const ThemeG10: {
15152
15198
  expandButton: string;
15153
15199
  tilesContainer: string;
15154
15200
  };
15201
+ headerActionConfig: number;
15202
+ contentSwitcherConfig: number;
15203
+ contentSwitcherLowContrast: boolean;
15155
15204
  headerAnimation: number;
15156
15205
  };
15157
15206
  };
@@ -30276,11 +30325,49 @@ export declare const ThemeG100: {
30276
30325
  };
30277
30326
  expandButtonLabel: {
30278
30327
  description: string;
30279
- type: string;
30280
30328
  };
30281
30329
  collapseButtonLabel: {
30282
30330
  description: string;
30283
- type: string;
30331
+ };
30332
+ headerActionConfig: {
30333
+ description: string;
30334
+ control: {
30335
+ type: string;
30336
+ labels: {
30337
+ 0: string;
30338
+ 1: string;
30339
+ 2: string;
30340
+ };
30341
+ };
30342
+ options: number[];
30343
+ };
30344
+ contentSwitcherConfig: {
30345
+ description: string;
30346
+ control: {
30347
+ type: string;
30348
+ labels: {
30349
+ 0: string;
30350
+ 1: string;
30351
+ 2: string;
30352
+ 3: string;
30353
+ };
30354
+ };
30355
+ options: number[];
30356
+ mapping: {
30357
+ 0: null;
30358
+ 1: import("..").ContentSwitcherConfig;
30359
+ 2: import("..").ContentSwitcherConfig;
30360
+ 3: import("..").ContentSwitcherConfig;
30361
+ };
30362
+ };
30363
+ contentSwitcherLowContrast: {
30364
+ description: string;
30365
+ control: {
30366
+ type: string;
30367
+ };
30368
+ table: {
30369
+ category: string;
30370
+ };
30284
30371
  };
30285
30372
  };
30286
30373
  args: {
@@ -30304,6 +30391,9 @@ export declare const ThemeG100: {
30304
30391
  expandButton: string;
30305
30392
  tilesContainer: string;
30306
30393
  };
30394
+ headerActionConfig: number;
30395
+ contentSwitcherConfig: number;
30396
+ contentSwitcherLowContrast: boolean;
30307
30397
  headerAnimation: number;
30308
30398
  };
30309
30399
  globals: {
@@ -7,6 +7,8 @@
7
7
  * LICENSE file in the root directory of this source tree.
8
8
  */
9
9
  import { TileGroup } from '../../components/AnimatedHeader/types';
10
+ import type { HeaderActionConfig } from '../../components/HeaderAction/header-action.types';
11
+ import type { ContentSwitcherConfig } from '../../components/ContentSwitcherSelector/ContentSwitcherSelector';
10
12
  export declare const workspaceData: {
11
13
  id: string;
12
14
  label: string;
@@ -35,6 +37,9 @@ export declare const tasksControllerConfigLoading: {
35
37
  type: string;
36
38
  isLoading: boolean;
37
39
  };
40
+ export declare const contentSwitcherConfigTwo: ContentSwitcherConfig;
41
+ export declare const contentSwitcherConfigThree: ContentSwitcherConfig;
42
+ export declare const contentSwitcherConfigLoading: ContentSwitcherConfig;
38
43
  export declare const workspaceSelectorConfig: {
39
44
  allWorkspaces: {
40
45
  id: string;
@@ -55,3 +60,5 @@ export declare const workspaceSelectorConfigLoading: {
55
60
  setSelectedWorkspace: () => void;
56
61
  isLoading: boolean;
57
62
  };
63
+ export declare const headerActionIcon: HeaderActionConfig;
64
+ export declare const headerActionGhost: HeaderActionConfig;
@@ -10,12 +10,15 @@ import React from 'react';
10
10
  import { TasksControllerProps } from '../TasksController/TasksController';
11
11
  import { WorkspaceSelectorProps } from '../WorkspaceSelector/WorkspaceSelector';
12
12
  import { Tile, TileGroup, AriaLabels } from './types';
13
+ import { type ContentSwitcherConfig } from '../ContentSwitcherSelector/ContentSwitcherSelector';
14
+ import type { HeaderActionProps } from '../HeaderAction/header-action.types';
13
15
  /** Animated Header */
14
16
  export type AnimatedHeaderProps = {
15
17
  allTileGroups?: TileGroup[];
16
18
  ariaLabels?: AriaLabels;
17
19
  selectedTileGroup?: TileGroup;
18
20
  setSelectedTileGroup?: (e: any) => void;
21
+ contentSwitcherConfig?: ContentSwitcherConfig;
19
22
  description?: string;
20
23
  headerAnimation?: object;
21
24
  headerStatic?: React.JSX.Element | string;
@@ -27,6 +30,6 @@ export type AnimatedHeaderProps = {
27
30
  expandButtonLabel?: string;
28
31
  collapseButtonLabel?: string;
29
32
  tileClickHandler?: (tile: Tile) => void;
30
- } & TasksControllerProps & WorkspaceSelectorProps;
33
+ } & TasksControllerProps & WorkspaceSelectorProps & HeaderActionProps;
31
34
  declare const AnimatedHeader: React.FC<AnimatedHeaderProps>;
32
35
  export default AnimatedHeader;
@@ -21,6 +21,8 @@ var BaseTile = require('../Tiles/BaseTile/BaseTile.js');
21
21
  var TasksController = require('../TasksController/TasksController.js');
22
22
  var WorkspaceSelector = require('../WorkspaceSelector/WorkspaceSelector.js');
23
23
  var HeaderTitle = require('../HeaderTitle/HeaderTitle.js');
24
+ var ContentSwitcherSelector = require('../ContentSwitcherSelector/ContentSwitcherSelector.js');
25
+ var HeaderAction = require('../HeaderAction/HeaderAction.js');
24
26
 
25
27
  /** Animated Header */
26
28
 
@@ -35,6 +37,8 @@ const AnimatedHeader = ({
35
37
  productName = '[Product name]',
36
38
  userName,
37
39
  welcomeText,
40
+ contentSwitcherConfig,
41
+ headerActionConfig,
38
42
  tasksControllerConfig,
39
43
  workspaceSelectorConfig,
40
44
  isLoading,
@@ -128,13 +132,22 @@ const AnimatedHeader = ({
128
132
  })), /*#__PURE__*/React.createElement(react.Column, {
129
133
  sm: 4,
130
134
  md: 8,
131
- lg: 16
135
+ lg: 16,
136
+ className: `${blockClass}__title-row`
137
+ }, /*#__PURE__*/React.createElement("div", {
138
+ className: `${blockClass}__title-and-actions`
132
139
  }, /*#__PURE__*/React.createElement(HeaderTitle.default, {
133
140
  userName: userName,
134
141
  welcomeText: welcomeText,
135
142
  headerExpanded: isOpen,
136
143
  ariaLabels: ariaLabels
137
- })), (description || tasksControllerConfig) && /*#__PURE__*/React.createElement(react.Column, {
144
+ }), contentSwitcherConfig ? /*#__PURE__*/React.createElement("div", {
145
+ className: `${blockClass}__actions`
146
+ }, /*#__PURE__*/React.createElement(ContentSwitcherSelector.default, {
147
+ contentSwitcherConfig: contentSwitcherConfig,
148
+ isLoading: isLoading || contentSwitcherConfig.isLoading,
149
+ headerExpanded: isOpen
150
+ })) : null)), (description || tasksControllerConfig) && /*#__PURE__*/React.createElement(react.Column, {
138
151
  sm: 4,
139
152
  md: 8,
140
153
  lg: 4,
@@ -144,7 +157,7 @@ const AnimatedHeader = ({
144
157
  }, description && /*#__PURE__*/React.createElement("h2", {
145
158
  className: `${blockClass}__description`,
146
159
  "aria-label": ariaLabels?.description ?? `Header description`
147
- }, description), /*#__PURE__*/React.createElement(TasksController.default, {
160
+ }, description), tasksControllerConfig && /*#__PURE__*/React.createElement(TasksController.default, {
148
161
  tasksControllerConfig: tasksControllerConfig,
149
162
  isLoading: isLoading,
150
163
  allTileGroups: allTileGroups,
@@ -194,7 +207,10 @@ const AnimatedHeader = ({
194
207
  className: `${blockClass}__button-collapse--gradient`
195
208
  }), /*#__PURE__*/React.createElement("div", {
196
209
  className: `${blockClass}__button-collapse--container`
197
- }, /*#__PURE__*/React.createElement(react.Button, {
210
+ }, headerActionConfig ? /*#__PURE__*/React.createElement(HeaderAction.default, {
211
+ config: headerActionConfig,
212
+ headerExpanded: isOpen
213
+ }) : null, /*#__PURE__*/React.createElement(react.Button, {
198
214
  id: `${blockClass}__button-collapse`,
199
215
  kind: "ghost",
200
216
  renderIcon: isOpen ? iconsReact.ChevronUp : iconsReact.ChevronDown,
@@ -222,6 +238,24 @@ AnimatedHeader.propTypes = {
222
238
  * Custom collapse button label
223
239
  */
224
240
  collapseButtonLabel: PropTypes.string,
241
+ /**
242
+ * Configuration for Carbon Content Switcher in header.
243
+ * Customized tasks are used to allow users that have multiple roles and
244
+ * permissions to experience better tailored content based on their need.
245
+ */
246
+ contentSwitcherConfig: PropTypes.shape({
247
+ items: PropTypes.arrayOf(PropTypes.shape({
248
+ id: PropTypes.string,
249
+ text: PropTypes.string.isRequired,
250
+ onSelect: PropTypes.func
251
+ }).isRequired).isRequired,
252
+ ariaLabel: PropTypes.string,
253
+ isLoading: PropTypes.bool,
254
+ lowContrast: PropTypes.bool,
255
+ headerExpanded: PropTypes.bool,
256
+ visibleCount: PropTypes.oneOf([2, 3]),
257
+ onChange: PropTypes.func
258
+ }),
225
259
  /**
226
260
  * Provide short sentence in max. 3 lines related to product context
227
261
  */
@@ -230,6 +264,34 @@ AnimatedHeader.propTypes = {
230
264
  * Custom expand button label
231
265
  */
232
266
  expandButtonLabel: PropTypes.string,
267
+ /**
268
+ * Configuration for the header action control (icon button / ghost button / carousel - *coming soon*).
269
+ * This sits to the left of the Collapse button and can trigger generic actions
270
+ * (open modal/panel) or page through tiles.
271
+ */
272
+ headerActionConfig: PropTypes.shape({
273
+ type: PropTypes.oneOf(['icon-button', 'ghost-button']).isRequired,
274
+ // Carbon IconButton variant
275
+ iconButton: PropTypes.shape({
276
+ icon: PropTypes.elementType.isRequired,
277
+ iconLabel: PropTypes.string.isRequired,
278
+ onClick: PropTypes.func.isRequired,
279
+ disabled: PropTypes.bool,
280
+ ariaLabel: PropTypes.string,
281
+ // Override Carbon IconButton props if needed
282
+ propsOverrides: PropTypes.object
283
+ }),
284
+ // Carbon Ghost Button variant
285
+ ghostButton: PropTypes.shape({
286
+ label: PropTypes.string.isRequired,
287
+ icon: PropTypes.elementType,
288
+ onClick: PropTypes.func.isRequired,
289
+ disabled: PropTypes.bool,
290
+ ariaLabel: PropTypes.string,
291
+ // Override Carbon Button props if needed
292
+ propsOverrides: PropTypes.object
293
+ })
294
+ }),
233
295
  /**
234
296
  * In-product imagery / lottie animation (.json) dim. 1312 x 738
235
297
  * (to update headerAnimation content storybook requires remount in toolbar)
@@ -258,23 +320,21 @@ AnimatedHeader.propTypes = {
258
320
  */
259
321
  setSelectedTileGroup: PropTypes.func,
260
322
  /**
261
- * Configuration for Carbon button or dropdown menu in header. Customized
262
- * tasks are used to allow users that have multiple roles and permissions
263
- * to experience better tailored content based on their need.
264
- * It also allows to override Carbon Button props by specifying them in tasksConfig.button.propsOverrides
265
- * or to override Carbon Dropdown props by specifying them in tasksConfig.dropdown.propsOverrides.
323
+ * Configuration for Carbon button / dropdown in header.
324
+ * Customized tasks are used to allow users that have multiple roles and
325
+ * permissions to experience better tailored content based on their need.
266
326
  */
267
327
  tasksControllerConfig: PropTypes.shape({
268
328
  type: PropTypes.oneOf(['button', 'dropdown']).isRequired,
329
+ isLoading: PropTypes.bool,
269
330
  button: PropTypes.shape({
270
331
  text: PropTypes.string.isRequired,
271
332
  // Override Carbon Button props
272
333
  propsOverrides: PropTypes.object
273
334
  }),
274
335
  dropdown: PropTypes.shape({
275
- allTileGroups: PropTypes.arrayOf(PropTypes.object),
276
- selectedTileGroup: PropTypes.object,
277
- setSelectedTileGroup: PropTypes.func.isRequired,
336
+ label: PropTypes.string,
337
+ ariaLabel: PropTypes.string,
278
338
  // Override Carbon Dropdown props
279
339
  propsOverrides: PropTypes.object
280
340
  })
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright IBM Corp. 2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import React from 'react';
10
+ import { type ContentSwitcherProps } from '@carbon/react';
11
+ export type ContentSwitcherItem = {
12
+ id?: string;
13
+ text: string;
14
+ onSelect?: () => void;
15
+ };
16
+ export type ContentSwitcherConfig = Omit<ContentSwitcherProps, 'children' | 'onChange' | 'size' | 'lowContrast'> & {
17
+ items: ContentSwitcherItem[];
18
+ ariaLabel?: string;
19
+ isLoading?: boolean;
20
+ lowContrast?: boolean;
21
+ visibleCount?: 2 | 3;
22
+ onChange?: ContentSwitcherProps['onChange'];
23
+ };
24
+ export type ContentSwitcherSelectorProps = {
25
+ contentSwitcherConfig?: ContentSwitcherConfig | null;
26
+ isLoading?: boolean;
27
+ headerExpanded?: boolean;
28
+ };
29
+ declare const ContentSwitcherSelector: React.FC<ContentSwitcherSelectorProps>;
30
+ export default ContentSwitcherSelector;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Copyright IBM Corp. 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ Object.defineProperty(exports, '__esModule', { value: true });
11
+
12
+ var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
13
+ var React = require('react');
14
+ var react = require('@carbon/react');
15
+ var usePrefix = require('../../node_modules/@carbon-labs/utilities/es/usePrefix.js');
16
+
17
+ const ContentSwitcherSelector = ({
18
+ contentSwitcherConfig,
19
+ isLoading,
20
+ headerExpanded
21
+ }) => {
22
+ const prefix = usePrefix.usePrefix();
23
+ const blockClass = `${prefix}--animated-header__content-switcher`;
24
+ if (!contentSwitcherConfig) return null;
25
+ if (isLoading || contentSwitcherConfig.isLoading) {
26
+ return /*#__PURE__*/React.createElement(react.SkeletonPlaceholder, {
27
+ className: `${blockClass}-skeleton`
28
+ });
29
+ }
30
+ const {
31
+ items = [],
32
+ visibleCount,
33
+ lowContrast,
34
+ ariaLabel,
35
+ onChange,
36
+ selectedIndex,
37
+ ...rest
38
+ } = contentSwitcherConfig;
39
+ const count = visibleCount === 3 ? 3 : 2;
40
+ const visibleItems = items.slice(0, count);
41
+ if (visibleItems.length < 2 || visibleItems.length > 3) {
42
+ if (process.env.NODE_ENV !== 'production') {
43
+ console.warn('[ContentSwitcherSelector] contentSwitcherConfig.items must contain 2 or 3 items.');
44
+ }
45
+ return null;
46
+ }
47
+ const selectedIndexSafe = React.useMemo(() => {
48
+ const idx = typeof selectedIndex === 'number' ? selectedIndex : 0;
49
+ return Math.min(Math.max(idx, 0), visibleItems.length - 1);
50
+ }, [selectedIndex, visibleItems.length]);
51
+ return /*#__PURE__*/React.createElement("div", {
52
+ className: `${blockClass}--container`,
53
+ "data-expanded": headerExpanded
54
+ }, /*#__PURE__*/React.createElement(react.ContentSwitcher, _rollupPluginBabelHelpers.extends({
55
+ className: `${blockClass}`,
56
+ "aria-label": ariaLabel ?? 'Select a task group',
57
+ lowContrast: lowContrast,
58
+ selectedIndex: selectedIndexSafe,
59
+ size: "md",
60
+ onChange: ev => {
61
+ onChange?.(ev);
62
+ const idx = ev.index ?? ev.selectedIndex ?? 0;
63
+ visibleItems[idx]?.onSelect?.();
64
+ }
65
+ }, rest), visibleItems.map((item, idx) => {
66
+ return /*#__PURE__*/React.createElement(react.Switch, {
67
+ key: item.id ?? idx,
68
+ name: `option-${idx}`,
69
+ text: item.text
70
+ });
71
+ })));
72
+ };
73
+
74
+ exports.default = ContentSwitcherSelector;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright IBM Corp. 2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import React from 'react';
10
+ import type { HeaderActionConfig } from './header-action.types';
11
+ declare const HeaderAction: React.FC<{
12
+ config: HeaderActionConfig;
13
+ headerExpanded: boolean;
14
+ }>;
15
+ export default HeaderAction;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright IBM Corp. 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ Object.defineProperty(exports, '__esModule', { value: true });
11
+
12
+ var React = require('react');
13
+ var react = require('@carbon/react');
14
+ var usePrefix = require('../../node_modules/@carbon-labs/utilities/es/usePrefix.js');
15
+
16
+ const HeaderAction = ({
17
+ config,
18
+ headerExpanded
19
+ }) => {
20
+ const prefix = usePrefix.usePrefix();
21
+ const blockClass = `${prefix}--animated-header__header-action`;
22
+
23
+ // ICON
24
+ if (config.type === 'icon-button') {
25
+ const {
26
+ icon: Icon,
27
+ iconLabel,
28
+ onClick,
29
+ disabled,
30
+ ariaLabel
31
+ } = config;
32
+ return /*#__PURE__*/React.createElement("div", {
33
+ className: blockClass,
34
+ "aria-label": ariaLabel,
35
+ "aria-hidden": !headerExpanded,
36
+ "data-expanded": headerExpanded
37
+ }, /*#__PURE__*/React.createElement(react.IconButton, {
38
+ kind: "ghost",
39
+ size: "lg",
40
+ label: iconLabel,
41
+ onClick: onClick,
42
+ disabled: disabled
43
+ }, Icon && /*#__PURE__*/React.createElement(Icon, {
44
+ fill: `var(--cds-icon-secondary)`,
45
+ size: 16
46
+ })));
47
+ }
48
+
49
+ // GHOST
50
+ if (config.type === 'ghost-button') {
51
+ const {
52
+ label,
53
+ icon,
54
+ onClick,
55
+ disabled,
56
+ ariaLabel
57
+ } = config;
58
+ return /*#__PURE__*/React.createElement("div", {
59
+ className: blockClass,
60
+ "aria-label": ariaLabel,
61
+ "aria-hidden": !headerExpanded,
62
+ "data-expanded": headerExpanded
63
+ }, /*#__PURE__*/React.createElement(react.Button, {
64
+ kind: "ghost",
65
+ size: "lg",
66
+ onClick: onClick,
67
+ disabled: disabled,
68
+ renderIcon: icon
69
+ }, label));
70
+ }
71
+ };
72
+
73
+ exports.default = HeaderAction;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright IBM Corp. 2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { ElementType } from 'react';
10
+ type Base = {
11
+ ariaLabel?: string;
12
+ headerExpanded?: boolean;
13
+ };
14
+ export type HeaderActionIcon = Base & {
15
+ type: 'icon-button';
16
+ icon: ElementType;
17
+ iconLabel: string;
18
+ onClick: () => void;
19
+ disabled?: boolean;
20
+ };
21
+ export type HeaderActionGhost = Base & {
22
+ type: 'ghost-button';
23
+ label: string;
24
+ icon?: ElementType;
25
+ onClick: () => void;
26
+ disabled?: boolean;
27
+ };
28
+ export type HeaderActionConfig = HeaderActionIcon | HeaderActionGhost;
29
+ export type HeaderActionProps = {
30
+ headerActionConfig?: HeaderActionConfig | null;
31
+ };
32
+ export {};