@shipfox/react-ui 0.16.0 → 0.17.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 (32) hide show
  1. package/dist/components/card/card.d.ts +24 -0
  2. package/dist/components/card/card.js +56 -0
  3. package/dist/components/card/card.stories.js +216 -0
  4. package/dist/components/card/index.d.ts +2 -0
  5. package/dist/components/card/index.js +3 -0
  6. package/dist/components/dashboard/components/charts/bar-chart.d.ts +8 -17
  7. package/dist/components/dashboard/components/charts/bar-chart.js +127 -81
  8. package/dist/components/dashboard/components/charts/bar-chart.stories.js +287 -0
  9. package/dist/components/dashboard/components/charts/chart-tooltip.js +13 -12
  10. package/dist/components/dashboard/components/charts/colors.d.ts +3 -2
  11. package/dist/components/dashboard/components/charts/colors.js +5 -2
  12. package/dist/components/dashboard/components/charts/index.d.ts +1 -0
  13. package/dist/components/dashboard/components/charts/index.js +1 -0
  14. package/dist/components/dashboard/components/charts/line-chart.d.ts +7 -16
  15. package/dist/components/dashboard/components/charts/line-chart.js +132 -108
  16. package/dist/components/dashboard/components/charts/line-chart.stories.js +257 -0
  17. package/dist/components/dashboard/components/charts/utils.d.ts +13 -0
  18. package/dist/components/dashboard/components/charts/utils.js +18 -0
  19. package/dist/components/dashboard/index.d.ts +1 -1
  20. package/dist/components/empty-state/empty-state.d.ts +10 -0
  21. package/dist/components/empty-state/empty-state.js +40 -0
  22. package/dist/components/empty-state/empty-state.stories.js +74 -0
  23. package/dist/components/empty-state/index.d.ts +2 -0
  24. package/dist/components/empty-state/index.js +3 -0
  25. package/dist/components/index.d.ts +3 -0
  26. package/dist/components/index.js +3 -0
  27. package/dist/components/table/data-table.d.ts +5 -1
  28. package/dist/components/table/data-table.js +83 -71
  29. package/dist/components/table/table.js +1 -1
  30. package/dist/components/table/table.stories.components.js +6 -28
  31. package/dist/styles.css +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { EmptyState } from './empty-state.js';
3
+ const meta = {
4
+ title: 'Components/EmptyState',
5
+ component: EmptyState,
6
+ tags: [
7
+ 'autodocs'
8
+ ],
9
+ parameters: {
10
+ layout: 'centered'
11
+ }
12
+ };
13
+ export default meta;
14
+ export const Default = {
15
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
16
+ className: "w-400",
17
+ children: /*#__PURE__*/ _jsx(EmptyState, {
18
+ ...args
19
+ })
20
+ }),
21
+ args: {}
22
+ };
23
+ export const CustomContent = {
24
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
25
+ className: "w-400",
26
+ children: /*#__PURE__*/ _jsx(EmptyState, {
27
+ ...args
28
+ })
29
+ }),
30
+ args: {
31
+ icon: 'shipfox',
32
+ title: 'No jobs yet',
33
+ description: 'Import past runs or start a runner.'
34
+ }
35
+ };
36
+ export const Compact = {
37
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
38
+ className: "w-400 h-200 relative",
39
+ children: /*#__PURE__*/ _jsx(EmptyState, {
40
+ ...args
41
+ })
42
+ }),
43
+ args: {
44
+ icon: 'lineChartLine',
45
+ title: 'Nothing here yet.',
46
+ variant: 'compact'
47
+ }
48
+ };
49
+ export const NoDescription = {
50
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
51
+ className: "w-400",
52
+ children: /*#__PURE__*/ _jsx(EmptyState, {
53
+ ...args
54
+ })
55
+ }),
56
+ args: {
57
+ title: 'No data available',
58
+ description: undefined
59
+ }
60
+ };
61
+ export const NoTitle = {
62
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
63
+ className: "w-400",
64
+ children: /*#__PURE__*/ _jsx(EmptyState, {
65
+ ...args
66
+ })
67
+ }),
68
+ args: {
69
+ title: undefined,
70
+ description: 'This is a description without a title.'
71
+ }
72
+ };
73
+
74
+ //# sourceMappingURL=empty-state.stories.js.map
@@ -0,0 +1,2 @@
1
+ export * from './empty-state';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from './empty-state.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -4,15 +4,18 @@ export * from './badge';
4
4
  export * from './button';
