@bundle-stats/ui 4.22.2-beta.1 → 4.22.3

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 (89) hide show
  1. package/.babelrc.js +65 -24
  2. package/globals.d.ts +13 -0
  3. package/lib/components/bundle-modules/index.js.map +1 -1
  4. package/lib/components/index.js.map +1 -1
  5. package/lib/components/metrics-table-header/metrics-table-header.js +2 -2
  6. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
  7. package/lib/css/default.css +1 -1
  8. package/lib/hooks/rows-sort.js +13 -12
  9. package/lib/hooks/rows-sort.js.map +1 -1
  10. package/lib/ui/button/button.js.map +1 -1
  11. package/lib/ui/empty-set/empty-set.js +3 -3
  12. package/lib/ui/empty-set/empty-set.js.map +1 -1
  13. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  14. package/lib-esm/components/index.js.map +1 -1
  15. package/lib-esm/components/metrics-table-header/metrics-table-header.js +2 -2
  16. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
  17. package/lib-esm/css/default.css +1 -1
  18. package/lib-esm/hooks/rows-sort.js +10 -8
  19. package/lib-esm/hooks/rows-sort.js.map +1 -1
  20. package/lib-esm/ui/button/button.js.map +1 -1
  21. package/lib-esm/ui/empty-set/empty-set.js +3 -3
  22. package/lib-esm/ui/empty-set/empty-set.js.map +1 -1
  23. package/package.json +26 -15
  24. package/src/app/app.stories.tsx +2 -2
  25. package/src/components/asset-info/asset-info.stories.tsx +47 -39
  26. package/src/components/asset-name/asset-name.stories.tsx +1 -3
  27. package/src/components/asset-not-predictive/asset-not-predictive.stories.tsx +22 -15
  28. package/src/components/browsertime-table/browsertime-table.stories.tsx +45 -0
  29. package/src/components/bundle-assets-totals/bundle-assets-totals.stories.tsx +47 -0
  30. package/src/components/bundle-modules/bundle-modules.stories.tsx +191 -0
  31. package/src/components/bundle-modules/bundle-modules.tsx +1 -1
  32. package/src/components/bundle-modules/index.tsx +4 -0
  33. package/src/components/bundle-packages/bundle-packages.stories.tsx +87 -0
  34. package/src/components/delta/delta.stories.tsx +57 -0
  35. package/src/components/entry-info/entry-info.stories.tsx +49 -54
  36. package/src/components/{index.js → index.ts} +4 -2
  37. package/src/components/insights/insights.stories.tsx +36 -33
  38. package/src/components/job-name/job-name.stories.tsx +46 -0
  39. package/src/components/jobs-header/jobs-header.stories.tsx +19 -15
  40. package/src/components/lighthouse-table/lighthouse-table.stories.tsx +30 -0
  41. package/src/components/metric/metric.stories.tsx +24 -22
  42. package/src/components/metric-run-info/metric-run-info.stories.tsx +45 -41
  43. package/src/components/metrics-table/metrics-table.stories.tsx +33 -13
  44. package/src/components/metrics-table/metrics-table.tsx +1 -1
  45. package/src/components/metrics-table-header/metrics-table-header.tsx +9 -4
  46. package/src/components/module-info/module-info.stories.tsx +41 -30
  47. package/src/components/package-info/package-info.stories.tsx +20 -15
  48. package/src/components/run-info/run-info.stories.tsx +39 -37
  49. package/src/components/summary/summary.stories.tsx +26 -32
  50. package/src/css/default.css +1 -1
  51. package/src/hooks/rows-sort.ts +9 -6
  52. package/src/layout/box/box.stories.tsx +35 -28
  53. package/src/layout/flex-stack/flex-stack.stories.tsx +79 -48
  54. package/src/layout/footer/footer.stories.tsx +30 -0
  55. package/src/layout/stack/stack.stories.tsx +68 -44
  56. package/src/ui/alert/alert.stories.tsx +25 -21
  57. package/src/ui/button/button.stories.tsx +181 -176
  58. package/src/ui/button/button.tsx +8 -1
  59. package/src/ui/container/container.stories.tsx +28 -21
  60. package/src/ui/control-group/control-group.stories.tsx +23 -16
  61. package/src/ui/dropdown/dropdown.stories.tsx +23 -15
  62. package/src/ui/empty-set/empty-set.jsx +16 -4
  63. package/src/ui/empty-set/empty-set.stories.tsx +41 -0
  64. package/src/ui/file-name/file-name.stories.tsx +45 -0
  65. package/src/ui/filters/filters.stories.tsx +29 -26
  66. package/src/ui/hover-card/hover-card.stories.tsx +35 -26
  67. package/src/ui/icon/icon.stories.tsx +36 -28
  68. package/src/ui/input/input.stories.tsx +17 -5
  69. package/src/ui/input-search/input-search.stories.tsx +31 -0
  70. package/src/ui/loader/loader.stories.tsx +22 -0
  71. package/src/ui/skeleton/skeleton.stories.tsx +42 -0
  72. package/src/ui/table/table.stories.tsx +244 -218
  73. package/src/ui/tag/tag.stories.tsx +11 -10
  74. package/src/ui/toolbar/toolbar.stories.tsx +41 -0
  75. package/types/components/bundle-modules/bundle-modules.d.ts +1 -1
  76. package/types/components/bundle-modules/index.d.ts +2 -1
  77. package/types/components/index.d.ts +22 -20
  78. package/types/components/metrics-table/metrics-table.d.ts +1 -1
  79. package/types/components/metrics-table-header/metrics-table-header.d.ts +1 -1
  80. package/types/hooks/rows-sort.d.ts +2 -2
  81. package/types/ui/button/button.d.ts +1 -1
  82. package/vitest.config.ts +47 -0
  83. package/vitest.setup.ts +26 -0
  84. package/lib/assets/icons.svg.js +0 -100
  85. package/lib/assets/icons.svg.js.map +0 -1
  86. package/lib-esm/assets/icons.svg.js +0 -63
  87. package/lib-esm/assets/icons.svg.js.map +0 -1
  88. package/src/assets/icons.svg.jsx +0 -279
  89. package/types/assets/icons.svg.d.ts +0 -2
