florixui 1.4.1 → 1.6.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/README.md CHANGED
@@ -243,6 +243,20 @@ Displays a short, important message that draws attention without interrupting th
243
243
  </Alert>
244
244
  ```
245
245
 
246
+ ### Alert Card
247
+
248
+ A higher-level alert with two looks — filled (soft tinted background) and outline (bordered card with an icon box and actions) — across four severities. Theme-aware: severities map to the blue / orange / red / green tokens.
249
+
250
+ ```tsx
251
+ <AlertCard
252
+ variant="filled"
253
+ severity="info"
254
+ title="New update"
255
+ description="v2.4.0 is ready. Restart to apply."
256
+ dismissible
257
+ />
258
+ ```
259
+
246
260
  ### Alert Dialog
247
261
 
248
262
  A modal dialog that interrupts the user with important content and expects a confirm or cancel response before continuing.
@@ -574,6 +588,38 @@ Displays a menu of actions or options triggered by a button, built on Radix UI w
574
588
  </DropdownMenu>
575
589
  ```
576
590
 
591
+ ### Empty
592
+
593
+ A composable empty state — media (icon/avatar), title, and description in a header, with optional actions. For "no data", "no results", offline, and 404 states.
594
+
595
+ ```tsx
596
+ <Empty>
597
+ <EmptyHeader>
598
+ <EmptyMedia variant="icon">
599
+ <FolderIcon />
600
+ </EmptyMedia>
601
+ <EmptyTitle>No projects yet</EmptyTitle>
602
+ <EmptyDescription>
603
+ Get started by creating your first project.
604
+ </EmptyDescription>
605
+ </EmptyHeader>
606
+ <EmptyContent>
607
+ <Button>
608
+ <PlusIcon />
609
+ Create project
610
+ </Button>
611
+ </EmptyContent>
612
+ </Empty>
613
+ ```
614
+
615
+ ### Empty State
616
+
617
+ A convenience wrapper over the Empty primitive — pass icon, title, description, and actions as props (with sensible defaults) instead of composing the parts by hand.
618
+
619
+ ```tsx
620
+ <EmptyState title="No notifications" />
621
+ ```
622
+
577
623
  ### Faceted Filter
578
624
 
579
625
  A controlled filter trigger and popover: a searchable list of options selectable as multi-select checkboxes (default) or single-select. Shows a selected-count badge on the trigger and emits the value(s) via onChange so you can filter your own list or API query.
@@ -775,6 +821,14 @@ An interactive map built on MapLibre GL (via mapcn), with markers, routes, clust
775
821
  />
776
822
  ```
777
823
 
824
+ ### Not Found
825
+
826
+ A centered status screen — a large code (e.g. "404"), a title, a description, and Go Back / Go to Home actions. Generic enough for 404 / 403 / 500 and empty states.
827
+
828
+ ```tsx
829
+ <NotFound homeHref="/" />
830
+ ```
831
+
778
832
  ### Popover
779
833
 
780
834
  Displays rich, floating content in a portal, anchored to a trigger and toggled by click.
@@ -1150,4 +1204,169 @@ Displays a brief, contextual label in a popup when the user hovers or focuses an
1150
1204
  </TooltipProvider>
1151
1205
  ```
1152
1206
 
