@flamingo-stack/openframe-frontend-core 0.0.273 → 0.0.274

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 (65) hide show
  1. package/dist/{chunk-IXRPEMZP.cjs → chunk-2KHFSSFZ.cjs} +11 -11
  2. package/dist/{chunk-IXRPEMZP.cjs.map → chunk-2KHFSSFZ.cjs.map} +1 -1
  3. package/dist/{chunk-Q32JUFIK.cjs → chunk-4DYXV3E7.cjs} +508 -543
  4. package/dist/chunk-4DYXV3E7.cjs.map +1 -0
  5. package/dist/{chunk-MCCYGAPE.js → chunk-FLIWL6V4.js} +2 -2
  6. package/dist/{chunk-4SNHFZQT.js → chunk-GL5X6VVC.js} +2 -2
  7. package/dist/{chunk-VFMMVGA4.js → chunk-OPSZNW3I.js} +316 -351
  8. package/dist/chunk-OPSZNW3I.js.map +1 -0
  9. package/dist/{chunk-UQCB2CP7.js → chunk-VASNLWPZ.js} +2 -2
  10. package/dist/{chunk-EEMZBQ7O.cjs → chunk-W5KBDFCR.cjs} +25 -25
  11. package/dist/{chunk-EEMZBQ7O.cjs.map → chunk-W5KBDFCR.cjs.map} +1 -1
  12. package/dist/{chunk-V5OZQF4B.cjs → chunk-WU6PMH5L.cjs} +32 -32
  13. package/dist/{chunk-V5OZQF4B.cjs.map → chunk-WU6PMH5L.cjs.map} +1 -1
  14. package/dist/components/chat/index.cjs +2 -2
  15. package/dist/components/chat/index.js +1 -1
  16. package/dist/components/contact/index.cjs +3 -3
  17. package/dist/components/contact/index.js +2 -2
  18. package/dist/components/features/index.cjs +2 -2
  19. package/dist/components/features/index.js +1 -1
  20. package/dist/components/index.cjs +54 -56
  21. package/dist/components/index.cjs.map +1 -1
  22. package/dist/components/index.js +3 -5
  23. package/dist/components/index.js.map +1 -1
  24. package/dist/components/navigation/index.cjs +2 -2
  25. package/dist/components/navigation/index.js +1 -1
  26. package/dist/components/related-content/index.cjs +3 -3
  27. package/dist/components/related-content/index.js +2 -2
  28. package/dist/components/tickets/index.cjs +53 -53
  29. package/dist/components/tickets/index.js +3 -3
  30. package/dist/components/ui/data-table/data-table-body.d.ts +5 -1
  31. package/dist/components/ui/data-table/data-table-body.d.ts.map +1 -1
  32. package/dist/components/ui/data-table/data-table-empty.d.ts +10 -10
  33. package/dist/components/ui/data-table/data-table-empty.d.ts.map +1 -1
  34. package/dist/components/ui/index.cjs +2 -4
  35. package/dist/components/ui/index.cjs.map +1 -1
  36. package/dist/components/ui/index.js +1 -3
  37. package/dist/components/ui/no-data/no-data-actions.d.ts +11 -15
  38. package/dist/components/ui/no-data/no-data-actions.d.ts.map +1 -1
  39. package/dist/components/ui/no-data/no-data-styles.d.ts +0 -1
  40. package/dist/components/ui/no-data/no-data-styles.d.ts.map +1 -1
  41. package/dist/components/ui/no-data/no-data.d.ts.map +1 -1
  42. package/dist/components/ui/query-report-table/query-report-table.d.ts.map +1 -1
  43. package/dist/components/ui/table/table-empty-state.d.ts +1 -2
  44. package/dist/components/ui/table/table-empty-state.d.ts.map +1 -1
  45. package/dist/components/ui/table/table.d.ts.map +1 -1
  46. package/dist/index.cjs +2 -4
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.js +1 -3
  49. package/package.json +1 -1
  50. package/src/components/ui/data-table/.data-table-empty.md +28 -24
  51. package/src/components/ui/data-table/data-table-body.tsx +13 -2
  52. package/src/components/ui/data-table/data-table-empty.tsx +18 -35
  53. package/src/components/ui/no-data/no-data-actions.tsx +20 -43
  54. package/src/components/ui/no-data/no-data-styles.ts +8 -18
  55. package/src/components/ui/no-data/no-data.tsx +7 -1
  56. package/src/components/ui/query-report-table/query-report-table.tsx +1 -1
  57. package/src/components/ui/table/table-empty-state.tsx +12 -37
  58. package/src/components/ui/table/table.tsx +1 -1
  59. package/src/stories/DataTable.stories.tsx +26 -2
  60. package/src/stories/EmptyState.stories.tsx +21 -34
  61. package/dist/chunk-Q32JUFIK.cjs.map +0 -1
  62. package/dist/chunk-VFMMVGA4.js.map +0 -1
  63. /package/dist/{chunk-MCCYGAPE.js.map → chunk-FLIWL6V4.js.map} +0 -0
  64. /package/dist/{chunk-4SNHFZQT.js.map → chunk-GL5X6VVC.js.map} +0 -0
  65. /package/dist/{chunk-UQCB2CP7.js.map → chunk-VASNLWPZ.js.map} +0 -0