@@ -1,24 +1,31 @@
1
1
  import React from 'react';
2
- import { Meta } from '@storybook/react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
3
 
4
4
  import { Button } from '../button';
5
5
  import { ControlGroup } from '.';
6
6
 
7
- export default {
7
+ const meta = {
8
8
  title: 'UI/ControlGroup',
9
9
  component: ControlGroup,
10
- } as Meta;
10
+ args: {
11
+ children: (
12
+ <>
13
+ <Button outline type="button">
14
+ Option A
15
+ </Button>
16
+ <Button outline type="button">
17
+ Option B
18
+ </Button>
19
+ <Button outline type="button">
20
+ Option C
21
+ </Button>
22
+ </>
23
+ ),
24
+ },
25
+ } satisfies Meta<typeof ControlGroup>;
11
26
 
12
- export const Default = () => (
13
- <ControlGroup>
14
- <Button outline type="button">
15
- Option A
16
- </Button>
17
- <Button outline type="button">
18
- Option B
19
- </Button>
20
- <Button outline type="button">
21
- Option C
22
- </Button>
23
- </ControlGroup>
24
- );
27
+ export default meta;
28
+
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ export const Default: Story = {};
@@ -1,25 +1,33 @@
1
1
  import React from 'react';
2
- import { Meta } from '@storybook/react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
3
 
4
4
  import { getWrapperDecorator } from '../../stories';
5
5
  import { Dropdown, DropdownItem } from '.';
6
6
 
7
- export default {
7
+ const meta = {
8
8
  title: 'UI/Dropdown',
9
9
  component: Dropdown,
10
10
  decorators: [getWrapperDecorator()],
11
- } as Meta;
11
+ args: {
12
+ glyph: 'filter',
13
+ label: 'Toggle',
14
+ children: (
15
+ <>
16
+ <DropdownItem>Option 1</DropdownItem>
17
+ <DropdownItem>Option 2</DropdownItem>
18
+ </>
19
+ ),
20
+ },
21
+ } satisfies Meta<typeof Dropdown>;
12
22
 