1207
+ ## Bits
1208
+
1209
+ > Small, composable building blocks (see the "Bits" page in the docs). Each shows a quick usage snippet.
1210
+
1211
+ ### Card in card
1212
+
1213
+ An outer card with a header + action, containing nested cards — one per Card background variant.
1214
+
1215
+ ```tsx
1216
+ // One nested card per Card variant
1217
+ const SITES = [
1218
+ { variant: 'alt', name: 'Skyline Tower', /* … */ },
1219
+ { variant: 'primary', name: 'Marina Heights', /* … */ },
1220
+ { variant: 'success', name: 'Green Park Plaza', /* … */ },
1221
+ { variant: 'warning', name: 'Dockside Depot', /* … */ },
1222
+ { variant: 'danger', name: 'Old Mill Unit', /* … */ },
1223
+ ]
1224
+
1225
+ <Card>
1226
+ <CardHeader>
1227
+ <CardTitle className="flex items-center gap-2">
1228
+ <Building2Icon className="size-5" /> Site Assignment
1229
+ </CardTitle>
1230
+ <CardDescription>Nested cards, one per variant</CardDescription>
1231
+ <CardAction>
1232
+ <Button variant="outline" size="sm">
1233
+ <ArrowLeftRightIcon className="size-4" /> Reassign
1234
+ </Button>
1235
+ </CardAction>
1236
+ </CardHeader>
1237
+ <CardContent className="grid gap-3 sm:grid-cols-2">
1238
+ {SITES.map((s) => (
1239
+ <Card key={s.name} variant={s.variant} size="sm">
1240
+ <CardContent className="flex items-center gap-3">
1241
+ <StatusIcon className="bg-card text-foreground"><Building2Icon /></StatusIcon>
1242
+ <div className="flex-1">
1243
+ <p className="font-medium">{s.name}</p>
1244
+ <p className="text-xs text-muted-foreground">
1245
+ <LayersIcon className="size-3.5" /> {s.floor}
1246
+ </p>
1247
+ <p className="text-xs text-muted-foreground">
1248
+ <MapPinIcon className="size-3.5" /> {s.addr}
1249
+ </p>
1250
+ </div>
1251
+ <Badge>{s.status}</Badge>
1252
+ </CardContent>
1253
+ </Card>
1254
+ ))}
1255
+ </CardContent>
1256
+ </Card>
1257
+ ```
1258
+
1259
+ ### DataCell
1260
+
1261
+ A labelled value cell. "stacked" (default) puts the label above the value — lay them out in a grid for spec sheets; "row" puts the value on the right.
1262
+
1263
+ ```tsx
1264
+ // stacked (default) — an optional icon sits beside the value
1265
+ <div className="grid grid-cols-3 gap-x-8 gap-y-4">
1266
+ <DataCell label="Make" value="Liebherr" />
1267
+ <DataCell label="Category" value="lifting" icon={<WrenchIcon />} />
1268
+ <DataCell label="Asset Value" value="₹4,500,000" icon={<BanknoteIcon />} />
1269
+ {/* … */}
1270
+ </div>
1271
+
1272
+ // row — value (with icon) on the right
1273
+ <div className="divide-y">
1274
+ <DataCell layout="row" icon={<BanknoteIcon />} label="Asset Value" value="₹4,500,000" />
1275
+ <DataCell layout="row" icon={<ShieldCheckIcon />} label="Insurance Policy" value="INS-CR-8821" />
1276
+ </div>
1277
+ ```
1278
+
1279
+ ### DefRow
1280
+
1281
+ A label/value definition row for detail cards. Stack several in a divide-y container.
1282
+
1283
+ ```tsx
1284
+ <div className="divide-y">
1285
+ <DefRow label="Price" value="$960.99" />
1286
+ <DefRow label="Stock" value="5 units" />
1287
+ <DefRow label="Category" value="Electronics" />
1288
+ <DefRow label="SKU" value="SKU-RCH45Q1A" />
1289
+ </div>
1290
+ ```
1291
+
1292
+ ### QuickStat
1293
+
1294
+ A compact inline stat — icon, value, and an optional muted label. Line several up with vertical separators.
1295
+
1296
+ ```tsx
1297
+ <div className="flex items-center gap-3 [&>[data-slot=separator]]:h-4">
1298
+ <QuickStat icon={<TagIcon />} value="$960.99" />
1299
+ <Separator orientation="vertical" />
1300
+ <QuickStat icon={<PackageIcon />} value={5} label="in stock" />
1301
+ <Separator orientation="vertical" />
1302
+ <QuickStat icon={<StarIcon className="fill-orange text-orange" />} value={4.9} />
1303
+ <Separator orientation="vertical" />
1304
+ <QuickStat icon={<TrendingUpIcon />} value={982} label="sold" />
1305
+ </div>
1306
+ ```
1307
+
1308
+ ### StatusList
1309
+
1310
+ Status rows with flexible leading visuals (tinted icon box, avatar/initials, or plain icon), pill / outline / text status, and group headers.
1311
+
1312
+ ```tsx
1313
+ <StatusList>
1314
+ <StatusListGroup label="Gateways" count={2}>
1315
+ <StatusListItem
1316
+ media={<StatusIcon tone="success"><RadioIcon /></StatusIcon>}
1317
+ title="GW-SKY-B01"
1318
+ description="WiFi · 100% · 2 tags"
1319
+ status="Online"
1320
+ statusVariant="outline"
1321
+ tone="success"
1322
+ />
1323
+ <StatusListItem
1324
+ media={<StatusIcon tone="warning"><RadioIcon /></StatusIcon>}
1325
+ title="GW-SKY-B04"
1326
+ description="4G · 54% · 2 tags"
1327
+ status="Degraded"
1328
+ statusVariant="outline"
1329
+ tone="warning"
1330
+ />
1331
+ </StatusListGroup>
1332
+
1333
+ <StatusListGroup label="Workers" count={2}>
1334
+ <StatusListItem
1335
+ media={<StatusAvatar name="Arjun Das" tone="primary" />}
1336
+ title="Arjun Das"
1337
+ description="Electrician"
1338
+ status="Active"
1339
+ statusVariant="text"
1340
+ tone="success"
1341
+ />
1342
+ <StatusListItem
1343
+ media={<StatusAvatar name="Fatima Sheikh" tone="primary" />}
1344
+ title="Fatima Sheikh"
1345
+ description="Safety Officer"
1346
+ status="Active"
1347
+ statusVariant="text"
1348
+ tone="success"
1349
+ />
1350
+ </StatusListGroup>
1351
+ </StatusList>
1352
+ ```
1353
+
1354
+ ### Thumbnail (inline)
1355
+
1356
+ A square image with an icon fallback when no src is provided — for record headers and lists.
1357
+
1358
+ ```tsx
1359
+ function Thumb({ src, alt }: { src?: string; alt: string }) {
1360
+ return (
1361
+ <div className="flex size-14 shrink-0 items-center justify-center overflow-hidden rounded-lg border bg-muted">
1362
+ {src ? (
1363
+ <img src={src} alt={alt} className="size-full object-cover" />
1364
+ ) : (
1365
+ <ImageIcon className="size-6 text-muted-foreground" />
1366
+ )}
1367
+ </div>
1368
+ )
1369
+ }
1370
+ ```
1371
+
1153
1372
  <!-- COMPONENTS:END -->