@@ -1,14 +1,9 @@
1
1
  import React from "react"
2
2
 
3
3
  import { cn } from "../../../utils/cn"
4
- import {
5
- noDataActionInteractiveClasses,
6
- noDataActionsVariants,
7
- noDataIconClasses,
8
- type NoDataActionsVariant,
9
- } from "./no-data-styles"
4
+ import { noDataActionsVariants, noDataIconClasses, type NoDataActionsVariant } from "./no-data-styles"
10
5
 
11
- interface NoDataActionProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "title"> {
6
+ interface NoDataActionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
12
7
  /** Leading glyph, sized to 16px (mobile) / 24px (md+). Optional. */
13
8
  icon?: React.ReactNode
14
9
  /** Short label describing the block. */
@@ -16,51 +11,42 @@ interface NoDataActionProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonEl
16
11
  }
17
12
 
18
13
  /**
19
- * A single clickable block: a leading icon with a short label, laid out
20
- * icon-beside-label on mobile and icon-above-label on larger screens. Tints on
21
- * hover, shows a focus ring for keyboard users, and grays out when disabled.
22
- * The outer border, rounded corners and dividers come from the surrounding
23
- * group, so on its own it has no frame.
14
+ * A single static info block: a leading icon with a short label, laid out
15
+ * icon-beside-label on mobile and icon-above-label on larger screens. Purely
16
+ * presentational no hover or click. The outer border, rounded corners and
17
+ * dividers come from the surrounding group. Capped at 244px wide on md+.
24
18
  */