13
- export const Defualt = () => (
14
- <Dropdown glyph="filter" label="Toggle">
15
- <DropdownItem>Option 1</DropdownItem>
16
- <DropdownItem>Option 2</DropdownItem>
17
- </Dropdown>
18
- );
23
+ export default meta;
19
24
 
20
- export const Disabled = () => (
21
- <Dropdown glyph="filter" label="Toggle" disabled>
22
- <DropdownItem>Option 1</DropdownItem>
23
- <DropdownItem>Option 2</DropdownItem>
24
- </Dropdown>
25
- );
25
+ type Story = StoryObj<typeof meta>;
26
+
27
+ export const Default: Story = {};
28
+
29
+ export const Disabled: Story = {
30
+ args: {
31
+ disabled: true,
32
+ },
33
+ };
@@ -13,14 +13,26 @@ export const EmptySet = (props) => {
13
13
  const actions = [
14
14
  ...(handleResetFilters
15
15
  ? [
16
- <Button kind="primary" type="button" onClick={handleResetFilters} className={css.action}>
16
+ <Button
17
+ key="reset-filters"
18
+ kind="primary"
19
+ type="button"
20
+ onClick={handleResetFilters}
21
+ className={css.action}
22
+ >
17
23
  {I18N.RESET_FILTERS}
18
24
  </Button>,
19
25
  ]
20
26
  : []),
21
27
  ...(handleViewAll
22
28
  ? [
23
- <Button kind="primary" type="button" onClick={handleViewAll} className={css.action}>
29
+ <Button
30
+ key="view-all"
31
+ kind="primary"
32
+ type="button"
33
+ onClick={handleViewAll}
34
+ className={css.action}
35
+ >
24
36
  {I18N.VIEW_ALL}
25
37
  </Button>,
26
38
  ]
@@ -32,10 +44,10 @@ export const EmptySet = (props) => {
32
44
  <p>{message}</p>
33
45
  {filtered &&
34
46
  actions.map((action, index) => (
35
- <>
47
+ <React.Fragment key={action.key}>
36
48
  {index > 0 && ' or '}
37
49
  {action}
38
- </>
50
+ </React.Fragment>
39
51
  ))}
40
52
  </Stack>
41
53
  );
@@ -0,0 +1,41 @@
1
+ import type React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { getWrapperDecorator } from '../../stories';
5
+ import { EmptySet } from '.';
6
+
7
+ // EmptySet is a plain .jsx component with defaultProps instead of inline
8
+ // destructuring defaults, so TS can't infer its props as optional on its own.
9
+ const TypedEmptySet = EmptySet as unknown as React.ComponentType<{
10
+ resources: string;
11
+ filtered: boolean;
12
+ handleResetFilters?: () => void;
13
+ handleViewAll?: () => void;
14
+ }>;
15
+
16
+ const meta = {
17
+ title: 'UI/EmptySet',
18
+ component: TypedEmptySet,
19
+ decorators: [getWrapperDecorator()],
20
+ args: {
21
+ resources: 'assets',
22
+ },
23
+ } satisfies Meta<typeof TypedEmptySet>;
24
+
25
+ export default meta;
26
+
27
+ type Story = StoryObj<typeof meta>;
28
+
29
+ export const Default: Story = {
30
+ args: {
31
+ filtered: true,
32
+ handleResetFilters: () => console.log('RESET_FILTERS'),
33
+ handleViewAll: () => console.log('VIEW_ALL'),
34
+ },
35
+ };
36
+
37
+ export const Empty: Story = {
38
+ args: {
39
+ filtered: false,
40
+ },
41
+ };
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { getWrapperDecorator } from '../../stories';
5
+ import { FileName } from './file-name';
6
+
7
+ // FileName is a plain .jsx component with defaultProps instead of inline
8
+ // destructuring defaults, so TS can't infer its props as optional on its own.
9
+ const TypedFileName = FileName as unknown as React.ComponentType<{
10
+ className?: string;
11
+ as?: React.ElementType;
12
+ name?: React.ReactNode;
13
+ }>;
14
+
15
+ const meta = {
16
+ title: 'Ui/FileName',
17
+ component: TypedFileName,
18
+ decorators: [getWrapperDecorator()],
19
+ } satisfies Meta<typeof TypedFileName>;
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof meta>;
24
+
25
+ const NAMES = [
26
+ 'styles.css',
27
+ './src/components/sources/styles.css',
28
+ 'css ./node_modules/css-loader/dist/cjs.js??ref--6-1!./node_modules/postcss-loader/src!./src/components/sources/source/styles.css',
29
+ 'rreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordeallylongwordrreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordeallylongwordrreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordreallylongwordeallylongword',
30
+ ];
31
+
32
+ export const Default: Story = {
33
+ render: () => (
34
+ <div>
35
+ {NAMES.map((name) => (
36
+ <div
37
+ key={name}
38
+ style={{ padding: '12px', outline: '1px dotted lightpink', margin: '12px' }}
39
+ >
40
+ <TypedFileName name={name} />
41
+ </div>
42
+ ))}
43
+ </div>
44
+ ),
45
+ };
@@ -1,20 +1,25 @@
1
- import React from 'react';
2
- import { Meta } from '@storybook/react';
3
- import { action } from 'storybook/actions'; // eslint-disable-line
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { action } from 'storybook/actions';
4
3
 
5
4
  import { getWrapperDecorator } from '../../stories';
6
5
  import { Filters } from '.';
7
6
 
8
- export default {
7
+ const meta = {
9
8
  title: 'UI/Filters',
10
9
  component: Filters,
11
10
  decorators: [getWrapperDecorator({ paddingLeft: '200px' })],
12
- } as Meta;
11
+ args: {
12
+ onChange: action('CHANGE'),
13
+ },
14
+ } satisfies Meta<typeof Filters>;
13
15
 
14
- export const Default = () => (
15
- <Filters
16
- onChange={action('CHANGE')}
17
- filters={{
16
+ export default meta;
17
+
18
+ type Story = StoryObj<typeof meta>;
19
+
20
+ export const Default: Story = {
21
+ args: {
22
+ filters: {
18
23
  changed: {
19
24
  label: 'Changed',
20
25
  defaultValue: true,
@@ -44,14 +49,13 @@ export const Default = () => (
44
49
  },
45
50
  ],
46
51
  },
47
- }}
48
- />
49
- );
52
+ },
53
+ },
54
+ };
50
55
 
51
- export const Overflow = () => (
52
- <Filters
53
- onChange={action('CHANGE')}
54
- filters={{
56
+ export const Overflow: Story = {
57
+ args: {
58
+ filters: {
55
59
  changed: {
56
60
  label: 'Changed',
57
61
  defaultValue: true,
@@ -66,14 +70,13 @@ export const Overflow = () => (
66
70
  defaultValue: true,
67
71
  })),
68
72
  },
69
- }}
70
- />
71
- );
73
+ },
74
+ },
75
+ };
72
76
 