5
5
  export * from './button-group';
6
6
  export * from './calendar';
7
+ export * from './card';
7
8
  export * from './checkbox';
8
9
  export * from './code-block';
9
10
  export * from './command';
10
11
  export * from './confetti';
12
+ export * from './dashboard';
11
13
  export * from './date-picker';
12
14
  export * from './date-time-range-picker';
13
15
  export * from './dot-grid';
14
16
  export * from './dropdown-menu';
15
17
  export * from './dynamic-item';
18
+ export * from './empty-state';
16
19
  export * from './form';
17
20
  export * from './icon';
18
21
  export * from './inline-tips';
@@ -4,15 +4,18 @@ export * from './badge/index.js';
4
4
  export * from './button/index.js';
5
5
  export * from './button-group/index.js';
6
6
  export * from './calendar/index.js';
7
+ export * from './card/index.js';
7
8
  export * from './checkbox/index.js';
8
9
  export * from './code-block/index.js';
9
10
  export * from './command/index.js';
10
11
  export * from './confetti/index.js';
12
+ export * from './dashboard/index.js';
11
13
  export * from './date-picker/index.js';
12
14
  export * from './date-time-range-picker/index.js';
13
15
  export * from './dot-grid/index.js';
14
16
  export * from './dropdown-menu/index.js';
15
17
  export * from './dynamic-item/index.js';
18
+ export * from './empty-state/index.js';
16
19
  export * from './form/index.js';
17
20
  export * from './icon/index.js';
18
21
  export * from './inline-tips/index.js';
@@ -77,7 +77,11 @@ interface DataTableProps<TData, TValue> extends Omit<ComponentProps<'div'>, 'chi
77
77
  * This is only used when {@link columnVisibility} is provided as a controlled prop.
78
78
  */
79
79
  onColumnVisibilityChange?: (visibility: VisibilityState) => void;
80
+ /**
81
+ * When `true`, displays a loading skeleton instead of the table.
82
+ */
83
+ isLoading?: boolean;
80
84
  }