@@ -0,0 +1,38 @@
1
+ import { Button } from '../ui/button';
2
+ import * as React from "react";
3
+ export type AlertSeverity = "info" | "warning" | "error" | "success";
4
+ export type AlertCardVariant = "filled" | "outline";
5
+ export interface AlertCardProps extends Omit<React.ComponentProps<"div">, "title"> {
6
+ /** Severity — sets the accent color and default icon. */
7
+ severity?: AlertSeverity;
8
+ /**
9
+ * - `filled`: a soft tinted background (compact).
10
+ * - `outline`: a bordered card with an icon box and room for actions.
11
+ */
12
+ variant?: AlertCardVariant;
13
+ /** Override the default severity icon. */
14
+ icon?: React.ReactNode;
15
+ /** Heading. */
16
+ title?: React.ReactNode;
17
+ /** Supporting text. */
18
+ description?: React.ReactNode;
19
+ /** Small badge beside the title (outline variant). */
20
+ badge?: React.ReactNode;
21
+ /** Action buttons rendered below the description (outline variant). */
22
+ actions?: React.ReactNode;
23
+ /** Show a dismiss (×) button. */
24
+ dismissible?: boolean;
25
+ /** Called when the dismiss button is clicked. */
26
+ onDismiss?: () => void;
27
+ }
28
+ /**
29
+ * A higher-level alert with two looks — `filled` (soft tinted background) and
30
+ * `outline` (bordered card with an icon box and actions) — across four
31
+ * severities (info / warning / error / success). Theme-aware: severities map to
32
+ * the blue / orange / red / green tokens.
33
+ */
34
+ export declare function AlertCard({ severity, variant, icon, title, description, badge, actions, dismissible, onDismiss, className, ...props }: AlertCardProps): import("react/jsx-runtime").JSX.Element;
35
+ /** A primary action button tinted to the alert's severity. */
36
+ export declare function AlertCardAction({ severity, className, ...props }: React.ComponentProps<typeof Button> & {
37
+ severity?: AlertSeverity;
38
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import * as React from "react";
2
+ export interface DataCellProps extends React.ComponentProps<"div"> {
3
+ /** Muted caption. */
4
+ label: React.ReactNode;
5
+ /** The value. */
6
+ value: React.ReactNode;
7
+ /**
8
+ * Optional icon (auto-sized, muted). In `stacked` it sits beside the value;
9
+ * in `row` it leads the label.
10
+ */
11
+ icon?: React.ReactNode;
12
+ /**
13
+ * - `stacked` (default): label above value — for spec/detail grids.
14
+ * - `row`: label on the left, value on the right — for definition lists.
15
+ */
16
+ layout?: "stacked" | "row";
17
+ }
18
+ /**
19
+ * A labelled value cell. `stacked` renders the muted `label` above the bold
20
+ * `value` (for spec/detail grids); `row` puts the label on the left and the
21
+ * value on the right (a definition row). Lay several `stacked` cells out in a
22
+ * grid, or several `row` cells in a `divide-y` column.
23
+ */
24
+ export declare function DataCell({ label, value, icon, layout, className, ...props }: DataCellProps): import("react/jsx-runtime").JSX.Element;
@@ -34,11 +34,16 @@ export interface DataTableProps<TRow> {
34
34
  pageSizeOptions?: number[];
35
35
  /** Alternating row backgrounds for easier scanning. */
36
36
  striped?: boolean;
37
- /** Keep the header visible while the body scrolls (pair with maxHeight). */
37
+ /** Keep the header visible while the body scrolls (pair with maxHeight/fillHeight). */
38
38
  stickyHeader?: boolean;
39
39
  /** Constrains height and enables vertical scroll, e.g. "24rem" or 400. */
40
40
  maxHeight?: string | number;
41
+ /**
42
+ * Grow the table to fill its parent's height (body scrolls, footer pinned).
43
+ * Place inside a flex column with a constrained height. Overrides `maxHeight`.
44
+ */
45
+ fillHeight?: boolean;
41
46
  onRowClick?: (row: TRow) => void;
42
47
  className?: string;
43
48
  }
44
- export declare function DataTable<TRow>({ columns, data, getRowId, selectable, selectedIds, onSelectionChange, rowActions, loading, emptyMessage, pagination, pageSize: pageSizeProp, pageSizeOptions, striped, stickyHeader, maxHeight, onRowClick, className, }: DataTableProps<TRow>): import("react/jsx-runtime").JSX.Element;
49
+ export declare function DataTable<TRow>({ columns, data, getRowId, selectable, selectedIds, onSelectionChange, rowActions, loading, emptyMessage, pagination, pageSize: pageSizeProp, pageSizeOptions, striped, stickyHeader, maxHeight, fillHeight, onRowClick, className, }: DataTableProps<TRow>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { Empty } from '../ui/empty';
2
+ import * as React from "react";
3
+ export interface EmptyStateProps extends Omit<React.ComponentProps<typeof Empty>, "title"> {
4
+ /** Leading icon (or any node). Defaults to an inbox icon. */
5
+ icon?: React.ReactNode;
6
+ /** Media style: `icon` wraps it in a muted square; `default` for avatars. */
7
+ mediaVariant?: "icon" | "default";
8
+ /** Heading. Defaults to "No data". */
9
+ title?: React.ReactNode;
10
+ /** Supporting text. */
11
+ description?: React.ReactNode;
12
+ /** Actions (buttons, links, inputs) rendered below. */
13
+ actions?: React.ReactNode;
14
+ }
15
+ /**
16
+ * A convenience wrapper over the compositional `Empty` primitive — pass
17
+ * `icon`, `title`, `description`, and `actions` as props (with sensible
18
+ * defaults) instead of composing the parts by hand. Drop the props you don't
19
+ * need; use the `Empty*` parts directly when you need full control.
20
+ */
21
+ export declare function EmptyState({ icon, mediaVariant, title, description, actions, ...props }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ export interface NotFoundProps extends Omit<React.ComponentProps<"div">, "title"> {
3
+ /** Big status code or glyph, e.g. "404". Pass an icon node for empty states. */
4
+ code?: React.ReactNode;
5
+ /** Heading. Defaults to "Page Not Found". */
6
+ title?: React.ReactNode;
7
+ /** Supporting text under the title. */
8
+ description?: React.ReactNode;
9
+ /** Show the "Go Back" button (calls `onGoBack`, or history.back()). */
10
+ showBack?: boolean;
11
+ /** Override the back-button handler. Defaults to `history.back()`. */
12
+ onGoBack?: () => void;
13
+ /** Href for the "Go to Home" button. Set `null` to hide it. */
14
+ homeHref?: string | null;
15
+ /** Label for the home button. */
16
+ homeLabel?: React.ReactNode;
17
+ /** Extra actions rendered after the default buttons. */
18
+ actions?: React.ReactNode;
19
+ }
20
+ /**
21
+ * A centered status / not-found screen: a large `code` (e.g. "404"), a `title`,
22
+ * a `description`, and action buttons (Go Back + Go to Home). Generic enough for
23
+ * 404 / 403 / 500 and empty states — pass an icon as `code` for the latter.
24
+ */
25
+ export declare function NotFound({ code, title, description, showBack, onGoBack, homeHref, homeLabel, actions, className, ...props }: NotFoundProps): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  declare const cardVariants: (props?: ({
4
- variant?: "default" | "alt" | "primary" | "success" | "warning" | "danger" | null | undefined;
4
+ variant?: "default" | "alt" | "warning" | "success" | "primary" | "danger" | null | undefined;
5
5
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
6
  declare function Card({ className, size, variant, ...props }: React.ComponentProps<"div"> & {
7
7
  size?: "default" | "sm";
@@ -0,0 +1,12 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from "react";
3
+ declare function Empty({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
4
+ declare function EmptyHeader({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
5
+ declare const emptyMediaVariants: (props?: ({
6
+ variant?: "default" | "icon" | null | undefined;
7
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
8
+ declare function EmptyMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>): import("react/jsx-runtime").JSX.Element;
9
+ declare function EmptyTitle({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
10
+ declare function EmptyDescription({ className, ...props }: React.ComponentProps<"p">): import("react/jsx-runtime").JSX.Element;
11
+ declare function EmptyContent({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
12
+ export { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent, };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { cn } from './lib/utils';
2
2
  export { useFileUpload, formatBytes, type FileMetadata, type FileWithPreview, type FileUploadOptions, type FileUploadState, type FileUploadActions, } from './lib/use-file-upload';
3
3
  export * from './components/custom/actions-menu';
4
4
  export * from './components/custom/advanced-input';
5
+ export * from './components/custom/alert-card';
5
6
  export * from './components/custom/file-upload';
6
7
  export * from './components/custom/advanced-select';
7
8
  export * from './components/custom/data-table';
@@ -9,9 +10,12 @@ export * from './components/custom/form-dialog';
9
10
  export * from './components/custom/card-radio-group';
10
11
  export * from './components/custom/confirm-prompt';
11
12
  export * from './components/custom/custom-tabs';
13
+ export * from './components/custom/data-cell';
12
14
  export * from './components/custom/def-row';
15
+ export * from './components/custom/empty-state';
13
16
  export * from './components/custom/faceted-filter';
14
17
  export * from './components/custom/list-card';
18
+ export * from './components/custom/not-found';
15
19
  export * from './components/custom/quick-stat';
16
20
  export * from './components/custom/sensor-card';
17
21
  export * from './components/custom/side-sheet';
@@ -31,6 +35,7 @@ export * from './components/ui/checkbox';
31
35
  export * from './components/ui/command';
32
36
  export * from './components/ui/dialog';
33
37
  export * from './components/ui/dropdown-menu';
38
+ export * from './components/ui/empty';
34
39
  export * from './components/ui/field';
35
40
  export * from './components/ui/hover-card';
36
41
  export * from './components/ui/input';