73
- export const DisableOptions = () => (
74
- <Filters
75
- onChange={action('CHANGE')}
76
- filters={{
77
+ export const DisableOptions: Story = {
78
+ args: {
79
+ filters: {
77
80
  changed: {
78
81
  label: 'Changed',
79
82
  defaultValue: false,
@@ -104,6 +107,6 @@ export const DisableOptions = () => (
104
107
  },
105
108
  ],
106
109
  },
107
- }}
108
- />
109
- );
110
+ },
111
+ },
112
+ };
@@ -1,34 +1,43 @@
1
1
  import React from 'react';
2
- import { Meta, Story } from '@storybook/react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
3
 
4
- import { HoverCard, HoverCardProps } from '.';
4
+ import { HoverCard } from '.';
5
5
 
6
- export default {
6
+ const meta = {
7
7
  title: 'UI/HoverCard',
8
8
  component: HoverCard,
9
- } as Meta;
9
+ render: (args) => (
10
+ <>
11
+ <HoverCard {...args} />
12
+ <p style={{ position: 'relative', zIndex: 1, maxWidth: 360 }}>
13
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in neque ante. Curabitur
14
+ vehicula, lorem sit amet fringilla dapibus, justo mauris varius elit, ut fermentum leo velit
15
+ eget risus
16
+ </p>
17
+ </>
18
+ ),
19
+ } satisfies Meta<typeof HoverCard>;
10
20
 
