@apify/ui-library 1.132.1 → 1.134.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.
- package/dist/src/components/box.d.ts.map +1 -1
- package/dist/src/components/card_container.js.map +1 -1
- package/dist/src/components/chip.d.ts.map +1 -1
- package/dist/src/components/chip.js.map +1 -1
- package/dist/src/components/code/code_block/code_block.d.ts.map +1 -1
- package/dist/src/components/code/inline_code/inline_code.d.ts.map +1 -1
- package/dist/src/components/code/one_line_code/one_line_code.d.ts.map +1 -1
- package/dist/src/components/code/prism_highlighter.d.ts.map +1 -1
- package/dist/src/components/code/prism_highlighter.js.map +1 -1
- package/dist/src/components/floating/tooltip.d.ts.map +1 -1
- package/dist/src/components/floating/tooltip.js +8 -0
- package/dist/src/components/floating/tooltip.js.map +1 -1
- package/dist/src/components/icon_button.d.ts.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/components/link.d.ts +3 -0
- package/dist/src/components/link.d.ts.map +1 -1
- package/dist/src/components/link.js +2 -2
- package/dist/src/components/link.js.map +1 -1
- package/dist/src/components/rating.d.ts.map +1 -1
- package/dist/src/components/simple_markdown/simple_markdown.d.ts.map +1 -1
- package/dist/src/components/spinner.d.ts.map +1 -1
- package/dist/src/components/spinner.js.map +1 -1
- package/dist/src/components/store/store_actor_header.d.ts.map +1 -1
- package/dist/src/components/store/store_actor_header.js.map +1 -1
- package/dist/src/components/table/index.d.ts +17 -0
- package/dist/src/components/table/index.d.ts.map +1 -0
- package/dist/src/components/table/index.js +16 -0
- package/dist/src/components/table/index.js.map +1 -0
- package/dist/src/components/table/table.context.d.ts +3 -0
- package/dist/src/components/table/table.context.d.ts.map +1 -0
- package/dist/src/components/table/table.context.js +3 -0
- package/dist/src/components/table/table.context.js.map +1 -0
- package/dist/src/components/table/table.d.ts +3 -0
- package/dist/src/components/table/table.d.ts.map +1 -0
- package/dist/src/components/table/table.js +6 -0
- package/dist/src/components/table/table.js.map +1 -0
- package/dist/src/components/table/table.styled.d.ts +30 -0
- package/dist/src/components/table/table.styled.d.ts.map +1 -0
- package/dist/src/components/table/table.styled.js +194 -0
- package/dist/src/components/table/table.styled.js.map +1 -0
- package/dist/src/components/table/table_body.d.ts +3 -0
- package/dist/src/components/table/table_body.d.ts.map +1 -0
- package/dist/src/components/table/table_body.js +6 -0
- package/dist/src/components/table/table_body.js.map +1 -0
- package/dist/src/components/table/table_cell.d.ts +10 -0
- package/dist/src/components/table/table_cell.d.ts.map +1 -0
- package/dist/src/components/table/table_cell.js +18 -0
- package/dist/src/components/table/table_cell.js.map +1 -0
- package/dist/src/components/table/table_empty_row.d.ts +6 -0
- package/dist/src/components/table/table_empty_row.d.ts.map +1 -0
- package/dist/src/components/table/table_empty_row.js +5 -0
- package/dist/src/components/table/table_empty_row.js.map +1 -0
- package/dist/src/components/table/table_error_row.d.ts +7 -0
- package/dist/src/components/table/table_error_row.d.ts.map +1 -0
- package/dist/src/components/table/table_error_row.js +6 -0
- package/dist/src/components/table/table_error_row.js.map +1 -0
- package/dist/src/components/table/table_expansion_row.d.ts +10 -0
- package/dist/src/components/table/table_expansion_row.d.ts.map +1 -0
- package/dist/src/components/table/table_expansion_row.js +10 -0
- package/dist/src/components/table/table_expansion_row.js.map +1 -0
- package/dist/src/components/table/table_foot.d.ts +3 -0
- package/dist/src/components/table/table_foot.d.ts.map +1 -0
- package/dist/src/components/table/table_foot.js +6 -0
- package/dist/src/components/table/table_foot.js.map +1 -0
- package/dist/src/components/table/table_head.d.ts +3 -0
- package/dist/src/components/table/table_head.d.ts.map +1 -0
- package/dist/src/components/table/table_head.js +6 -0
- package/dist/src/components/table/table_head.js.map +1 -0
- package/dist/src/components/table/table_head_cell.d.ts +3 -0
- package/dist/src/components/table/table_head_cell.d.ts.map +1 -0
- package/dist/src/components/table/table_head_cell.js +6 -0
- package/dist/src/components/table/table_head_cell.js.map +1 -0
- package/dist/src/components/table/table_head_row.d.ts +3 -0
- package/dist/src/components/table/table_head_row.d.ts.map +1 -0
- package/dist/src/components/table/table_head_row.js +6 -0
- package/dist/src/components/table/table_head_row.js.map +1 -0
- package/dist/src/components/table/table_loading_row.d.ts +6 -0
- package/dist/src/components/table/table_loading_row.d.ts.map +1 -0
- package/dist/src/components/table/table_loading_row.js +6 -0
- package/dist/src/components/table/table_loading_row.js.map +1 -0
- package/dist/src/components/table/table_row.d.ts +4 -0
- package/dist/src/components/table/table_row.d.ts.map +1 -0
- package/dist/src/components/table/table_row.js +12 -0
- package/dist/src/components/table/table_row.js.map +1 -0
- package/dist/src/components/table/table_test_ids.d.ts +16 -0
- package/dist/src/components/table/table_test_ids.d.ts.map +1 -0
- package/dist/src/components/table/table_test_ids.js +16 -0
- package/dist/src/components/table/table_test_ids.js.map +1 -0
- package/dist/src/components/table/table_wrapper.d.ts +4 -0
- package/dist/src/components/table/table_wrapper.d.ts.map +1 -0
- package/dist/src/components/table/table_wrapper.js +49 -0
- package/dist/src/components/table/table_wrapper.js.map +1 -0
- package/dist/src/components/table/types.d.ts +21 -0
- package/dist/src/components/table/types.d.ts.map +1 -0
- package/dist/src/components/table/types.js +2 -0
- package/dist/src/components/table/types.js.map +1 -0
- package/dist/src/components/tag.d.ts.map +1 -1
- package/dist/src/components/to_consolidate/pagination.d.ts.map +1 -1
- package/dist/src/design_system/theme.d.ts.map +1 -1
- package/dist/src/type_utils.d.ts.map +1 -1
- package/dist/src/ui_dependency_provider.d.ts.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/components/box.tsx +1 -1
- package/src/components/card_container.tsx +1 -1
- package/src/components/chip.tsx +3 -3
- package/src/components/code/code_block/code_block.tsx +3 -3
- package/src/components/code/inline_code/inline_code.tsx +1 -1
- package/src/components/code/one_line_code/one_line_code.tsx +2 -2
- package/src/components/code/prism_highlighter.tsx +1 -1
- package/src/components/floating/tooltip.tsx +8 -0
- package/src/components/image.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/components/link.stories.tsx +12 -0
- package/src/components/link.tsx +9 -0
- package/src/components/rating.tsx +3 -3
- package/src/components/simple_markdown/simple_markdown.tsx +1 -1
- package/src/components/spinner.tsx +1 -1
- package/src/components/store/store_actor_header.tsx +2 -2
- package/src/components/table/index.ts +16 -0
- package/src/components/table/table.context.ts +5 -0
- package/src/components/table/table.stories.tsx +258 -0
- package/src/components/table/table.styled.ts +207 -0
- package/src/components/table/table.tsx +9 -0
- package/src/components/table/table_body.tsx +9 -0
- package/src/components/table/table_cell.tsx +28 -0
- package/src/components/table/table_empty_row.tsx +12 -0
- package/src/components/table/table_error_row.tsx +13 -0
- package/src/components/table/table_expansion_row.tsx +24 -0
- package/src/components/table/table_foot.tsx +9 -0
- package/src/components/table/table_head.tsx +9 -0
- package/src/components/table/table_head_cell.tsx +9 -0
- package/src/components/table/table_head_row.tsx +9 -0
- package/src/components/table/table_loading_row.tsx +13 -0
- package/src/components/table/table_row.tsx +30 -0
- package/src/components/table/table_test_ids.ts +15 -0
- package/src/components/table/table_wrapper.tsx +71 -0
- package/src/components/table/types.ts +24 -0
- package/src/components/tabs/tabs.tsx +1 -1
- package/src/components/tag.tsx +1 -1
- package/src/components/to_consolidate/pagination.tsx +1 -1
- package/src/design_system/theme.ts +1 -1
- package/src/type_utils.ts +1 -1
- package/src/ui_dependency_provider.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/ui-library",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.134.0",
|
|
4
4
|
"description": "React UI library used by apify.com",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"postpublish": "npm run clean"
|
|
24
24
|
},
|
|
25
25
|
"//": [
|
|
26
|
-
"Storybook for the components lives in a separate package
|
|
26
|
+
"Storybook for the components lives in a separate package ui-storybook.",
|
|
27
27
|
"It's not nice, but helps us to get around the problem of multiple react instances."
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"src",
|
|
71
71
|
"style"
|
|
72
72
|
],
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "f8321843cceed834c46deb61af56d269efc3c7ae"
|
|
74
74
|
}
|
package/src/components/box.tsx
CHANGED
|
@@ -34,7 +34,7 @@ type SharedBoxProps = {
|
|
|
34
34
|
style?: React.CSSProperties
|
|
35
35
|
onClick?: (e: React.MouseEvent) => void,
|
|
36
36
|
id?: string,
|
|
37
|
-
}
|
|
37
|
+
};
|
|
38
38
|
|
|
39
39
|
// This should be renamed - these props are global for any element not just Boxes
|
|
40
40
|
export type RegularBoxProps = SharedBoxProps & { as?: React.ElementType };
|
|
@@ -16,7 +16,7 @@ const HEADER_PLACEMENT = {
|
|
|
16
16
|
BOTTOM: 'BOTTOM',
|
|
17
17
|
} as const;
|
|
18
18
|
|
|
19
|
-
const Wrapper = styled(Box)<{$headerPlacement: ValueOf<typeof HEADER_PLACEMENT>}>`
|
|
19
|
+
const Wrapper = styled(Box)<{ $headerPlacement: ValueOf<typeof HEADER_PLACEMENT> }>`
|
|
20
20
|
background-color: ${theme.color.neutral.backgroundSubtle};
|
|
21
21
|
border-radius: ${theme.radius.radius12};
|
|
22
22
|
|
package/src/components/chip.tsx
CHANGED
|
@@ -80,7 +80,7 @@ const chipTypeStyle = {
|
|
|
80
80
|
`,
|
|
81
81
|
} satisfies Record<CHIP_TYPES, unknown>;
|
|
82
82
|
|
|
83
|
-
const StyledChip = styled.span<{size: CHIP_SIZES, type: CHIP_TYPES, clickable: boolean}>`
|
|
83
|
+
const StyledChip = styled.span<{ size: CHIP_SIZES, type: CHIP_TYPES, clickable: boolean }>`
|
|
84
84
|
${({ size }) => chipSizeStyle[size]};
|
|
85
85
|
${({ type }) => chipTypeStyle[type]};
|
|
86
86
|
/* Static styles */
|
|
@@ -100,7 +100,7 @@ export type ChipProps = RegularBoxProps & {
|
|
|
100
100
|
size?: CHIP_SIZES
|
|
101
101
|
icon?: React.ReactNode
|
|
102
102
|
clickable?: boolean
|
|
103
|
-
}
|
|
103
|
+
};
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Component for displaying status and for labelling other components.
|
|
@@ -121,7 +121,7 @@ export const Chip = forwardRef(({
|
|
|
121
121
|
|
|
122
122
|
Chip.displayName = 'Chip';
|
|
123
123
|
|
|
124
|
-
type SpecificChipProps = Omit<ChipProps, 'type'
|
|
124
|
+
type SpecificChipProps = Omit<ChipProps, 'type'>;
|
|
125
125
|
|
|
126
126
|
export const PrimaryChip: FC<SpecificChipProps> = (props) => <Chip type={CHIP_TYPES.PRIMARY} {...props} />;
|
|
127
127
|
export const NeutralChip: FC<SpecificChipProps> = (props) => <Chip type={CHIP_TYPES.DEFAULT} {...props} />;
|
|
@@ -21,7 +21,7 @@ type CodeTab = {
|
|
|
21
21
|
language?: string;
|
|
22
22
|
bashCommandsStart?: number[];
|
|
23
23
|
to?: string;
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
25
|
|
|
26
26
|
type HeaderProps = {
|
|
27
27
|
tabs: CodeTab[] | null;
|
|
@@ -29,7 +29,7 @@ type HeaderProps = {
|
|
|
29
29
|
onTabChange: (tab: CodeTab, e: React.MouseEvent) => void;
|
|
30
30
|
title?: string;
|
|
31
31
|
showBashHeader?: boolean;
|
|
32
|
-
}
|
|
32
|
+
};
|
|
33
33
|
|
|
34
34
|
const LANGUAGES_WITHOUT_LINE_NUMBERS = ['json', 'jsonp', 'jsonp', 'rss', 'yaml', 'xml', 'html', 'bash', 'text', 'dockerfile', 'http'];
|
|
35
35
|
|
|
@@ -111,7 +111,7 @@ export type CodeBlockProps = RegularBoxProps & {
|
|
|
111
111
|
bashCommandsStart?: number[];
|
|
112
112
|
hideBashPromptPrefixes?: boolean;
|
|
113
113
|
hideLineNumbers?: boolean | undefined;
|
|
114
|
-
}
|
|
114
|
+
};
|
|
115
115
|
|
|
116
116
|
export const CodeBlock = ({
|
|
117
117
|
content,
|
|
@@ -51,7 +51,7 @@ type OneLineCodeWrapperProps = SyntaxHighlighterBaseStylesWrapperProps & {
|
|
|
51
51
|
$fitContent?: boolean;
|
|
52
52
|
$showBashPrefixes?: boolean;
|
|
53
53
|
$disabled?: boolean;
|
|
54
|
-
}
|
|
54
|
+
};
|
|
55
55
|
|
|
56
56
|
const OneLineCodeWrapper = styled(SyntaxHighlighterBaseStylesWrapper)<OneLineCodeWrapperProps>`
|
|
57
57
|
display: flex;
|
|
@@ -160,7 +160,7 @@ export type OneLineCodeProps = Omit<BoxProps, 'children'> & {
|
|
|
160
160
|
disabled?: boolean;
|
|
161
161
|
hideCopyButton?: boolean;
|
|
162
162
|
trackingBundle?: OneLineCodeTrackingBundle;
|
|
163
|
-
}
|
|
163
|
+
};
|
|
164
164
|
|
|
165
165
|
export function OneLineCode({
|
|
166
166
|
children,
|
|
@@ -128,7 +128,7 @@ const PreWrapper = styled.pre<PreWrapperProps>`
|
|
|
128
128
|
padding-left: ${({ $hasLinePrefixes }) => ($hasLinePrefixes ? '0.2' : '1')}rem;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
${({ $isSingleLine }) => !$isSingleLine && css<{$hasLinePrefixes: boolean}>`
|
|
131
|
+
${({ $isSingleLine }) => !$isSingleLine && css<{ $hasLinePrefixes: boolean }>`
|
|
132
132
|
&:hover {
|
|
133
133
|
background-color: ${HIGHLIGHT_BACKGROUND_COLOR} !important;
|
|
134
134
|
border-left: 6px solid ${theme.color.neutral.border} !important;
|
|
@@ -52,6 +52,14 @@ const StyledFloatingComponentBase = styled(FloatingComponentBase)<{ $isDarkTheme
|
|
|
52
52
|
background-color: ${theme.colorPalette.dark.neutral900};
|
|
53
53
|
padding: ${theme.space.space8};
|
|
54
54
|
|
|
55
|
+
a {
|
|
56
|
+
color: ${theme.colorPalette.dark.blue100};
|
|
57
|
+
|
|
58
|
+
&:hover {
|
|
59
|
+
color: ${theme.colorPalette.dark.blue75};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
${({ $isDarkTheme }) => $isDarkTheme && css`
|
|
56
64
|
box-shadow: ${theme.shadow.shadow2};
|
|
57
65
|
border: 1px solid ${theme.color.neutral.smallTooltipBorder};
|
package/src/components/image.tsx
CHANGED
|
@@ -10,7 +10,7 @@ type ImageProps = {
|
|
|
10
10
|
width?: number,
|
|
11
11
|
height?: number,
|
|
12
12
|
loading?: 'eager' | 'lazy' | undefined;
|
|
13
|
-
} & ImageProxyOptions
|
|
13
|
+
} & ImageProxyOptions;
|
|
14
14
|
|
|
15
15
|
export const Image = forwardRef<HTMLImageElement, ImageProps & Omit<BoxProps, 'as'>>((props, ref) => {
|
|
16
16
|
const { InternalImage } = useSharedUiDependencies();
|
package/src/components/index.ts
CHANGED
|
@@ -69,6 +69,18 @@ export default {
|
|
|
69
69
|
control: 'text',
|
|
70
70
|
description: 'The link text or content to display',
|
|
71
71
|
},
|
|
72
|
+
ariaHidden: {
|
|
73
|
+
control: 'boolean',
|
|
74
|
+
description: 'Whether the link should be hidden from screen readers (useful for decorative links)',
|
|
75
|
+
},
|
|
76
|
+
ariaLabel: {
|
|
77
|
+
control: 'text',
|
|
78
|
+
description: 'Accessible label for screen readers when the link text is not descriptive',
|
|
79
|
+
},
|
|
80
|
+
tabIndex: {
|
|
81
|
+
control: 'number',
|
|
82
|
+
description: 'Tab index for keyboard navigation (default is 0)',
|
|
83
|
+
},
|
|
72
84
|
},
|
|
73
85
|
parameters: {
|
|
74
86
|
design: {
|
package/src/components/link.tsx
CHANGED
|
@@ -19,6 +19,9 @@ export interface RegularLinkProps {
|
|
|
19
19
|
target?: string,
|
|
20
20
|
trackingId?: string,
|
|
21
21
|
trackingData?: object,
|
|
22
|
+
tabIndex?: number,
|
|
23
|
+
ariaHidden?: boolean,
|
|
24
|
+
ariaLabel?: string,
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
/**
|
|
@@ -104,6 +107,9 @@ export const Link = forwardRef<HTMLElement, LinkProps>(({
|
|
|
104
107
|
onClick,
|
|
105
108
|
trackingId,
|
|
106
109
|
trackingData,
|
|
110
|
+
tabIndex,
|
|
111
|
+
ariaHidden,
|
|
112
|
+
ariaLabel,
|
|
107
113
|
...rest
|
|
108
114
|
}, ref) => {
|
|
109
115
|
const {
|
|
@@ -139,6 +145,9 @@ export const Link = forwardRef<HTMLElement, LinkProps>(({
|
|
|
139
145
|
target={target || (isExternal ? '_blank' : '_self')}
|
|
140
146
|
onClick={trackedOnClick}
|
|
141
147
|
ref={ref}
|
|
148
|
+
tabIndex={tabIndex}
|
|
149
|
+
aria-hidden={ariaHidden}
|
|
150
|
+
aria-label={ariaLabel}
|
|
142
151
|
{...rest}
|
|
143
152
|
>
|
|
144
153
|
{children}
|
|
@@ -13,7 +13,7 @@ import { Text } from './text/index.js';
|
|
|
13
13
|
|
|
14
14
|
type RatingStatsProps = {
|
|
15
15
|
ratingStats: Record<ReviewRating, number>
|
|
16
|
-
}
|
|
16
|
+
};
|
|
17
17
|
|
|
18
18
|
const StyledRating = styled(Box)`
|
|
19
19
|
display: flex;
|
|
@@ -57,7 +57,7 @@ const StyledRatingBar = styled(Box)<{ $widthPercent: number }>`
|
|
|
57
57
|
|
|
58
58
|
type SingleStarRatingProps = BoxProps & {
|
|
59
59
|
color?: string;
|
|
60
|
-
}
|
|
60
|
+
};
|
|
61
61
|
|
|
62
62
|
export const SingleStarRating: FC<SingleStarRatingProps> = ({
|
|
63
63
|
color = theme.color.neutral.icon,
|
|
@@ -74,7 +74,7 @@ export const SingleStarRating: FC<SingleStarRatingProps> = ({
|
|
|
74
74
|
type RatingProps = BoxProps & {
|
|
75
75
|
rating: number | undefined;
|
|
76
76
|
color?: string;
|
|
77
|
-
}
|
|
77
|
+
};
|
|
78
78
|
|
|
79
79
|
export const Rating: FC<RatingProps> = ({
|
|
80
80
|
rating = 0,
|
|
@@ -190,7 +190,7 @@ export type SimpleMarkdownProps = Omit<ReactMarkdownOptions, 'urlTransform' | 'c
|
|
|
190
190
|
size?: MarkdownSize,
|
|
191
191
|
children: string,
|
|
192
192
|
className?: string,
|
|
193
|
-
}
|
|
193
|
+
};
|
|
194
194
|
|
|
195
195
|
export const useDefaultUrlTransform = () => {
|
|
196
196
|
const { windowLocationHost } = useSharedUiDependencies();
|
|
@@ -102,7 +102,7 @@ export const BlockSpinner = styled(Spinner)`
|
|
|
102
102
|
/**
|
|
103
103
|
* Use the inline variant within buttons, texts etc. The color of the spinner is set to current color of text.
|
|
104
104
|
*/
|
|
105
|
-
export const InlineSpinner = styled(Spinner)<{size?: string}>`
|
|
105
|
+
export const InlineSpinner = styled(Spinner)<{ size?: string }>`
|
|
106
106
|
display: inline-block;
|
|
107
107
|
position: relative;
|
|
108
108
|
height: ${({ size }) => size || theme.space.space12};
|
|
@@ -12,7 +12,7 @@ const storeActorHeaderClassNames = {
|
|
|
12
12
|
badge: 'ActorStoreItem-badge',
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
const StyledStoreActorHeader = styled(Box)<{ $compact: boolean}>`
|
|
15
|
+
const StyledStoreActorHeader = styled(Box)<{ $compact: boolean }>`
|
|
16
16
|
display: flex;
|
|
17
17
|
gap: ${({ $compact }) => ($compact ? theme.space.space4 : theme.space.space12)};
|
|
18
18
|
align-items: ${({ $compact }) => ($compact ? 'flex-start' : 'center')};
|
|
@@ -79,7 +79,7 @@ export type StoreActorHeaderProps = {
|
|
|
79
79
|
hasRisingStarBadge?: boolean,
|
|
80
80
|
avatarSize?: number,
|
|
81
81
|
compact?: boolean;
|
|
82
|
-
}
|
|
82
|
+
};
|
|
83
83
|
|
|
84
84
|
export const StoreActorHeader: React.FC<StoreActorHeaderProps & BoxProps> = ({
|
|
85
85
|
name,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { Table } from './table.js';
|
|
2
|
+
export { TableHead } from './table_head.js';
|
|
3
|
+
export { TableBody } from './table_body.js';
|
|
4
|
+
export { TableFoot } from './table_foot.js';
|
|
5
|
+
export { TableHeadRow } from './table_head_row.js';
|
|
6
|
+
export { TableHeadCell } from './table_head_cell.js';
|
|
7
|
+
export { TableRow } from './table_row.js';
|
|
8
|
+
export { TableCell, TableCellLink } from './table_cell.js';
|
|
9
|
+
export { HorizontallyScrollableTableWrapper } from './table_wrapper.js';
|
|
10
|
+
export { TableExpansionRow } from './table_expansion_row.js';
|
|
11
|
+
export { TableEmptyRow } from './table_empty_row.js';
|
|
12
|
+
export { TableLoadingRow } from './table_loading_row.js';
|
|
13
|
+
export { TableErrorRow } from './table_error_row.js';
|
|
14
|
+
export { tableClassNames } from './table.styled.js';
|
|
15
|
+
export { tableTestIds } from './table_test_ids.js';
|
|
16
|
+
export type { HorizontallyScrollableTableWrapperProps, TableExpansion, TableRowProps } from './types.js';
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, within } from 'storybook/test';
|
|
3
|
+
|
|
4
|
+
import { Text } from '../text/index.js';
|
|
5
|
+
import { Table } from './table.js';
|
|
6
|
+
import { TableBody } from './table_body.js';
|
|
7
|
+
import { TableCell, TableCellLink } from './table_cell.js';
|
|
8
|
+
import { TableEmptyRow } from './table_empty_row.js';
|
|
9
|
+
import { TableErrorRow } from './table_error_row.js';
|
|
10
|
+
import { TableHead } from './table_head.js';
|
|
11
|
+
import { TableHeadCell } from './table_head_cell.js';
|
|
12
|
+
import { TableHeadRow } from './table_head_row.js';
|
|
13
|
+
import { TableLoadingRow } from './table_loading_row.js';
|
|
14
|
+
import { TableRow } from './table_row.js';
|
|
15
|
+
import { HorizontallyScrollableTableWrapper } from './table_wrapper.js';
|
|
16
|
+
import { tableTestIds } from './table_test_ids.js';
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Mock data
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
type MockItem = {
|
|
23
|
+
_id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
status: string;
|
|
26
|
+
email: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const MOCK_DATA: MockItem[] = [
|
|
30
|
+
{ _id: '1', name: 'Web Scraper', status: 'active', email: 'alice@example.com' },
|
|
31
|
+
{ _id: '2', name: 'Data Extractor', status: 'inactive', email: 'bob@example.com' },
|
|
32
|
+
{ _id: '3', name: 'Email Sender', status: 'pending', email: 'carol@example.com' },
|
|
33
|
+
{ _id: '4', name: 'PDF Parser', status: 'active', email: 'dave@example.com' },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Storybook meta
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
const meta: Meta = {
|
|
41
|
+
title: 'UI-Library/Table',
|
|
42
|
+
tags: ['new'],
|
|
43
|
+
component: Table,
|
|
44
|
+
subcomponents: {
|
|
45
|
+
HorizontallyScrollableTableWrapper,
|
|
46
|
+
TableHead,
|
|
47
|
+
TableHeadRow,
|
|
48
|
+
TableHeadCell,
|
|
49
|
+
TableBody,
|
|
50
|
+
TableRow,
|
|
51
|
+
TableCell,
|
|
52
|
+
TableCellLink,
|
|
53
|
+
TableEmptyRow,
|
|
54
|
+
TableLoadingRow,
|
|
55
|
+
TableErrorRow,
|
|
56
|
+
},
|
|
57
|
+
parameters: {
|
|
58
|
+
docs: {
|
|
59
|
+
description: {
|
|
60
|
+
component: 'Compositional table primitives. Compose together to build any table layout. See subcomponents below.',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default meta;
|
|
67
|
+
|
|
68
|
+
type Story = StoryObj;
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Stories
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
/** Basic table with primitives only. */
|
|
75
|
+
export const Default: Story = {
|
|
76
|
+
render: () => (
|
|
77
|
+
<HorizontallyScrollableTableWrapper>
|
|
78
|
+
<Table>
|
|
79
|
+
<TableHead>
|
|
80
|
+
<TableHeadRow>
|
|
81
|
+
<TableHeadCell>Name</TableHeadCell>
|
|
82
|
+
<TableHeadCell>Email</TableHeadCell>
|
|
83
|
+
<TableHeadCell>Status</TableHeadCell>
|
|
84
|
+
</TableHeadRow>
|
|
85
|
+
</TableHead>
|
|
86
|
+
<TableBody>
|
|
87
|
+
{MOCK_DATA.map((item) => (
|
|
88
|
+
<TableRow key={item._id}>
|
|
89
|
+
<TableCell>{item.name}</TableCell>
|
|
90
|
+
<TableCell>{item.email}</TableCell>
|
|
91
|
+
<TableCell>{item.status}</TableCell>
|
|
92
|
+
</TableRow>
|
|
93
|
+
))}
|
|
94
|
+
</TableBody>
|
|
95
|
+
</Table>
|
|
96
|
+
</HorizontallyScrollableTableWrapper>
|
|
97
|
+
),
|
|
98
|
+
play: async ({ canvasElement }) => {
|
|
99
|
+
const canvas = within(canvasElement);
|
|
100
|
+
|
|
101
|
+
await expect(canvas.getByTestId(tableTestIds.WRAPPER)).toBeInTheDocument();
|
|
102
|
+
await expect(canvas.getByTestId(tableTestIds.TABLE)).toBeInTheDocument();
|
|
103
|
+
await expect(canvas.getAllByTestId(tableTestIds.ROW).length).toBe(MOCK_DATA.length);
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/** Empty state with TableEmptyRow. */
|
|
108
|
+
export const Empty: Story = {
|
|
109
|
+
render: () => (
|
|
110
|
+
<HorizontallyScrollableTableWrapper>
|
|
111
|
+
<Table>
|
|
112
|
+
<TableHead>
|
|
113
|
+
<TableHeadRow>
|
|
114
|
+
<TableHeadCell>Name</TableHeadCell>
|
|
115
|
+
<TableHeadCell>Email</TableHeadCell>
|
|
116
|
+
<TableHeadCell>Status</TableHeadCell>
|
|
117
|
+
</TableHeadRow>
|
|
118
|
+
</TableHead>
|
|
119
|
+
<TableBody>
|
|
120
|
+
<TableEmptyRow colSpan={3}>No data available</TableEmptyRow>
|
|
121
|
+
</TableBody>
|
|
122
|
+
</Table>
|
|
123
|
+
</HorizontallyScrollableTableWrapper>
|
|
124
|
+
),
|
|
125
|
+
play: async ({ canvasElement }) => {
|
|
126
|
+
const canvas = within(canvasElement);
|
|
127
|
+
|
|
128
|
+
await expect(canvas.getByTestId(tableTestIds.EMPTY_ROW)).toBeInTheDocument();
|
|
129
|
+
await expect(canvas.queryAllByTestId(tableTestIds.ROW).length).toBe(0);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/** Loading state with TableLoadingRow. */
|
|
134
|
+
export const Loading: Story = {
|
|
135
|
+
render: () => (
|
|
136
|
+
<HorizontallyScrollableTableWrapper>
|
|
137
|
+
<Table>
|
|
138
|
+
<TableHead>
|
|
139
|
+
<TableHeadRow>
|
|
140
|
+
<TableHeadCell>Name</TableHeadCell>
|
|
141
|
+
<TableHeadCell>Email</TableHeadCell>
|
|
142
|
+
<TableHeadCell>Status</TableHeadCell>
|
|
143
|
+
</TableHeadRow>
|
|
144
|
+
</TableHead>
|
|
145
|
+
<TableBody>
|
|
146
|
+
<TableLoadingRow colSpan={3} />
|
|
147
|
+
</TableBody>
|
|
148
|
+
</Table>
|
|
149
|
+
</HorizontallyScrollableTableWrapper>
|
|
150
|
+
),
|
|
151
|
+
play: async ({ canvasElement }) => {
|
|
152
|
+
const canvas = within(canvasElement);
|
|
153
|
+
|
|
154
|
+
await expect(canvas.getByTestId(tableTestIds.LOADING_ROW)).toBeInTheDocument();
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Error state with TableErrorRow. */
|
|
159
|
+
export const WithError: Story = {
|
|
160
|
+
render: () => (
|
|
161
|
+
<HorizontallyScrollableTableWrapper>
|
|
162
|
+
<Table>
|
|
163
|
+
<TableHead>
|
|
164
|
+
<TableHeadRow>
|
|
165
|
+
<TableHeadCell>Name</TableHeadCell>
|
|
166
|
+
<TableHeadCell>Email</TableHeadCell>
|
|
167
|
+
<TableHeadCell>Status</TableHeadCell>
|
|
168
|
+
</TableHeadRow>
|
|
169
|
+
</TableHead>
|
|
170
|
+
<TableBody>
|
|
171
|
+
<TableErrorRow colSpan={3} error={new globalThis.Error('Connection timed out')} />
|
|
172
|
+
</TableBody>
|
|
173
|
+
</Table>
|
|
174
|
+
</HorizontallyScrollableTableWrapper>
|
|
175
|
+
),
|
|
176
|
+
play: async ({ canvasElement }) => {
|
|
177
|
+
const canvas = within(canvasElement);
|
|
178
|
+
|
|
179
|
+
await expect(canvas.getByTestId(tableTestIds.ERROR_ROW)).toBeInTheDocument();
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/** Nested links — row-level link via `to` prop + inner TableCellLink. */
|
|
184
|
+
export const WithNestedLinks: Story = {
|
|
185
|
+
render: () => (
|
|
186
|
+
<HorizontallyScrollableTableWrapper>
|
|
187
|
+
<Table>
|
|
188
|
+
<TableHead>
|
|
189
|
+
<TableHeadRow>
|
|
190
|
+
<TableHeadCell>Name</TableHeadCell>
|
|
191
|
+
<TableHeadCell>Email</TableHeadCell>
|
|
192
|
+
<TableHeadCell>Status</TableHeadCell>
|
|
193
|
+
</TableHeadRow>
|
|
194
|
+
</TableHead>
|
|
195
|
+
<TableBody>
|
|
196
|
+
{MOCK_DATA.map((item) => (
|
|
197
|
+
<TableRow key={item._id} to={`/items/${item._id}`}>
|
|
198
|
+
<TableCell>
|
|
199
|
+
<TableCellLink to={`/actors/${item._id}`}>{item.name}</TableCellLink>
|
|
200
|
+
</TableCell>
|
|
201
|
+
<TableCell>{item.email}</TableCell>
|
|
202
|
+
<TableCell>{item.status}</TableCell>
|
|
203
|
+
</TableRow>
|
|
204
|
+
))}
|
|
205
|
+
</TableBody>
|
|
206
|
+
</Table>
|
|
207
|
+
</HorizontallyScrollableTableWrapper>
|
|
208
|
+
),
|
|
209
|
+
play: async ({ canvasElement }) => {
|
|
210
|
+
const canvas = within(canvasElement);
|
|
211
|
+
|
|
212
|
+
await expect(canvas.getAllByTestId(tableTestIds.ROW).length).toBe(MOCK_DATA.length);
|
|
213
|
+
|
|
214
|
+
// Each cell in a row with `to` should have an overlay link + first cell has inner link
|
|
215
|
+
const cells = canvas.getAllByTestId(tableTestIds.CELL);
|
|
216
|
+
const firstCellLinks = cells[0].querySelectorAll('a');
|
|
217
|
+
await expect(firstCellLinks.length).toBe(2);
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/** Direct inline data — no hooks, no data fetching. */
|
|
222
|
+
export const DirectData: Story = {
|
|
223
|
+
render: () => {
|
|
224
|
+
const items = [
|
|
225
|
+
{ _id: '1', key: 'API_TOKEN', value: '••••••••', updatedAt: '2025-04-01' },
|
|
226
|
+
{ _id: '2', key: 'BASE_URL', value: 'https://api.example.com', updatedAt: '2025-03-15' },
|
|
227
|
+
{ _id: '3', key: 'TIMEOUT_MS', value: '30000', updatedAt: '2025-02-20' },
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<HorizontallyScrollableTableWrapper>
|
|
232
|
+
<Table>
|
|
233
|
+
<TableHead>
|
|
234
|
+
<TableHeadRow>
|
|
235
|
+
<TableHeadCell>Key</TableHeadCell>
|
|
236
|
+
<TableHeadCell>Value</TableHeadCell>
|
|
237
|
+
<TableHeadCell>Updated</TableHeadCell>
|
|
238
|
+
</TableHeadRow>
|
|
239
|
+
</TableHead>
|
|
240
|
+
<TableBody>
|
|
241
|
+
{items.map((item) => (
|
|
242
|
+
<TableRow key={item._id}>
|
|
243
|
+
<TableCell><Text weight="bold">{item.key}</Text></TableCell>
|
|
244
|
+
<TableCell>{item.value}</TableCell>
|
|
245
|
+
<TableCell>{item.updatedAt}</TableCell>
|
|
246
|
+
</TableRow>
|
|
247
|
+
))}
|
|
248
|
+
</TableBody>
|
|
249
|
+
</Table>
|
|
250
|
+
</HorizontallyScrollableTableWrapper>
|
|
251
|
+
);
|
|
252
|
+
},
|
|
253
|
+
play: async ({ canvasElement }) => {
|
|
254
|
+
const canvas = within(canvasElement);
|
|
255
|
+
|
|
256
|
+
await expect(canvas.getAllByTestId(tableTestIds.ROW).length).toBe(3);
|
|
257
|
+
},
|
|
258
|
+
};
|