25
- const NoDataAction = React.forwardRef<HTMLButtonElement, NoDataActionProps>(
26
- function NoDataAction({ icon, label, children, className, disabled, type, ...props }, ref) {
19
+ const NoDataAction = React.forwardRef<HTMLDivElement, NoDataActionProps>(
20
+ function NoDataAction({ icon, label, children, className, ...props }, ref) {
27
21
  return (
28
- <button
22
+ <div
29
23
  ref={ref}
30
- type={type ?? "button"}
31
- disabled={disabled}
32
24
  className={cn(
33
- "flex flex-1 items-center gap-[var(--spacing-system-s)] p-[var(--spacing-system-m)] text-left text-ods-text-secondary",
34
- "md:flex-col md:items-start md:gap-[var(--spacing-system-xs)]",
35
- noDataActionInteractiveClasses,
25
+ "flex flex-1 items-center gap-[var(--spacing-system-s)] p-[var(--spacing-system-m)] text-ods-text-secondary",
26
+ "md:w-[224px] md:flex-none md:flex-col md:items-start md:gap-[var(--spacing-system-xs)]",
36
27
  className,
37
28
  )}
38
29
  {...props}
39
30
  >
40
- {icon && <span className={noDataIconClasses}>{icon}</span>}
41
- <span className="min-w-0 flex-1 break-words text-h6 md:w-full md:flex-none">
42
- {label ?? children}
43
- </span>
44
- </button>
31
+ {icon && <span className={cn(noDataIconClasses, "text-ods-text-primary")}>{icon}</span>}
32
+ <span className="min-w-0 flex-1 break-words text-h6 md:w-full md:flex-none">{label ?? children}</span>
33
+ </div>
45
34
  )
46
35
  },
47
36
  )
48
37
 
49
38
  interface NoDataActionsProps extends React.HTMLAttributes<HTMLDivElement> {
50
- /**
51
- * The blocks to render. Count is dynamic — any number works. When omitted,
52
- * `children` are rendered instead.
53
- */
39
+ /** The blocks to render. When omitted, `children` are rendered instead. */
54
40
  actions?: NoDataActionProps[]
55
41
  /** Surface treatment of the group panel. */
56
42
  variant?: NoDataActionsVariant
57
43
  }
58
44
 
59
45
  /**
60
- * A group of clickable blocks sharing one bordered, card-colored panel. Renders
46
+ * A group of static info blocks sharing one transparent, bordered panel. Renders
61
47
  * as a horizontal row with vertical dividers on larger screens and a vertical
62
- * stack with horizontal dividers on mobile, switching automatically. Only the
63
- * outermost blocks have rounded corners.
48
+ * stack with horizontal dividers on mobile. Only the outermost blocks have
49
+ * rounded corners.
64
50
  */
65
51
  const NoDataActions = React.forwardRef<HTMLDivElement, NoDataActionsProps>(
66
52
  function NoDataActions({ actions, variant = "outline", className, children, ...props }, ref) {
@@ -71,11 +57,7 @@ const NoDataActions = React.forwardRef<HTMLDivElement, NoDataActionsProps>(
71
57
  return (
72
58
  <div
73
59
  ref={ref}
74
- className={cn(
75
- noDataActionsVariants({ variant }),
76
- "flex w-full flex-col md:w-auto md:flex-row",
77
- className,
78
- )}
60
+ className={cn(noDataActionsVariants({ variant }), "flex w-full flex-col md:w-auto md:flex-row", className)}
79
61
  {...props}
80
62
  >
81
63
  {blocks.map((block, index) => (
@@ -94,9 +76,4 @@ const NoDataActions = React.forwardRef<HTMLDivElement, NoDataActionsProps>(
94
76
  },
95
77
  )
96
78
 
97
- export {
98
- NoDataAction,
99
- NoDataActions,
100
- type NoDataActionProps,
101
- type NoDataActionsProps,
102
- }
79
+ export { NoDataAction, NoDataActions, type NoDataActionProps, type NoDataActionsProps }
@@ -1,23 +1,21 @@
1
- // Shared style atoms for the NoData (empty-state) family. Mirrors the approach
2
- // used by `button-styles.ts`: a single source of truth for the icon scale, the
3
- // block-group surface and the interactive/disabled treatment, expressed as
4
- // reusable class atoms so new looks can be added without touching the markup.
1
+ // Shared style atoms for the NoData (empty-state) family. A single source of
2
+ // truth for the icon scale and the info-block group surface, expressed as CVA
3
+ // variants so new looks can be added without touching the markup.
5
4
 
6
5
  import { cva, type VariantProps } from "class-variance-authority"
7
6
 
8
7
  // Leading-icon glyph scale: 16px on mobile, 24px on md+. Color is intentionally
9
- // omitted so the glyph inherits the current text color (and dims with it when
10
- // the block is disabled).
8
+ // omitted so the glyph inherits the current text color.
11
9
  export const noDataIconClasses =
12
10
  "inline-flex shrink-0 items-center justify-center [&_svg]:h-4 [&_svg]:w-4 md:[&_svg]:h-6 md:[&_svg]:w-6"
13
11
 
14
- // Surface for the action-block group container: a card-colored panel with a
15
- // border and rounded corners. `overflow-hidden` keeps only the outer blocks
16
- // round — inner blocks stay square.
12
+ // Surface for the info-block group container: a transparent, bordered panel with
13
+ // rounded corners. `overflow-hidden` keeps only the outer blocks round — inner
14
+ // blocks stay square.
17
15
  export const noDataActionsVariants = cva("overflow-hidden rounded-md", {
18
16
  variants: {
19
17
  variant: {
20
- outline: "bg-ods-card border border-ods-border",
18
+ outline: "border border-ods-border",
21
19
  },
22
20
  },
23
21
  defaultVariants: { variant: "outline" },
@@ -26,11 +24,3 @@ export const noDataActionsVariants = cva("overflow-hidden rounded-md", {
26
24
  export type NoDataActionsVariant = NonNullable<
27
25
  VariantProps<typeof noDataActionsVariants>["variant"]
28
26
  >
29
-
30
- // Interactive treatment for a clickable block: hover/active surface tints, a
31
- // keyboard focus ring, and a disabled state that grays the text and stops
32
- // pointer interaction — matching the disabled outline button.
33
- export const noDataActionInteractiveClasses =
34
- "cursor-pointer transition-colors hover:bg-ods-bg-hover active:bg-ods-bg-active " +
35
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus focus-visible:ring-inset " +
36
- "disabled:cursor-default disabled:pointer-events-none disabled:text-ods-text-disabled"
@@ -60,7 +60,13 @@ const NoData = React.forwardRef<HTMLDivElement, NoDataProps>(function NoData(
60
60
  const footerButton =
61
61
  button ??
62
62
  (buttonLabel != null ? (
63
- <Button variant="outline" leftIcon={buttonIcon} onClick={onButtonClick} {...buttonProps}>
63
+ <Button
64
+ variant="outline"
65
+ leftIcon={buttonIcon}
66
+ onClick={onButtonClick}
67
+ {...buttonProps}
68
+ className={cn("w-full md:w-auto", buttonProps?.className)}
69
+ >
64
70
  {buttonLabel}
65
71
  </Button>
66
72
  ) : null)
@@ -18,7 +18,7 @@ export function QueryReportTable({
18
18
  loading = false,
19
19
  skeletonRows = 8,
20
20
  skeletonColumns = 6,
21
- emptyMessage = 'No results found',
21
+ emptyMessage,
22
22
  columnWidth = 160,
23
23
  columnOrder,
24
24
  showExport = true,
@@ -1,45 +1,20 @@
1
1
  'use client'
2
2
 
3
- import React from 'react'
4
- import { FileX2 } from 'lucide-react'
5
3
  import { cn } from '../../../utils/cn'
6
- import { Button } from '../button'
4
+ import { SearchIcon } from '../../icons-v2-generated'
5
+ import { NoData } from '../no-data'
7
6
  import type { TableEmptyStateProps } from './types'
8
7
 
9
8
  /** @deprecated Use `DataTableEmpty` from `data-table` instead. */
10
- export function TableEmptyState({
11
- message = 'No data available',
12
- icon,
13
- action,
14
- className
15
- }: TableEmptyStateProps) {
9
+ export function TableEmptyState({ message, icon, action, className }: TableEmptyStateProps) {
16
10
  return (
17
- <div
18
- className={cn(
19
- 'flex flex-col items-center justify-center py-12 px-4 rounded-[6px] bg-ods-card border border-ods-border',
20
- className
21
- )}
22
- >
23
- {/* Icon */}
24
- <div className="mb-4 text-ods-text-secondary">
25
- {icon || <FileX2 className="w-12 h-12" />}
26
- </div>
27
-
28
- {/* Message */}
29
- <p className="text-h4 text-ods-text-secondary text-center mb-6">
30
- {message}
31
- </p>
32
-
33
- {/* Action Button */}
34
- {action && (
35
- <Button
36
- variant="outline"
37
- onClick={action.onClick}
38
- className="bg-ods-card border-ods-border hover:bg-ods-bg-active text-ods-text-primary"
39
- >
40
- {action.label}
41
- </Button>
42
- )}
43
- </div>
11
+ <NoData
12
+ icon={icon ?? <SearchIcon />}
13
+ title={message ?? 'No results found'}
14
+ description={message == null ? 'Try adjusting your search or filters' : undefined}
15
+ buttonLabel={action?.label}
16
+ onButtonClick={action?.onClick}
17
+ className={cn('py-[var(--spacing-system-xxl)]', className)}
18
+ />
44
19
  )
45
- }
20
+ }
@@ -91,7 +91,7 @@ export function Table<T = any>({
91
91
  columns,
92
92
  rowKey,
93
93
  loading = false,
94
- emptyMessage = 'No data available',
94
+ emptyMessage,
95
95
  skeletonRows = 10,
96
96
  className,
97
97
  containerClassName,
@@ -730,7 +730,8 @@ export const Loading: Story = {
730
730
 
731
731
  /**
732
732
  * **Empty state** — when there are no rows and `loading` is falsy, the body
733
- * renders the built-in empty state. Override the message via `emptyMessage`.
733
+ * renders the built-in empty state (`NoData`). By default it shows a search
734
+ * icon with "No results found" / "Try adjusting your search or filters".
734
735
  */
735
736
  export const EmptyState: Story = {
736
737
  render: () => {
@@ -740,7 +741,30 @@ export const EmptyState: Story = {
740
741
  return (
741
742
  <DataTable table={table}>
742
743
  <DataTable.Header />
743
- <DataTable.Body emptyMessage="No devices match your filters" />
744
+ <DataTable.Body />
745
+ </DataTable>
746
+ )
747
+ },
748
+ }
749
+
750
+ /**
751
+ * **Empty state — custom** — override any field via the `emptyState` prop,
752
+ * which accepts the full `NoData` props (icon/title/description/actions/button).
753
+ */
754
+ export const EmptyStateCustom: Story = {
755
+ render: () => {
756
+ const columns = useMemo<ColumnDef<Device>[]>(() => baseColumns().slice(0, 4), [])
757
+ const table = useDataTable<Device>({ data: [], columns })
758
+
759
+ return (
760
+ <DataTable table={table}>
761
+ <DataTable.Header />
762
+ <DataTable.Body
763
+ emptyState={{
764
+ title: 'No devices yet',
765
+ description: 'Connect your first device to get started',
766
+ }}
767
+ />
744
768
  </DataTable>
745
769
  )
746
770
  },
@@ -1,6 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
2
  import { Database, FileText, Inbox, Plus, Search, Settings, Sparkles, Upload, Zap } from 'lucide-react';
3
3
  import React from 'react';
4
+ import { MingoIcon } from '../components/icons';
4
5
  import { Button } from '../components/ui/button';
5
6
  import { NoData, NoDataAction, NoDataActions, NoDataMessage } from '../components/ui/no-data';
6
7
 
@@ -25,10 +26,14 @@ type Story = StoryObj<typeof meta>;
25
26
 
26
27
  const noop = () => {};
27
28
 
29
+ const mingoButtonIcon = (
30
+ <MingoIcon className="size-5" eyesColor="var(--ods-flamingo-cyan-base)" cornerColor="var(--ods-flamingo-cyan-base)" />
31
+ );
32
+
28
33
  const defaultActions = [
29
- { icon: <Zap />, label: 'Feature Description', onClick: noop },
30
- { icon: <Sparkles />, label: 'Feature Description', onClick: noop },
31
- { icon: <Database />, label: 'Feature Description', onClick: noop },
34
+ { icon: <Zap />, label: 'Feature Description' },
35
+ { icon: <Sparkles />, label: 'Feature Description' },
36
+ { icon: <Database />, label: 'Feature Description' },
32
37
  ];
33
38
 
34
39
  // === Full composition ===
@@ -40,7 +45,7 @@ export const Default: Story = {
40
45
  description: 'Start by adding an item',
41
46
  actions: defaultActions,
42
47
  buttonLabel: 'Ask Mingo about Item',
43
- buttonIcon: <Sparkles />,
48
+ buttonIcon: mingoButtonIcon,
44
49
  onButtonClick: noop,
45
50
  },
46
51
  };
@@ -84,11 +89,11 @@ export const TwoActions: Story = {
84
89
  title: 'No data available',
85
90
  description: 'Start by adding an item',
86
91
  actions: [
87
- { icon: <Zap />, label: 'Feature Description', onClick: noop },
88
- { icon: <Sparkles />, label: 'Feature Description', onClick: noop },
92
+ { icon: <Zap />, label: 'Feature Description' },
93
+ { icon: <Sparkles />, label: 'Feature Description' },
89
94
  ],
90
95
  buttonLabel: 'Ask Mingo about Item',
91
- buttonIcon: <Sparkles />,
96
+ buttonIcon: mingoButtonIcon,
92
97
  onButtonClick: noop,
93
98
  },
94
99
  };
@@ -99,31 +104,13 @@ export const FourActions: Story = {
99
104
  title: 'No data available',
100
105
  description: 'Start by adding an item',
101
106
  actions: [
102
- { icon: <Zap />, label: 'Real-time sync', onClick: noop },
103
- { icon: <Sparkles />, label: 'Smart suggestions', onClick: noop },
104
- { icon: <Database />, label: 'Unlimited storage', onClick: noop },
105
- { icon: <FileText />, label: 'Export anywhere', onClick: noop },
106
- ],
107
- buttonLabel: 'Ask Mingo about Item',
108
- buttonIcon: <Sparkles />,
109
- onButtonClick: noop,
110
- },
111
- };
112
-
113
- // === Disabled blocks ===
114
-
115
- export const DisabledActions: Story = {
116
- args: {
117
- icon: <Inbox />,
118
- title: 'No data available',
119
- description: 'Some actions are unavailable',
120
- actions: [
121
- { icon: <Zap />, label: 'Available', onClick: noop },
122
- { icon: <Sparkles />, label: 'Disabled', onClick: noop, disabled: true },
123
- { icon: <Database />, label: 'Disabled', onClick: noop, disabled: true },
107
+ { icon: <Zap />, label: 'Real-time sync' },
108
+ { icon: <Sparkles />, label: 'Smart suggestions' },
109
+ { icon: <Database />, label: 'Unlimited storage' },
110
+ { icon: <FileText />, label: 'Export anywhere' },
124
111
  ],
125
112
  buttonLabel: 'Ask Mingo about Item',
126
- buttonIcon: <Sparkles />,
113
+ buttonIcon: mingoButtonIcon,
127
114
  onButtonClick: noop,
128
115
  },
129
116
  };
@@ -162,9 +149,9 @@ export const StandaloneActions: Story = {
162
149
  args: { title: '' },
163
150
  render: () => (
164
151
  <NoDataActions>
165
- <NoDataAction icon={<Zap />} label="Clickable block" onClick={noop} />
166
- <NoDataAction icon={<Sparkles />} label="Clickable block" onClick={noop} />
167
- <NoDataAction icon={<Database />} label="Disabled block" onClick={noop} disabled />
152
+ <NoDataAction icon={<Zap />} label="Info block" />
153
+ <NoDataAction icon={<Sparkles />} label="Info block" />
154
+ <NoDataAction icon={<Database />} label="Info block" />
168
155
  </NoDataActions>
169
156
  ),
170
157
  };
@@ -192,7 +179,7 @@ export const Showcase: Story = {
192
179
  description="Start by adding an item"
193
180
  actions={defaultActions}
194
181
  buttonLabel="Ask Mingo about Item"
195
- buttonIcon={<Sparkles />}
182
+ buttonIcon={mingoButtonIcon}
196
183
  onButtonClick={noop}
197
184
  />
198
185
  <NoData icon={<Search />} title="No results found" description="Try a different search" />