11
- const Template: Story<HoverCardProps> = (props) => (
12
- <>
13
- <HoverCard {...props} />
14
- <p style={{ position: 'relative', zIndex: 1, maxWidth: 360 }}>
15
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in neque ante. Curabitur
16
- vehicula, lorem sit amet fringilla dapibus, justo mauris varius elit, ut fermentum leo velit
17
- eget risus
18
- </p>
19
- </>
20
- );
21
+ export default meta;
21
22
 
22
- export const Default = () => (
23
- <Template label="main.js">
24
- <h1>main.js</h1>
25
- <p>info</p>
26
- </Template>
27
- );
23
+ type Story = StoryObj<typeof meta>;
28
24
 
29
- export const WithRenderFn = () => (
30
- <Template label="main.js">
31
- {({ close }) => (
25
+ export const Default: Story = {
26
+ args: {
27
+ label: 'main.js',
28
+ children: (
29
+ <>
30
+ <h1>main.js</h1>
31
+ <p>info</p>
32
+ </>
33
+ ),
34
+ },
35
+ };
36
+
37
+ export const WithRenderFn: Story = {
38
+ args: {
39
+ label: 'main.js',
40
+ children: ({ close }) => (
32
41
  <div>
33
42
  <h1>main.js</h1>
34
43
  <p>info</p>
@@ -36,6 +45,6 @@ export const WithRenderFn = () => (
36
45
  close
37
46
  </button>
38
47
  </div>
39
- )}
40
- </Template>
41
- );
48
+ ),
49
+ },
50
+ };
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import { Meta, Story } from '@storybook/react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
3
 
4
4
  import { Icon } from '.';
5
5
 
6
- export default {
6
+ const meta = {
7
7
  title: 'UI/Icon',
8
8
  component: Icon,
9
9
  args: {
@@ -19,36 +19,44 @@ export default {
19
19
  control: { type: 'select' },
20
20
  },
21
21
  },
22
- } as Meta;
22
+ } satisfies Meta<typeof Icon>;
23
23
 
24
- const Template: Story = (args: any) => <Icon {...args} />;
24
+ export default meta;
25
25
 
26
- export const Standard = Template.bind({});
26
+ type Story = StoryObj<typeof meta>;
27
27
 
28
- Standard.args = {
29
- glyph: Icon.ICONS.ARROW,
28
+ export const Standard: Story = {
29
+ args: {
30
+ glyph: Icon.ICONS.ARROW,
31
+ },
30
32
  };
31
33
 
32
- export const CustomSize = Template.bind({});
33
-
34
- CustomSize.args = {
35
- glyph: Icon.ICONS.ARROW,
36
- size: Icon.SIZE_LARGE,
34
+ export const CustomSize: Story = {
35
+ args: {
36
+ glyph: Icon.ICONS.ARROW,
37
+ size: Icon.SIZE_LARGE,
38
+ },
37
39
  };
38
40
 
39
- export const All = ({ size }: Pick<React.ComponentProps<typeof Icon>, 'size'>) => (
40
- <>
41
- {Object.values(Icon.ICONS).map((glyph) => (
42
- <div
43
- style={{
44
- display: 'inline-block',
45
- padding: '1rem',
46
- textAlign: 'center',
47
- }}
48
- >
49
- <Icon glyph={glyph} size={size} key={glyph} />
50
- <code style={{ display: 'block' }}>{glyph}</code>
51
- </div>
52
- ))}
53
- </>
54
- );
41
+ export const All: Story = {
42
+ args: {
43
+ glyph: Icon.ICONS.ARROW,
44
+ },
45
+ render: ({ size }) => (
46
+ <>
47
+ {Object.values(Icon.ICONS).map((glyph) => (
48
+ <div
49
+ key={glyph}
50
+ style={{
51
+ display: 'inline-block',
52
+ padding: '1rem',
53
+ textAlign: 'center',
54
+ }}
55
+ >
56
+ <Icon glyph={glyph} size={size} />
57
+ <code style={{ display: 'block' }}>{glyph}</code>
58
+ </div>
59
+ ))}
60
+ </>
61
+ ),
62
+ };
@@ -1,13 +1,25 @@
1
- import React from 'react';
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { getWrapperDecorator } from '../../stories';
4
4
  import { Input } from '.';
5
5
 
6
- export default {
6
+ const meta = {
7
7
  title: 'UI/Input',
8
8
  component: Input,
9
9
  decorators: [getWrapperDecorator()],
10
- };
10
+ args: {
11
+ placeholder: 'Search',
12
+ },
13
+ } satisfies Meta<typeof Input>;
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof meta>;
11
18
 
12
- export const Default = () => <Input placeholder="Search" />;
13
- export const WithSize = () => <Input placeholder="Search" size="small" />;
19
+ export const Default: Story = {};
20
+
21
+ export const WithSize: Story = {
22
+ args: {
23
+ size: 'small',
24
+ },
25
+ };
@@ -0,0 +1,31 @@
1
+ import React, { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { getWrapperDecorator } from '../../stories';
5
+ import { InputSearch } from '.';
6
+
7
+ const meta = {
8
+ title: 'UI/InputSearch',
9
+ component: InputSearch,
10
+ decorators: [getWrapperDecorator()],
11
+ } satisfies Meta<typeof InputSearch>;
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ const InputSearchWithState = () => {
18
+ const [search, updateSearch] = useState('');
19
+
20
+ return (
21
+ <div>
22
+ <pre>{JSON.stringify({ search }, null, 2)}</pre>
23
+ <br />
24
+ <InputSearch placeholder="Search by name" defaultValue={search} onChange={updateSearch} />
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export const Default: Story = {
30
+ render: () => <InputSearchWithState />,
31
+ };
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { getWrapperDecorator } from '../../stories';
4
+ import { Loader } from '.';
5
+
6
+ const meta = {
7
+ title: 'UI/Loader',
8
+ component: Loader,
9
+ decorators: [getWrapperDecorator()],
10
+ } satisfies Meta<typeof Loader>;
11
+
12
+ export default meta;
13
+
14
+ type Story = StoryObj<typeof meta>;
15
+
16
+ export const Default: Story = {};
17
+
18
+ export const WithSize: Story = {
19
+ args: {
20
+ size: Loader.SIZE_LARGE,
21
+ },
22
+ };
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { Skeleton } from '.';
5
+
6
+ // Skeleton is a plain .jsx component with defaultProps instead of inline
7
+ // destructuring defaults, so TS can't infer its props as optional on its own.
8
+ const TypedSkeleton = Skeleton as unknown as React.ComponentType<
9
+ {
10
+ className?: string;
11
+ as?: React.ElementType;
12
+ block?: boolean;
13
+ } & React.HTMLAttributes<HTMLElement>
14
+ >;
15
+
16
+ const meta = {
17
+ title: 'UI/Skeleton',
18
+ component: TypedSkeleton,
19
+ } satisfies Meta<typeof TypedSkeleton>;
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof meta>;
24
+
25
+ export const MultipleTextLines: Story = {
26
+ render: () => (
27
+ <>
28
+ <TypedSkeleton as="h1" style={{ outline: '1px solid magenta' }} />
29
+ <TypedSkeleton as="h2" style={{ outline: '1px solid magenta' }} />
30
+ <TypedSkeleton as="p" style={{ outline: '1px solid magenta' }} />
31
+ <TypedSkeleton style={{ outline: '1px solid pink' }} />
32
+ </>
33
+ ),
34
+ };
35
+
36
+ export const Block: Story = {
37
+ render: () => (
38
+ <div style={{ outline: '1px solid magenta' }}>
39
+ <TypedSkeleton as="div" block />
40
+ </div>
41
+ ),
42
+ };