@workday/canvas-kit-react 7.0.0-alpha.97-next.23 → 7.0.2

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 (134) hide show
  1. package/action-bar/index.ts +1 -0
  2. package/action-bar/lib/ActionBar.tsx +33 -31
  3. package/action-bar/lib/ActionBarItem.tsx +41 -0
  4. package/action-bar/lib/ActionBarList.tsx +70 -0
  5. package/action-bar/lib/ActionBarOverflowButton.tsx +36 -0
  6. package/action-bar/lib/useActionBarModel.tsx +91 -0
  7. package/avatar/lib/Avatar.tsx +4 -0
  8. package/button/index.ts +1 -0
  9. package/button/lib/ExternalHyperlink.tsx +59 -0
  10. package/button/lib/TertiaryButton.tsx +1 -0
  11. package/collection/lib/useListItemRovingFocus.tsx +4 -2
  12. package/collection/lib/useListRenderItem.tsx +3 -3
  13. package/common/lib/parts/_brand-assets.ts +1 -1
  14. package/common/lib/utils/elements.ts +5 -1
  15. package/dist/commonjs/action-bar/index.d.ts +1 -0
  16. package/dist/commonjs/action-bar/index.d.ts.map +1 -1
  17. package/dist/commonjs/action-bar/index.js +1 -0
  18. package/dist/commonjs/action-bar/lib/ActionBar.d.ts +3495 -5
  19. package/dist/commonjs/action-bar/lib/ActionBar.d.ts.map +1 -1
  20. package/dist/commonjs/action-bar/lib/ActionBar.js +28 -27
  21. package/dist/commonjs/action-bar/lib/ActionBarItem.d.ts +215 -0
  22. package/dist/commonjs/action-bar/lib/ActionBarItem.d.ts.map +1 -0
  23. package/dist/commonjs/action-bar/lib/ActionBarItem.js +46 -0
  24. package/dist/commonjs/action-bar/lib/ActionBarList.d.ts +221 -0
  25. package/dist/commonjs/action-bar/lib/ActionBarList.d.ts.map +1 -0
  26. package/dist/commonjs/action-bar/lib/ActionBarList.js +74 -0
  27. package/dist/commonjs/action-bar/lib/ActionBarOverflowButton.d.ts +230 -0
  28. package/dist/commonjs/action-bar/lib/ActionBarOverflowButton.d.ts.map +1 -0
  29. package/dist/commonjs/action-bar/lib/ActionBarOverflowButton.js +57 -0
  30. package/dist/commonjs/action-bar/lib/useActionBarModel.d.ts +1659 -0
  31. package/dist/commonjs/action-bar/lib/useActionBarModel.d.ts.map +1 -0
  32. package/dist/commonjs/action-bar/lib/useActionBarModel.js +77 -0
  33. package/dist/commonjs/avatar/lib/Avatar.d.ts.map +1 -1
  34. package/dist/commonjs/avatar/lib/Avatar.js +3 -0
  35. package/dist/commonjs/button/index.d.ts +1 -0
  36. package/dist/commonjs/button/index.d.ts.map +1 -1
  37. package/dist/commonjs/button/index.js +3 -1
  38. package/dist/commonjs/button/lib/ExternalHyperlink.d.ts +11 -0
  39. package/dist/commonjs/button/lib/ExternalHyperlink.d.ts.map +1 -0
  40. package/dist/commonjs/button/lib/ExternalHyperlink.js +48 -0
  41. package/dist/commonjs/button/lib/TertiaryButton.d.ts.map +1 -1
  42. package/dist/commonjs/button/lib/TertiaryButton.js +1 -0
  43. package/dist/commonjs/collection/lib/useListItemRovingFocus.d.ts +1 -1
  44. package/dist/commonjs/collection/lib/useListItemRovingFocus.d.ts.map +1 -1
  45. package/dist/commonjs/collection/lib/useListItemRovingFocus.js +2 -2
  46. package/dist/commonjs/collection/lib/useListRenderItem.d.ts +1 -1
  47. package/dist/commonjs/collection/lib/useListRenderItem.d.ts.map +1 -1
  48. package/dist/commonjs/collection/lib/useListRenderItem.js +2 -2
  49. package/dist/commonjs/common/lib/parts/_brand-assets.js +1 -1
  50. package/dist/commonjs/common/lib/utils/elements.d.ts +2 -2
  51. package/dist/commonjs/common/lib/utils/elements.d.ts.map +1 -1
  52. package/dist/commonjs/common/lib/utils/elements.js +4 -1
  53. package/dist/commonjs/form-field/lib/Label.d.ts.map +1 -1
  54. package/dist/commonjs/form-field/lib/Label.js +3 -7
  55. package/dist/commonjs/icon/lib/Icon.d.ts +1 -1
  56. package/dist/commonjs/icon/lib/Icon.d.ts.map +1 -1
  57. package/dist/commonjs/icon/lib/Icon.js +2 -4
  58. package/dist/commonjs/icon/lib/SystemIcon.d.ts +1 -1
  59. package/dist/commonjs/icon/lib/SystemIcon.d.ts.map +1 -1
  60. package/dist/commonjs/popup/lib/hooks/useDisableBodyScroll.d.ts.map +1 -1
  61. package/dist/commonjs/popup/lib/hooks/useDisableBodyScroll.js +2 -0
  62. package/dist/commonjs/popup/lib/hooks/usePopupTarget.js +1 -1
  63. package/dist/commonjs/table/lib/TableRow.d.ts +4 -4
  64. package/dist/commonjs/table/lib/TableRow.d.ts.map +1 -1
  65. package/dist/commonjs/table/lib/TableRow.js +12 -26
  66. package/dist/commonjs/tabs/lib/Tabs.d.ts.map +1 -1
  67. package/dist/commonjs/tabs/lib/Tabs.js +1 -2
  68. package/dist/commonjs/tabs/lib/TabsItem.d.ts +1 -1
  69. package/dist/commonjs/tabs/lib/TabsItem.d.ts.map +1 -1
  70. package/dist/commonjs/tabs/lib/TabsItem.js +1 -0
  71. package/dist/es6/action-bar/index.d.ts +1 -0
  72. package/dist/es6/action-bar/index.d.ts.map +1 -1
  73. package/dist/es6/action-bar/index.js +1 -0
  74. package/dist/es6/action-bar/lib/ActionBar.d.ts +3495 -5
  75. package/dist/es6/action-bar/lib/ActionBar.d.ts.map +1 -1
  76. package/dist/es6/action-bar/lib/ActionBar.js +29 -28
  77. package/dist/es6/action-bar/lib/ActionBarItem.d.ts +215 -0
  78. package/dist/es6/action-bar/lib/ActionBarItem.d.ts.map +1 -0
  79. package/dist/es6/action-bar/lib/ActionBarItem.js +24 -0
  80. package/dist/es6/action-bar/lib/ActionBarList.d.ts +221 -0
  81. package/dist/es6/action-bar/lib/ActionBarList.d.ts.map +1 -0
  82. package/dist/es6/action-bar/lib/ActionBarList.js +52 -0
  83. package/dist/es6/action-bar/lib/ActionBarOverflowButton.d.ts +230 -0
  84. package/dist/es6/action-bar/lib/ActionBarOverflowButton.d.ts.map +1 -0
  85. package/dist/es6/action-bar/lib/ActionBarOverflowButton.js +32 -0
  86. package/dist/es6/action-bar/lib/useActionBarModel.d.ts +1659 -0
  87. package/dist/es6/action-bar/lib/useActionBarModel.d.ts.map +1 -0
  88. package/dist/es6/action-bar/lib/useActionBarModel.js +71 -0
  89. package/dist/es6/avatar/lib/Avatar.d.ts.map +1 -1
  90. package/dist/es6/avatar/lib/Avatar.js +3 -0
  91. package/dist/es6/button/index.d.ts +1 -0
  92. package/dist/es6/button/index.d.ts.map +1 -1
  93. package/dist/es6/button/index.js +1 -0
  94. package/dist/es6/button/lib/ExternalHyperlink.d.ts +11 -0
  95. package/dist/es6/button/lib/ExternalHyperlink.d.ts.map +1 -0
  96. package/dist/es6/button/lib/ExternalHyperlink.js +42 -0
  97. package/dist/es6/button/lib/TertiaryButton.d.ts.map +1 -1
  98. package/dist/es6/button/lib/TertiaryButton.js +1 -0
  99. package/dist/es6/collection/lib/useListItemRovingFocus.d.ts +1 -1
  100. package/dist/es6/collection/lib/useListItemRovingFocus.d.ts.map +1 -1
  101. package/dist/es6/collection/lib/useListItemRovingFocus.js +2 -2
  102. package/dist/es6/collection/lib/useListRenderItem.d.ts +1 -1
  103. package/dist/es6/collection/lib/useListRenderItem.d.ts.map +1 -1
  104. package/dist/es6/collection/lib/useListRenderItem.js +2 -2
  105. package/dist/es6/common/lib/parts/_brand-assets.js +1 -1
  106. package/dist/es6/common/lib/utils/elements.d.ts +2 -2
  107. package/dist/es6/common/lib/utils/elements.d.ts.map +1 -1
  108. package/dist/es6/common/lib/utils/elements.js +4 -1
  109. package/dist/es6/form-field/lib/Label.d.ts.map +1 -1
  110. package/dist/es6/form-field/lib/Label.js +1 -2
  111. package/dist/es6/icon/lib/Icon.d.ts +1 -1
  112. package/dist/es6/icon/lib/Icon.d.ts.map +1 -1
  113. package/dist/es6/icon/lib/Icon.js +2 -4
  114. package/dist/es6/icon/lib/SystemIcon.d.ts +1 -1
  115. package/dist/es6/icon/lib/SystemIcon.d.ts.map +1 -1
  116. package/dist/es6/popup/lib/hooks/useDisableBodyScroll.d.ts.map +1 -1
  117. package/dist/es6/popup/lib/hooks/useDisableBodyScroll.js +2 -0
  118. package/dist/es6/popup/lib/hooks/usePopupTarget.js +1 -1
  119. package/dist/es6/table/lib/TableRow.d.ts +4 -4
  120. package/dist/es6/table/lib/TableRow.d.ts.map +1 -1
  121. package/dist/es6/table/lib/TableRow.js +12 -26
  122. package/dist/es6/tabs/lib/Tabs.d.ts.map +1 -1
  123. package/dist/es6/tabs/lib/Tabs.js +1 -2
  124. package/dist/es6/tabs/lib/TabsItem.d.ts.map +1 -1
  125. package/dist/es6/tabs/lib/TabsItem.js +1 -0
  126. package/form-field/lib/Label.tsx +1 -2
  127. package/icon/lib/Icon.tsx +2 -1
  128. package/icon/lib/SystemIcon.tsx +1 -1
  129. package/package.json +5 -5
  130. package/popup/lib/hooks/useDisableBodyScroll.ts +2 -0
  131. package/popup/lib/hooks/usePopupTarget.ts +1 -1
  132. package/table/lib/TableRow.tsx +18 -11
  133. package/tabs/lib/Tabs.tsx +1 -5
  134. package/tabs/lib/TabsItem.tsx +1 -0