81
- export declare function DataTable<TData, TValue>({ columns, data, pagination, pageSize, pageSizeOptions, showSelectedCount, onRowClick, emptyState, columnVisibility: controlledColumnVisibility, onColumnVisibilityChange, className, ...props }: DataTableProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
85
+ export declare function DataTable<TData, TValue>({ columns, data, pagination, pageSize, pageSizeOptions, showSelectedCount, onRowClick, emptyState, columnVisibility: controlledColumnVisibility, onColumnVisibilityChange, isLoading, className, ...props }: DataTableProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
82
86
  export {};
83
87
  //# sourceMappingURL=data-table.d.ts.map
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table';
3
+ import { Card, CardContent } from '../../components/card/index.js';
3
4
  import { Checkbox } from '../../components/checkbox/index.js';
4
- import { Icon } from '../../components/icon/index.js';
5
- import { Text } from '../../components/typography/index.js';
5
+ import { EmptyState } from '../../components/empty-state/index.js';
6
+ import { Skeleton } from '../../components/skeleton/index.js';
6
7
  import { useEffect, useMemo, useState } from 'react';
7
8
  import { cn } from '../../utils/cn.js';
8
9
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './table.js';
9
10
  import { TablePagination } from './table-pagination.js';
10
- export function DataTable({ columns, data, pagination = true, pageSize = 10, pageSizeOptions, showSelectedCount = false, onRowClick, emptyState, columnVisibility: controlledColumnVisibility, onColumnVisibilityChange, className, ...props }) {
11
+ export function DataTable({ columns, data, pagination = true, pageSize = 10, pageSizeOptions, showSelectedCount = false, onRowClick, emptyState, columnVisibility: controlledColumnVisibility, onColumnVisibilityChange, isLoading, className, ...props }) {
11
12
  const [sorting, setSorting] = useState([]);
12
13
  const [columnFilters, setColumnFilters] = useState([]);
13
14
  const [internalColumnVisibility, setInternalColumnVisibility] = useState({});
@@ -30,7 +31,6 @@ export function DataTable({ columns, data, pagination = true, pageSize = 10, pag
30
31
  }, [
31
32
  pageSize
32
33
  ]);
33
- // Add selection column if showSelectedCount is enabled
34
34
  const columnsWithSelection = useMemo(()=>{
35
35
  if (!showSelectedCount) {
36
36
  return columns;
@@ -85,78 +85,90 @@ export function DataTable({ columns, data, pagination = true, pageSize = 10, pag
85
85
  pagination: pagination ? paginationState : undefined
86
86
  }
87
87
  });
88
- return /*#__PURE__*/ _jsx("div", {
89
- className: cn('rounded-8 border border-border-neutral-base overflow-hidden', className),
90
- ...props,
91
- children: /*#__PURE__*/ _jsxs(Table, {
92
- children: [
93
- table.getRowModel().rows.length > 0 ? /*#__PURE__*/ _jsx(TableHeader, {
94
- children: table.getHeaderGroups().map((headerGroup)=>/*#__PURE__*/ _jsx(TableRow, {
95
- className: "hover:bg-transparent border-b",
96
- children: headerGroup.headers.map((header)=>/*#__PURE__*/ _jsx(TableHead, {
97
- children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
98
- }, header.id))
99
- }, headerGroup.id))
100
- }) : null,
101
- /*#__PURE__*/ _jsx(TableBody, {
102
- children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row)=>/*#__PURE__*/ _jsx(TableRow, {
103
- onClick: ()=>onRowClick?.(row.original),
104
- "data-selected": row.getIsSelected(),
105
- className: onRowClick ? 'cursor-pointer' : '',
106
- tabIndex: onRowClick ? 0 : undefined,
107
- role: onRowClick ? 'button' : undefined,
108
- onKeyDown: (event)=>{
109
- if (!onRowClick) return;
110
- if (event.key === 'Enter' || event.key === ' ') {
111
- event.preventDefault();
112
- onRowClick(row.original);
113
- }
114
- },
115
- children: row.getVisibleCells().map((cell)=>/*#__PURE__*/ _jsx(TableCell, {
116
- children: flexRender(cell.column.columnDef.cell, cell.getContext())
117
- }, cell.id))
118
- }, row.id)) : /*#__PURE__*/ _jsx(TableRow, {
119
- className: "hover:bg-transparent",
120
- children: /*#__PURE__*/ _jsx(TableCell, {
121
- colSpan: table.getAllColumns().length,
122
- className: "h-240 text-center",
123
- children: emptyState || /*#__PURE__*/ _jsxs("div", {
124
- className: "flex flex-col items-center justify-center gap-12 py-48",
125
- children: [
126
- /*#__PURE__*/ _jsx("div", {
127
- className: "size-32 rounded-6 bg-transparent border border-border-neutral-strong flex items-center justify-center",
128
- children: /*#__PURE__*/ _jsx(Icon, {
129
- name: "fileDamageLine",
130
- className: "size-16 text-foreground-neutral-subtle",
131
- color: "var(--foreground-neutral-subtle, #a1a1aa)"
88
+ const skeletonRowCount = pageSize > 5 ? 5 : pageSize;
89
+ if (isLoading) {
90
+ return /*#__PURE__*/ _jsx(Card, {
91
+ className: cn('p-0 gap-0', className),
92
+ ...props,
93
+ children: /*#__PURE__*/ _jsx(CardContent, {
94
+ className: "rounded-8 overflow-hidden p-0",
95
+ children: /*#__PURE__*/ _jsxs(Table, {
96
+ children: [
97
+ /*#__PURE__*/ _jsx(TableHeader, {
98
+ children: /*#__PURE__*/ _jsx(TableRow, {
99
+ className: "hover:bg-transparent border-b",
100
+ children: columns.map((_, idx)=>/*#__PURE__*/ _jsx(TableHead, {
101
+ children: /*#__PURE__*/ _jsx(Skeleton, {
102
+ className: "h-16 w-24"
132
103
  })
133
- }),
134
- /*#__PURE__*/ _jsxs("div", {
135
- className: "text-center space-y-4",
136
- children: [
137
- /*#__PURE__*/ _jsx(Text, {
138
- size: "sm",
139
- className: "text-foreground-neutral-base",
140
- children: "No results"
141
- }),
142
- /*#__PURE__*/ _jsx(Text, {
143
- size: "xs",
144
- className: "text-foreground-neutral-muted",
145
- children: "Looks like there are no results."
104
+ }, idx.toString()))
105
+ })
106
+ }),
107
+ /*#__PURE__*/ _jsx(TableBody, {
108
+ children: Array.from({
109
+ length: skeletonRowCount
110
+ }).map((_, rowIdx)=>/*#__PURE__*/ _jsx(TableRow, {
111
+ className: "hover:bg-transparent",
112
+ children: columns.map((_, colIdx)=>/*#__PURE__*/ _jsx(TableCell, {
113
+ children: /*#__PURE__*/ _jsx(Skeleton, {
114
+ className: "h-16 w-full"
146
115
  })
147
- ]
148
- })
149
- ]
116
+ }, colIdx.toString()))
117
+ }, rowIdx.toString()))
118
+ })
119
+ ]
120
+ })
121
+ })
122
+ });
123
+ }
124
+ return /*#__PURE__*/ _jsx(Card, {
125
+ className: cn('p-0 gap-0', className),
126
+ ...props,
127
+ children: /*#__PURE__*/ _jsx(CardContent, {
128
+ className: "rounded-b-8 overflow-hidden p-0",
129
+ children: /*#__PURE__*/ _jsxs(Table, {
130
+ children: [
131
+ table.getRowModel().rows.length > 0 ? /*#__PURE__*/ _jsx(TableHeader, {
132
+ children: table.getHeaderGroups().map((headerGroup)=>/*#__PURE__*/ _jsx(TableRow, {
133
+ className: "hover:bg-transparent border-b",
134
+ children: headerGroup.headers.map((header)=>/*#__PURE__*/ _jsx(TableHead, {
135
+ children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
136
+ }, header.id))
137
+ }, headerGroup.id))
138
+ }) : null,
139
+ /*#__PURE__*/ _jsx(TableBody, {
140
+ children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row)=>/*#__PURE__*/ _jsx(TableRow, {
141
+ onClick: ()=>onRowClick?.(row.original),
142
+ "data-selected": row.getIsSelected(),
143
+ className: onRowClick ? 'cursor-pointer' : '',
144
+ tabIndex: onRowClick ? 0 : undefined,
145
+ role: onRowClick ? 'button' : undefined,
146
+ onKeyDown: (event)=>{
147
+ if (!onRowClick) return;
148
+ if (event.key === 'Enter' || event.key === ' ') {
149
+ event.preventDefault();
150
+ onRowClick(row.original);
151
+ }
152
+ },
153
+ children: row.getVisibleCells().map((cell)=>/*#__PURE__*/ _jsx(TableCell, {
154
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
155
+ }, cell.id))
156
+ }, row.id)) : /*#__PURE__*/ _jsx(TableRow, {
157
+ className: "hover:bg-transparent",
158
+ children: /*#__PURE__*/ _jsx(TableCell, {
159
+ colSpan: table.getAllColumns().length,
160
+ className: "h-240 text-center rounded-t-8",
161
+ children: emptyState || /*#__PURE__*/ _jsx(EmptyState, {})
150
162
  })
151
163
  })
164
+ }),
165
+ pagination && table.getRowModel().rows?.length > 0 && /*#__PURE__*/ _jsx(TablePagination, {
166
+ table: table,
167
+ pageSizeOptions: pageSizeOptions,
168
+ showSelectedCount: showSelectedCount
152
169
  })
153
- }),
154
- pagination && table.getRowModel().rows?.length > 0 && /*#__PURE__*/ _jsx(TablePagination, {
155
- table: table,
156
- pageSizeOptions: pageSizeOptions,
157
- showSelectedCount: showSelectedCount
158
- })
159
- ]
170
+ ]
171
+ })
160
172
  })
161
173
  });
162
174
  }
@@ -34,7 +34,7 @@ function TableFooter({ className, ...props }) {
34
34
  function TableRow({ className, ...props }) {
35
35
  return /*#__PURE__*/ _jsx("tr", {
36
36
  "data-slot": "table-row",
37
- className: cn('group/row border-b border-border-neutral-base transition-colors', 'last:border-b-0', 'hover:bg-background-neutral-hover', 'data-[selected=true]:bg-background-neutral-pressed data-[selected=true]:hover:bg-background-neutral-pressed', className),
37
+ className: cn('group/row border-b border-border-neutral-base transition-colors', 'last:border-b-0 last:rounded-b-8', 'hover:bg-background-neutral-hover', 'data-[selected=true]:bg-background-neutral-pressed data-[selected=true]:hover:bg-background-neutral-pressed', className),
38
38
  ...props
39
39
  });
40
40
  }
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /**
3
3
  * Shared components for Table stories
4
- */ import { Icon } from '../../components/icon/index.js';
4
+ */ import { EmptyState } from '../../components/empty-state/index.js';
5
+ import { Icon } from '../../components/icon/index.js';
5
6
  import { useSearchContext } from '../../components/search/search-context.js';
6
7
  import { SearchEmpty, SearchFooter, SearchGroup, SearchInput, SearchItem, SearchList } from '../../components/search/search-modal.js';
7
8
  import { Text } from '../../components/typography/index.js';
@@ -10,33 +11,10 @@ import { searchJobsData } from './table.stories.data.js';
10
11
  /**
11
12
  * Empty state component for job tables
12
13
  */ export function JobsEmptyState() {
13
- return /*#__PURE__*/ _jsxs("div", {
14
- className: "flex flex-col items-center justify-center gap-12 py-48",
15
- children: [
16
- /*#__PURE__*/ _jsx("div", {
17
- className: "size-32 rounded-6 bg-transparent border border-border-neutral-strong flex items-center justify-center",
18
- children: /*#__PURE__*/ _jsx(Icon, {
19
- name: "shipfox",
20
- className: "size-16 text-foreground-neutral-subtle",
21
- color: "var(--foreground-neutral-subtle, #a1a1aa)"
22
- })
23
- }),
24
- /*#__PURE__*/ _jsxs("div", {
25
- className: "text-center space-y-4",
26
- children: [
27
- /*#__PURE__*/ _jsx(Text, {
28
- size: "sm",
29
- className: "text-foreground-neutral-base",
30
- children: "No jobs yet"
31
- }),
32
- /*#__PURE__*/ _jsx(Text, {
33
- size: "xs",
34
- className: "text-foreground-neutral-muted",
35
- children: "Import past runs or start a runner."
36
- })
37
- ]
38
- })
39
- ]
14
+ return /*#__PURE__*/ _jsx(EmptyState, {
15
+ icon: "shipfox",
16
+ title: "No jobs yet",
17
+ description: "Import past runs or start a runner."
40
18
  });
41
19
  }
42
20
  /**