@@ -1 +1,2 @@
1
1
  export * from './lib/ActionBar';
2
+ export * from './lib/useActionBarModel';
@@ -1,37 +1,39 @@
1
1
  import * as React from 'react';
2
- import {createComponent, styled, StyledType} from '@workday/canvas-kit-react/common';
3
- import {commonColors, colors, space} from '@workday/canvas-kit-react/tokens';
4
- import {HStack, HStackProps, StackSpacing} from '@workday/canvas-kit-react/layout';
2
+ import {createContainer} from '@workday/canvas-kit-react/common';
3
+ import {Menu} from '@workday/canvas-kit-react/menu';
4
+ import {useActionBarModel} from './useActionBarModel';
5
+ import {ActionBarList} from './ActionBarList';
6
+ import {ActionBarOverflowButton} from './ActionBarOverflowButton';
7
+ import {ActionBarItem} from './ActionBarItem';
5
8
 
6
- interface ActionBarProps extends Omit<HStackProps, 'spacing'> {
7
- spacing?: StackSpacing;
9
+ export interface ActionBarProps {
10
+ /**
11
+ * The contents of the ActionBar. Can be `ActionBar` children or any valid elements.
12
+ */
13
+ children: React.ReactNode;
8
14
  }
9
15
 
10
- const ResponsiveHStack = styled(HStack)<HStackProps & StyledType>(({theme}) => ({
11
- [theme.canvas.breakpoints.down('s')]: {
12
- padding: space.s,
13
- '> *:not(div)': {
14
- flex: 1,
15
- },
16
- },
17
- }));
18
-
19
- export const ActionBar = createComponent('div')({
16
+ export const ActionBar = createContainer()({
20
17
  displayName: 'ActionBar',
21
- Component: (elemProps: ActionBarProps, ref, Element) => (
22
- <ResponsiveHStack
23
- ref={ref}
24
- as={Element}
25
- spacing="s"
26
- depth={1}
27
- background={commonColors.background}
28
- borderTop={`solid 1px ${colors.soap400}`}
29
- padding={`${space.s} ${space.xl} `}
30
- position="fixed"
31
- bottom={0}
32
- left={0}
33
- right={0}
34
- {...elemProps}
35
- />
36
- ),
18
+ modelHook: useActionBarModel,
19
+ subComponents: {
20
+ List: ActionBarList,
21
+ Item: ActionBarItem,
22
+ OverflowButton: ActionBarOverflowButton,
23
+ /**
24
+ * The overflow menu of the ActionBar component. If there isn't enough room to render all the action
25
+ * items, the extra actions that don't fit will be overflowed into this menu.
26
+ * @example
27
+ * <ActionBar.Menu.Popper>
28
+ * <ActionBar.Menu.Card>
29
+ * <ActionBar.Menu.List>
30
+ * {(item: MyActionItem) => <ActionBar.Menu.Item>{item.text}</ActionBar.Menu.Item>}
31
+ * </ActionBar.Menu.List>
32
+ * </ActionBar.Menu.Card>
33
+ * </ActionBar.Menu.Popper>
34
+ */
35
+ Menu,
36
+ },
37
+ })<ActionBarProps>(({children}, _, model) => {
38
+ return <Menu model={model.menu}>{children}</Menu>;
37
39
  });
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ import {composeHooks, createSubcomponent} from '@workday/canvas-kit-react/common';
3
+ import {SecondaryButton} from '@workday/canvas-kit-react/button';
4
+ import {
5
+ useListItemRegister,
6
+ useListItemRovingFocus,
7
+ useOverflowListItemMeasure,
8
+ } from '@workday/canvas-kit-react/collection';
9
+
10
+ import {useActionBarModel} from './useActionBarModel';
11
+
12
+ export interface ActionBarItemProps {
13
+ /**
14
+ * The contents of the action item. This will be the accessible name of the action for screen readers.
15
+ *
16
+ * ```tsx
17
+ * <ActionBar.Item>First Action</ActionBar.Item>
18
+ * ```
19
+ */
20
+ children: React.ReactNode;
21
+ /**
22
+ * The identifier of the action. This identifier will be used for correct overflow behavior.
23
+ * If this property is not provided, it will default to a string representation
24
+ * of the the zero-based index of the Item when it was initialized.
25
+ */
26
+ 'data-id'?: string;
27
+ }
28
+
29
+ export const useActionBarItem = composeHooks(
30
+ useOverflowListItemMeasure,
31
+ useListItemRovingFocus,
32
+ useListItemRegister
33
+ );
34
+
35
+ export const ActionBarItem = createSubcomponent(SecondaryButton)({
36
+ displayName: 'ActionBar.Item',
37
+ modelHook: useActionBarModel,
38
+ elemPropsHook: useActionBarItem,
39
+ })<ActionBarItemProps>((elemProps, Element) => {
40
+ return <Element {...elemProps} />;
41
+ });
@@ -0,0 +1,70 @@
1
+ import * as React from 'react';
2
+
3
+ import {commonColors, colors, space} from '@workday/canvas-kit-react/tokens';
4
+ import {
5
+ composeHooks,
6
+ createSubcomponent,
7
+ ExtractProps,
8
+ styled,
9
+ StyledType,
10
+ } from '@workday/canvas-kit-react/common';
11
+ import {HStack} from '@workday/canvas-kit-react/layout';
12
+ import {
13
+ useOverflowListMeasure,
14
+ useListRenderItems,
15
+ useListResetCursorOnBlur,
16
+ } from '@workday/canvas-kit-react/collection';
17
+
18
+ import {useActionBarModel} from './useActionBarModel';
19
+ import {ActionBar} from './ActionBar';
20
+
21
+ // Use `Partial` here to make `spacing` optional
22
+ export interface ActionBarListProps<T = unknown>
23
+ extends Partial<ExtractProps<typeof HStack, never>> {
24
+ /**
25
+ * If items are passed to a `ActionBarModel`, the child of `ActionBar.List` should be a render prop. The
26
+ * List will determine how and when the item will be rendered.
27
+ *
28
+ * @example
29
+ * <ActionBar.List>
30
+ * {(item) => <ActionBar.Item key={item.id} name={item.name}>{item.text}</ActionBar.Item>}
31
+ * </ActionBar.List>
32
+ */
33
+ children: ((item: T) => React.ReactNode) | React.ReactNode;
34
+ }
35
+
36
+ const ResponsiveHStack = styled(HStack)<ActionBarListProps & StyledType>(({theme}) => ({
37
+ [theme.canvas.breakpoints.down('s')]: {
38
+ padding: space.s,
39
+ '> *': {
40
+ flex: 1,
41
+ },
42
+ },
43
+ }));
44
+
45
+ export const useActionBarList = composeHooks(useOverflowListMeasure, useListResetCursorOnBlur);
46
+
47
+ export const ActionBarList = createSubcomponent('div')({
48
+ displayName: 'ActionBar.List',
49
+ modelHook: useActionBarModel,
50
+ elemPropsHook: useActionBarList,
51
+ })<ActionBarListProps>(({children, ...elemProps}, Element, model) => {
52
+ return (
53
+ <ResponsiveHStack
54
+ as={Element}
55
+ spacing="s"
56
+ depth={1}
57
+ background={commonColors.background}
58
+ borderTop={`solid 1px ${colors.soap400}`}
59
+ padding={`${space.s} ${space.xl} `}
60
+ position="fixed"
61
+ bottom={0}
62
+ left={0}
63
+ right={0}
64
+ {...elemProps}
65
+ >
66
+ {useListRenderItems(model, children)}
67
+ <ActionBar.OverflowButton />
68
+ </ResponsiveHStack>
69
+ );
70
+ });
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import styled from '@emotion/styled';
3
+
4
+ import {relatedActionsIcon} from '@workday/canvas-system-icons-web';
5
+ import {
6
+ createElemPropsHook,
7
+ composeHooks,
8
+ subModelHook,
9
+ createSubcomponent,
10
+ StyledType,
11
+ } from '@workday/canvas-kit-react/common';
12
+ import {useOverflowListTarget} from '@workday/canvas-kit-react/collection';
13
+
14
+ import {useMenuTarget} from '@workday/canvas-kit-react/menu';
15
+ import {useActionBarModel} from './useActionBarModel';
16
+ import {SecondaryButton} from '@workday/canvas-kit-react/button';
17
+
18
+ export const useActionBarOverflowButton = composeHooks(
19
+ createElemPropsHook(useActionBarModel)(() => ({
20
+ 'aria-haspopup': true,
21
+ })),
22
+ useOverflowListTarget,
23
+ subModelHook((m: ReturnType<typeof useActionBarModel>) => m.menu, useMenuTarget)
24
+ );
25
+
26
+ const StyledSecondaryButton = styled(SecondaryButton)<StyledType>({
27
+ flex: 0,
28
+ });
29
+
30
+ export const ActionBarOverflowButton = createSubcomponent('button')({
31
+ displayName: 'ActionBar.OverflowButton',
32
+ modelHook: useActionBarModel,
33
+ elemPropsHook: useActionBarOverflowButton,
34
+ })((elemProps, Element) => {
35
+ return <StyledSecondaryButton as={Element} icon={relatedActionsIcon} {...elemProps} />;
36
+ });
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import {createModelHook} from '@workday/canvas-kit-react/common';
3
+ import {defaultGetId, useOverflowListModel} from '@workday/canvas-kit-react/collection';
4
+
5
+ import {useMenuModel} from '@workday/canvas-kit-react/menu';
6
+
7
+ export const useActionBarModel = createModelHook({
8
+ defaultConfig: {
9
+ ...useOverflowListModel.defaultConfig,
10
+ /**
11
+ * Optional id for the whole `ActionBar` group. If not provided, a unique id will be created.
12
+ * @default useUniqueId()
13
+ */
14
+ id: '',
15
+ /**
16
+ * The default ActionBar sub-components only handle rendering of button group in a horizontal orientation,
17
+ * but the sub-components could be replaced to handle vertical orientations.
18
+ * @default 'horizontal'
19
+ */
20
+ orientation: 'horizontal' as typeof useOverflowListModel.defaultConfig.orientation,
21
+ menuConfig: {} as Partial<typeof useMenuModel.defaultConfig>,
22
+ },
23
+ requiredConfig: useOverflowListModel.requiredConfig,
24
+ })(config => {
25
+ const getId = config.getId || defaultGetId;
26
+
27
+ const items = config.items;
28
+
29
+ const model = useOverflowListModel(
30
+ useOverflowListModel.mergeConfig(config, {
31
+ orientation: config.orientation || 'horizontal',
32
+ items,
33
+ shouldVirtualize: false,
34
+ })
35
+ );
36
+
37
+ let hiddenIds = model.state.hiddenIds;
38
+ let nonInteractiveIds = model.state.nonInteractiveIds;
39
+ const totalSize = model.state.items.length;
40
+
41
+ // Only show a maximum of 3 buttons
42
+ if (totalSize - hiddenIds.length >= 3) {
43
+ hiddenIds = items.slice(3, totalSize).map(getId);
44
+ }
45
+
46
+ // Always show the first button and make sure it is interactive
47
+ if (totalSize - hiddenIds.length === 0) {
48
+ hiddenIds = items.slice(1, totalSize).map(getId);
49
+ }
50
+
51
+ nonInteractiveIds = hiddenIds;
52
+
53
+ const state = {
54
+ ...model.state,
55
+ hiddenIds,
56
+ nonInteractiveIds,
57
+ orientation: config.orientation || 'horizontal',
58
+ };
59
+
60
+ const overflowItems = React.useMemo(
61
+ () => (items ? items.filter(item => state.hiddenIds.includes(getId(item))) : undefined),
62
+ // eslint-disable-next-line react-hooks/exhaustive-deps
63
+ [state.hiddenIds, items]
64
+ );
65
+
66
+ const events = {
67
+ ...model.events,
68
+ };
69
+
70
+ const menu = useMenuModel(
71
+ useMenuModel.mergeConfig(config.menuConfig as Required<typeof config.menuConfig>, {
72
+ id: `act-bar-menu-${model.state.id}`,
73
+ items: overflowItems,
74
+ nonInteractiveIds: state.nonInteractiveIds.filter(key => !state.hiddenIds.includes(key)),
75
+ onSelect() {
76
+ menu.events.hide();
77
+ },
78
+ onShow() {
79
+ // Always select the first item when the menu is opened
80
+ menu.events.goToFirst();
81
+ },
82
+ })
83
+ );
84
+
85
+ return {
86
+ ...model,
87
+ state,
88
+ events,
89
+ menu,
90
+ };
91
+ });
@@ -139,6 +139,10 @@ const Avatar: AvatarOverload = React.forwardRef(
139
139
  }
140
140
  };
141
141
 
142
+ React.useLayoutEffect(() => {
143
+ setImageLoaded(false);
144
+ }, [url]);
145
+
142
146
  const background = variant === AvatarVariant.Dark ? colors.blueberry400 : colors.soap300;
143
147
 
144
148
  return (
package/button/index.ts CHANGED
@@ -10,4 +10,5 @@ export {ToolbarIconButton, ToolbarIconButtonProps} from './lib/ToolbarIconButton
10
10
  export {ToolbarDropdownButton, ToolbarDropdownButtonProps} from './lib/ToolbarDropdownButton';
11
11
  export {Hyperlink, HyperlinkProps} from './lib/Hyperlink';
12
12
  export {BaseButton, ButtonContainerProps} from './lib/BaseButton';
13
+ export {ExternalHyperlink, ExternalHyperlinkProps} from './lib/ExternalHyperlink';
13
14
  export * from './lib/types';
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import {styled, createComponent, StyledType} from '@workday/canvas-kit-react/common';
3
+ import {extLinkIcon} from '@workday/canvas-system-icons-web';
4
+ import {SystemIcon, systemIconStyles} from '@workday/canvas-kit-react/icon';
5
+ import {Hyperlink, HyperlinkProps} from './Hyperlink';
6
+
7
+ export interface ExternalHyperlinkProps extends HyperlinkProps {
8
+ /**
9
+ * Informs a screen reader user the link will open in a new window. It is read after the link text.
10
+ * This value will need to be translated.
11
+ * @default 'Opens link in new window'
12
+ */
13
+ iconLabel?: string;
14
+ }
15
+
16
+ const iconStyles = {
17
+ ...systemIconStyles({fill: 'currentColor', fillHover: 'currentColor'}),
18
+ };
19
+
20
+ const Anchor = styled(Hyperlink)<ExternalHyperlinkProps & StyledType>({
21
+ ...iconStyles,
22
+ display: 'inline-flex',
23
+ flexDirection: 'row',
24
+ alignItems: 'center',
25
+ });
26
+
27
+ const iconSize = '1em';
28
+ const minIconSize = '16px';
29
+
30
+ const StyledSystemIcon = styled(SystemIcon)<StyledType>({
31
+ ...iconStyles,
32
+ width: `calc(${iconSize} - 1px)`,
33
+ minWidth: `calc(${minIconSize} - 1px)`,
34
+ marginLeft: '2px',
35
+ });
36
+
37
+ export const ExternalHyperlink = createComponent('a')({
38
+ displayName: 'ExternalHyperlink',
39
+ Component: (
40
+ {
41
+ children,
42
+ variant,
43
+ iconLabel = 'Opens link in new window',
44
+ ...elemProps
45
+ }: ExternalHyperlinkProps,
46
+ ref
47
+ ) => (
48
+ <Anchor ref={ref} target="_blank" rel="noreferrer" variant={variant} {...elemProps}>
49
+ <span>{children}</span>
50
+ <StyledSystemIcon
51
+ icon={extLinkIcon}
52
+ role="img"
53
+ aria-label={iconLabel}
54
+ size={iconSize}
55
+ styles={{['& svg']: {minWidth: minIconSize, minHeight: minIconSize}}}
56
+ />
57
+ </Anchor>
58
+ ),
59
+ });
@@ -118,6 +118,7 @@ const getTertiaryButtonColors = (
118
118
  focusRing: focusRing({innerColor: colors.blueberry400}, theme),
119
119
  },
120
120
  disabled: {
121
+ background: 'transparent',
121
122
  icon: children ? themePrimary.main : colors.blackPepper400,
122
123
  label: themePrimary.main,
123
124
  },
@@ -85,7 +85,9 @@ export const useListItemRovingFocus = createElemPropsHook(useCursorListModel)(
85
85
  }
86
86
  requestAnimationFrame(() => {
87
87
  document
88
- .querySelector<HTMLElement>(`[id="${state.id}-${getIdRef.current(item)}"]`)
88
+ .querySelector<HTMLElement>(
89
+ `[data-focus-id="${`${state.id}-${getIdRef.current(item)}`}"]`
90
+ )
89
91
  ?.focus();
90
92
  });
91
93
 
@@ -132,7 +134,7 @@ export const useListItemRovingFocus = createElemPropsHook(useCursorListModel)(
132
134
  onClick() {
133
135
  events.goTo({id: elemProps['data-id']!});
134
136
  },
135
- id: `${state.id}-${elemProps['data-id']}`,
137
+ 'data-focus-id': `${state.id}-${elemProps['data-id']}`,
136
138
  tabIndex: !state.cursorId
137
139
  ? 0 // cursor isn't known yet, be safe and mark this as focusable
138
140
  : !!elemProps['data-id'] && state.cursorId === elemProps['data-id']
@@ -6,14 +6,14 @@ import {useBaseListModel} from './useBaseListModel';
6
6
 
7
7
  export function useListRenderItems<T>(
8
8
  model: ReturnType<typeof useBaseListModel>,
9
- children: ((item: Generic) => React.ReactNode) | React.ReactNode
9
+ children: ((item: Generic, index: number) => React.ReactNode) | React.ReactNode
10
10
  ) {
11
11
  const items =
12
12
  typeof children === 'function'
13
13
  ? model.state.isVirtualized
14
14
  ? model.state.UNSTABLE_virtual.virtualItems.map(virtual => {
15
15
  const item = model.state.items[virtual.index];
16
- const child = children(item.value);
16
+ const child = children(item.value, virtual.index);
17
17
  return React.cloneElement(child, {
18
18
  // We call this `virtual` instead of `virtualItem` to avoid a React render warning
19
19
  // about capital letters in attributes. React thinks this will be applied to the DOM
@@ -24,7 +24,7 @@ export function useListRenderItems<T>(
24
24
  });
25
25
  })
26
26
  : model.state.items.map(item =>
27
- React.cloneElement(children(item.value), {key: item.id, item: item.value})
27
+ React.cloneElement(children(item.value, item.index), {key: item.id, item: item.value})
28
28
  )
29
29
  : null;
30
30
 
@@ -1,4 +1,4 @@
1
- const CDN_URI = '//design.workday.com/images/';
1
+ const CDN_URI = 'https://design.workday.com/images/';
2
2
 
3
3
  export const dubLogoBlue = `<img src="${CDN_URI}ck-dub-logo-blue.svg" alt="">`;
4
4
 
@@ -1,8 +1,12 @@
1
1
  /**
2
2
  * Is an element focusable? This function performs various tests to see if the element in question
3
- * can receive focus.
3
+ * can receive focus. Should skip disabled elements as they are not focusable.
4
4
  */
5
5
  export const isFocusable = (element: HTMLElement) => {
6
+ if (element.hasAttribute('disabled')) {
7
+ return null;
8
+ }
9
+
6
10
  const nodeName = element.nodeName.toLowerCase();
7
11
  const validInput = nodeName === 'input' && element.getAttribute('type') !== 'hidden';
8
12
  const validAnchor = nodeName === 'a' && element.hasAttribute('href');
@@ -1,2 +1,3 @@
1
1
  export * from './lib/ActionBar';
2
+ export * from './lib/useActionBarModel';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../action-bar/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../action-bar/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
@@ -11,3 +11,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  __exportStar(require("./lib/ActionBar"), exports);
14
+ __exportStar(require("./lib/useActionBarModel"), exports);