@l3mpire/ui 3.3.0 → 3.5.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/USAGE.md +469 -10
- package/dist/index.d.mts +498 -28
- package/dist/index.d.ts +498 -28
- package/dist/index.js +5674 -3594
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6011 -3909
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/styles/globals.css +241 -1
package/USAGE.md
CHANGED
|
@@ -116,7 +116,7 @@ Works with all Tailwind spacing prefixes: `p-`, `px-`, `py-`, `m-`, `mx-`, `my-`
|
|
|
116
116
|
|
|
117
117
|
**Line heights:** `leading-2xs` (14px), `leading-xs` (16px), `leading-sm` (20px), `leading-base` (24px), `leading-md` (28px), `leading-lg` (32px)
|
|
118
118
|
|
|
119
|
-
**Font weights:** `font-regular` (400), `font-medium` (500), `font-semibold` (600), `font-
|
|
119
|
+
**Font weights:** `font-regular` (400), `font-medium` (500), `font-semibold` (600), `font-solid` (700)
|
|
120
120
|
|
|
121
121
|
### Typography component
|
|
122
122
|
|
|
@@ -129,7 +129,8 @@ import { Typography } from "@l3mpire/ui";
|
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
**Variants:** `h1`, `h2`, `h3`, `lg`, `md`, `sm`, `xs`
|
|
132
|
-
**Weights:** `regular`, `medium`, `
|
|
132
|
+
**Weights:** `regular`, `medium`, `semibold`, `solid`
|
|
133
|
+
Default weight by variant (from Figma text styles): `h1` → `semibold`, `h2`/`h3` → `medium`, body (`lg`/`md`/`sm`/`xs`) → `regular`. Override with the `weight` prop.
|
|
133
134
|
|
|
134
135
|
---
|
|
135
136
|
|
|
@@ -141,6 +142,57 @@ import { Typography } from "@l3mpire/ui";
|
|
|
141
142
|
| `shadow-md` | Cards, dropdowns |
|
|
142
143
|
| `shadow-lg` | Modals, popovers |
|
|
143
144
|
| `shadow-focus-ring` | Focus state ring (3px blue) |
|
|
145
|
+
| `shadow-elevation-sm` | Tight 1px AI cell / chip lift |
|
|
146
|
+
| `shadow-elevation-md` | AI popover / floating panel |
|
|
147
|
+
| `shadow-elevation-lg` | AI hero / standalone card |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## AI Utilities
|
|
152
|
+
|
|
153
|
+
Animation primitives shared by AI cells, AI badges, suggestion dots and any
|
|
154
|
+
surface that should look like it is thinking. The shimmer-text and
|
|
155
|
+
icon-spin classes are the load-bearing ones; the rest are decorative.
|
|
156
|
+
|
|
157
|
+
| Class | Usage |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `bg-ai-gradient` | Brand AI gradient (blue → violet → indigo, 125deg) |
|
|
160
|
+
| `ai-shimmer-text` | Text with a tertiary → info → tertiary sweep (2.1s) |
|
|
161
|
+
| `ai-icon-spin` | Wrapper that rotates its child icon (see FA Kit caveat below) |
|
|
162
|
+
| `ai-skeleton` | Surface skeleton with a horizontal sheen sweep |
|
|
163
|
+
| `ai-cell-reveal` | One-shot blur(3px) → clear, 320ms fade-in for cells |
|
|
164
|
+
| `ai-pulse` | Breathing scale + opacity for dot indicators |
|
|
165
|
+
| `ai-gradient-text` | Flat info-blue accent for AI labels |
|
|
166
|
+
| `ai-orb` | Decorative gradient disc with a soft glow |
|
|
167
|
+
| `ai-halo` | Conic-gradient halo that rotates around an orb |
|
|
168
|
+
| `ai-ring` | Pulsing concentric ring |
|
|
169
|
+
| `animate-fade-up` | Generic entrance (8px translate + fade) |
|
|
170
|
+
| `animate-pop-in` | Generic entrance (0.85 → 1 scale with overshoot) |
|
|
171
|
+
|
|
172
|
+
All animations are disabled under `@media (prefers-reduced-motion: reduce)` —
|
|
173
|
+
the shimmer text falls back to a flat info color so labels stay readable.
|
|
174
|
+
|
|
175
|
+
### Spinning icons / FA Kit rule
|
|
176
|
+
|
|
177
|
+
We load FontAwesome through the Kit script, which swaps every `<i class="fa-…">`
|
|
178
|
+
into an `<svg>` via a MutationObserver. Any subsequent className change on the
|
|
179
|
+
icon re-triggers the swap and **interrupts** any rotation animation applied
|
|
180
|
+
directly to the icon. The symptom: an icon that ticks ~90° and resets in a loop.
|
|
181
|
+
|
|
182
|
+
Always wrap the icon in a span that carries the rotation:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
// ❌ fa-spin on <Icon> is interrupted by the Kit re-swap
|
|
186
|
+
<Icon icon={faSpinnerThirdOutline} className="fa-spin" />
|
|
187
|
+
|
|
188
|
+
// ✅ rotation lives on a stable parent; the icon is left alone
|
|
189
|
+
<span className="ai-icon-spin">
|
|
190
|
+
<Icon icon={faSpinnerThirdOutline} size="xs" />
|
|
191
|
+
</span>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The same applies to any custom rotation animation — never put it on the icon
|
|
195
|
+
className itself.
|
|
144
196
|
|
|
145
197
|
---
|
|
146
198
|
|
|
@@ -221,7 +273,7 @@ import { faStarOutline } from "@l3mpire/icons";
|
|
|
221
273
|
|---|---|
|
|
222
274
|
| `variant` | `"solid"`, `"light"`, `"outlined"` |
|
|
223
275
|
| `type` | `"primary"`, `"success"`, `"critical"`, `"warning"`, `"neutral"` |
|
|
224
|
-
| `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"` — categorical palette; combines with `variant`, overrides `type` |
|
|
276
|
+
| `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"`, `"teal"`, `"sky"`, `"purple"`, `"pink"` — categorical palette; combines with `variant`, overrides `type` |
|
|
225
277
|
| `size` | `"sm"`, `"md"`, `"lg"` |
|
|
226
278
|
| `icon` | `IconDefinition` (optional) |
|
|
227
279
|
|
|
@@ -245,7 +297,7 @@ import { faPaperPlaneOutline } from "@l3mpire/icons";
|
|
|
245
297
|
| Prop | Values |
|
|
246
298
|
|---|---|
|
|
247
299
|
| `variant` | `"brand"`, `"neutral"` |
|
|
248
|
-
| `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"` — categorical palette; overrides `variant` |
|
|
300
|
+
| `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"`, `"teal"`, `"sky"`, `"purple"`, `"pink"` — categorical palette; overrides `variant` |
|
|
249
301
|
| `size` | `"sm"`, `"md"` |
|
|
250
302
|
| `icon` | `IconDefinition` |
|
|
251
303
|
| `onClose` | `() => void` (shows remove button when provided) |
|
|
@@ -746,7 +798,7 @@ import { InfoMessage } from "@l3mpire/ui";
|
|
|
746
798
|
|
|
747
799
|
| Prop | Values |
|
|
748
800
|
|---|---|
|
|
749
|
-
| `type` | `"info"`, `"success"`, `"alert"`, `"warning"`, `"empty"` |
|
|
801
|
+
| `type` | `"info"`, `"success"`, `"alert"`, `"warning"`, `"empty"`, `"ai"` |
|
|
750
802
|
| `title` | `React.ReactNode` (required) |
|
|
751
803
|
| `description` | `React.ReactNode` |
|
|
752
804
|
| `onClose` | `() => void` (shows close button when provided) |
|
|
@@ -904,7 +956,7 @@ import { faRocketOutline } from "@l3mpire/icons";
|
|
|
904
956
|
|
|
905
957
|
Active tabs render with concave bottom corners that fuse into the bar divider (real browser-tab look). Inactive tabs get a hover fill + soft shadow on the inner pill (active tabs keep their bg on hover).
|
|
906
958
|
|
|
907
|
-
The close `×` only appears **on hover** of a non-pinned tab, as an absolutely-positioned overlay with a gradient fade — it never takes layout space (the label slides under the gradient instead of being pushed). Set `pinned` to hide the close button entirely and show a **"Pinned tab"** tooltip on hover.
|
|
959
|
+
The close `×` only appears **on hover** of a non-pinned tab, as an absolutely-positioned overlay with a gradient fade — it never takes layout space (the label slides under the gradient instead of being pushed). Set `pinned` to hide the close button entirely and show a **"Pinned tab"** tooltip on hover. Set `isEditable` (+ `onEdit`) to add a pencil button in the same overlay, to the left of the close `×`.
|
|
908
960
|
|
|
909
961
|
| Prop (BrowserTab) | Values |
|
|
910
962
|
|---|---|
|
|
@@ -920,6 +972,8 @@ The close `×` only appears **on hover** of a non-pinned tab, as an absolutely-p
|
|
|
920
972
|
| `badge` | `string` |
|
|
921
973
|
| `isActive` | `boolean` |
|
|
922
974
|
| `pinned` | `boolean` (no close button, "Pinned tab" tooltip on hover) |
|
|
975
|
+
| `isEditable` | `boolean` (pencil button in hover overlay, left of close) |
|
|
976
|
+
| `onEdit` | `(e) => void` (edit-button click, used with `isEditable`) |
|
|
923
977
|
| `onClose` | `(e) => void` (close `×` appears on hover only; ignored when `pinned`) |
|
|
924
978
|
| `onRename` | `(newLabel: string) => void` (enables dbl-click rename) |
|
|
925
979
|
|
|
@@ -1362,7 +1416,7 @@ import { ProductLogo } from "@l3mpire/ui";
|
|
|
1362
1416
|
|
|
1363
1417
|
### BulkAction
|
|
1364
1418
|
|
|
1365
|
-
Bottom-anchored toolbar that appears when one or more list items are selected. The selection count sits on the **left**, a fully composable **responsive** actions slot in the middle, and a ghost-brand icon-only **close button on the right** (
|
|
1419
|
+
Bottom-anchored toolbar that appears when one or more list items are selected. The selection count sits on the **left**, a fully composable **responsive** actions slot in the middle, and a ghost-brand icon-only **close button on the right** (`clearLabel` shows as a hover tooltip + `aria-label`). Actions that don't fit collapse automatically into a "more" menu.
|
|
1366
1420
|
|
|
1367
1421
|
```tsx
|
|
1368
1422
|
import { BulkAction, type BulkActionItem } from "@l3mpire/ui";
|
|
@@ -1388,9 +1442,10 @@ const actions: BulkActionItem[] = [
|
|
|
1388
1442
|
| `count` | Number of selected items (rendered as `{count} {countLabel}`) |
|
|
1389
1443
|
| `onClear` | Called when the user clicks the right-side close button |
|
|
1390
1444
|
| `countLabel` | Defaults to `"selected"` — override for i18n |
|
|
1391
|
-
| `clearLabel` | Defaults to `"Clear"` —
|
|
1445
|
+
| `clearLabel` | Defaults to `"Clear"` — shown as the close button's hover tooltip + `aria-label` |
|
|
1392
1446
|
| `actions` | `BulkActionItem[]` — items collapse into a "more" menu when they overflow |
|
|
1393
|
-
| `
|
|
1447
|
+
| `position` | `"sticky"` (default), `"static"`, `"floating-top"` — `sticky` pins to the bottom of the scroll container; `static` flows inline; `floating-top` floats a centred pill above a `position: relative` parent (e.g. above a pagination footer) |
|
|
1448
|
+
| `sticky` | **Deprecated** — use `position`. `true` maps to `"sticky"`, `false` to `"static"`; ignored when `position` is set |
|
|
1394
1449
|
|
|
1395
1450
|
**`BulkActionItem` shape:**
|
|
1396
1451
|
|
|
@@ -1477,6 +1532,8 @@ const columns: ColumnDef<Person>[] = [
|
|
|
1477
1532
|
| `lockedColumnIds` | inferred | Column IDs the manage-table modal hides (defaults to `enableHiding: false` columns plus `select`) |
|
|
1478
1533
|
| `tableSettingsTitle` | `"Manage table"` | Override the manage-table modal title |
|
|
1479
1534
|
| `bordered` | `false` | Border-top on header (full-width layouts) |
|
|
1535
|
+
| `scrollContainer` | `"self"` | Set to `"parent"` to drop the internal `overflow-auto` wrapper. Required when sticky column pinning has to compose with a page-level scroll. |
|
|
1536
|
+
| `columnManagerSlot` | — | Slot mounted as a `<th>` at the right end of the header row. Use it to host a custom column manager (see `ColumnManagerPopover`). |
|
|
1480
1537
|
| `emptyState` | — | `ReactNode` shown when `data` is empty |
|
|
1481
1538
|
| `sorting` | — | Controlled sorting state |
|
|
1482
1539
|
| `onSortingChange` | — | Controlled sorting callback |
|
|
@@ -1553,8 +1610,10 @@ import {
|
|
|
1553
1610
|
EmailCell, LinkCell, ButtonCell, EditableCell, RowActions,
|
|
1554
1611
|
} from "@l3mpire/ui";
|
|
1555
1612
|
|
|
1613
|
+
// Row cells are a fixed 40px tall; headers 32px; both with 12px horizontal padding.
|
|
1556
1614
|
// In column definitions:
|
|
1557
|
-
|
|
1615
|
+
// AvatarCell: shape="rounded" (default, people) | "squared" (companies)
|
|
1616
|
+
{ cell: ({ row }) => <AvatarCell name={row.original.name} src={row.original.avatar} shape="squared" /> }
|
|
1558
1617
|
{ cell: ({ row }) => <StatusCell status="active" /> }
|
|
1559
1618
|
{ cell: ({ row }) => <NumberCell value={row.original.amount} /> }
|
|
1560
1619
|
{ cell: ({ row }) => <DateCell value={row.original.date} /> }
|
|
@@ -1565,6 +1624,406 @@ import {
|
|
|
1565
1624
|
|
|
1566
1625
|
---
|
|
1567
1626
|
|
|
1627
|
+
### EntityCell
|
|
1628
|
+
|
|
1629
|
+
```tsx
|
|
1630
|
+
import { EntityCell, Avatar } from "@l3mpire/ui";
|
|
1631
|
+
import { faArrowUpRightFromSquareOutline } from "@l3mpire/icons";
|
|
1632
|
+
|
|
1633
|
+
<EntityCell avatar={<Avatar size="sm" initials="AC" />} name="Acme Corp" subtitle="acme.com" />
|
|
1634
|
+
<EntityCell
|
|
1635
|
+
avatar={<Avatar size="sm" src={logo} />}
|
|
1636
|
+
name="Acme Corp"
|
|
1637
|
+
onNameClick={() => openRecord(id)}
|
|
1638
|
+
hoverCard={<CompanyPreview id={id} />}
|
|
1639
|
+
quickActions={[{ icon: faArrowUpRightFromSquareOutline, label: "Open", onClick: () => {} }]}
|
|
1640
|
+
/>
|
|
1641
|
+
```
|
|
1642
|
+
|
|
1643
|
+
| Prop | Values |
|
|
1644
|
+
|---|---|
|
|
1645
|
+
| `avatar` | `React.ReactNode` (required) — pass an `<Avatar />` or any logo/icon |
|
|
1646
|
+
| `name` | `string` (required) |
|
|
1647
|
+
| `subtitle` | `string` — optional second line |
|
|
1648
|
+
| `badge` | `React.ReactNode` — marker after the name (sync/status indicator) |
|
|
1649
|
+
| `hoverCard` | `React.ReactNode` — opens in a `<HoverCard />` when the name is hovered |
|
|
1650
|
+
| `quickActions` | `RowQuickAction[]` — hover-revealed actions on the right edge |
|
|
1651
|
+
| `onNameClick` | `(e) => void` — makes the name a clickable link; stops propagation |
|
|
1652
|
+
|
|
1653
|
+
---
|
|
1654
|
+
|
|
1655
|
+
### HoverCard
|
|
1656
|
+
|
|
1657
|
+
```tsx
|
|
1658
|
+
import { HoverCard, HoverCardTrigger, HoverCardContent } from "@l3mpire/ui";
|
|
1659
|
+
|
|
1660
|
+
<HoverCard openDelay={350} closeDelay={120}>
|
|
1661
|
+
<HoverCardTrigger asChild><span>Acme Corp</span></HoverCardTrigger>
|
|
1662
|
+
<HoverCardContent side="bottom" align="start">
|
|
1663
|
+
<CompanyPreview id={id} />
|
|
1664
|
+
</HoverCardContent>
|
|
1665
|
+
</HoverCard>
|
|
1666
|
+
```
|
|
1667
|
+
|
|
1668
|
+
Compound component (`HoverCard` / `HoverCardTrigger` / `HoverCardContent`). Hover-intent popover with open/close delays; stays open while the pointer is over the content.
|
|
1669
|
+
|
|
1670
|
+
| Prop (HoverCard) | Values |
|
|
1671
|
+
|---|---|
|
|
1672
|
+
| `openDelay` | `number` ms before opening (default `350`) |
|
|
1673
|
+
| `closeDelay` | `number` ms before closing (default `120`) |
|
|
1674
|
+
| `open` / `onOpenChange` | controlled open state |
|
|
1675
|
+
|
|
1676
|
+
| Prop (HoverCardTrigger) | Values |
|
|
1677
|
+
|---|---|
|
|
1678
|
+
| `asChild` | `boolean` — merge props onto the child |
|
|
1679
|
+
|
|
1680
|
+
`HoverCardContent` accepts Radix Popover Content props (`side`, `align`, `sideOffset` — defaults `"bottom"` / `"start"` / `8`).
|
|
1681
|
+
|
|
1682
|
+
---
|
|
1683
|
+
|
|
1684
|
+
### RowQuickActions
|
|
1685
|
+
|
|
1686
|
+
```tsx
|
|
1687
|
+
import { RowQuickActions } from "@l3mpire/ui";
|
|
1688
|
+
import { faPenOutline, faTrashOutline } from "@l3mpire/icons";
|
|
1689
|
+
|
|
1690
|
+
<RowQuickActions
|
|
1691
|
+
group="co"
|
|
1692
|
+
actions={[
|
|
1693
|
+
{ icon: faPenOutline, label: "Edit", onClick: () => {} },
|
|
1694
|
+
{ icon: faTrashOutline, label: "Delete", onClick: () => {} },
|
|
1695
|
+
]}
|
|
1696
|
+
/>
|
|
1697
|
+
```
|
|
1698
|
+
|
|
1699
|
+
A row of icon-only buttons that fade in on parent-row hover. Each button stops propagation and carries a tooltip from its `label`.
|
|
1700
|
+
|
|
1701
|
+
| Prop | Values |
|
|
1702
|
+
|---|---|
|
|
1703
|
+
| `actions` | `RowQuickAction[]` (required) — `{ icon, label, onClick, href? }` |
|
|
1704
|
+
| `group` | `string` — named hover group to listen to (e.g. `"co"`); defaults to the unnamed `group` |
|
|
1705
|
+
| `size` | `"sm"` (default), `"md"` |
|
|
1706
|
+
|
|
1707
|
+
---
|
|
1708
|
+
|
|
1709
|
+
### StatusPickerCell
|
|
1710
|
+
|
|
1711
|
+
```tsx
|
|
1712
|
+
import { StatusPickerCell, type StatusOption } from "@l3mpire/ui";
|
|
1713
|
+
|
|
1714
|
+
const options: StatusOption[] = [
|
|
1715
|
+
{ id: "new", label: "New", tone: "sky" },
|
|
1716
|
+
{ id: "won", label: "Won", type: "success" },
|
|
1717
|
+
];
|
|
1718
|
+
|
|
1719
|
+
<StatusPickerCell
|
|
1720
|
+
current={options[0]}
|
|
1721
|
+
options={options}
|
|
1722
|
+
onChange={(id) => setStatus(id)}
|
|
1723
|
+
onAddOption={(label) => addStatus(label)}
|
|
1724
|
+
onSync={() => syncCrm()}
|
|
1725
|
+
/>
|
|
1726
|
+
```
|
|
1727
|
+
|
|
1728
|
+
Badge-pill cell that opens a popover to pick, rename, add, or CRM-sync a status. Each `StatusOption` carries optional `variant` / `type` / `tone` to style its `<Badge />`.
|
|
1729
|
+
|
|
1730
|
+
| Prop | Values |
|
|
1731
|
+
|---|---|
|
|
1732
|
+
| `current` | `StatusOption \| null` (required) |
|
|
1733
|
+
| `options` | `StatusOption[]` (required) |
|
|
1734
|
+
| `onChange` | `(id: string) => void` (required) |
|
|
1735
|
+
| `onAddOption` | `(label: string) => void` — adds an "Add status" row |
|
|
1736
|
+
| `onRenameOption` | `(id, label) => void` — adds per-row rename on hover |
|
|
1737
|
+
| `onSync` | `() => void` — adds a "Sync with CRM" row |
|
|
1738
|
+
| `triggerStyle` | `"cell"` (default), `"compact"` |
|
|
1739
|
+
| `placeholder` | `string` (default `"Set status"`) |
|
|
1740
|
+
|
|
1741
|
+
---
|
|
1742
|
+
|
|
1743
|
+
### ScoreBadge
|
|
1744
|
+
|
|
1745
|
+
```tsx
|
|
1746
|
+
import { ScoreBadge } from "@l3mpire/ui";
|
|
1747
|
+
|
|
1748
|
+
<ScoreBadge score={3} matched={2} total={5} />
|
|
1749
|
+
<ScoreBadge score={-1} matched={1} total={4} size="md" />
|
|
1750
|
+
```
|
|
1751
|
+
|
|
1752
|
+
Renders a score-rule result: a colored Badge (positive → success, negative → critical, zero → neutral) plus a `matched/total` counter.
|
|
1753
|
+
|
|
1754
|
+
| Prop | Values |
|
|
1755
|
+
|---|---|
|
|
1756
|
+
| `score` | `number` (required) — signed total |
|
|
1757
|
+
| `matched` | `number` (required) |
|
|
1758
|
+
| `total` | `number` (required) |
|
|
1759
|
+
| `size` | Badge size — `"sm"` (default), `"md"`, `"lg"` |
|
|
1760
|
+
|
|
1761
|
+
---
|
|
1762
|
+
|
|
1763
|
+
### ColumnTypeBadge
|
|
1764
|
+
|
|
1765
|
+
```tsx
|
|
1766
|
+
import { ColumnTypeBadge } from "@l3mpire/ui";
|
|
1767
|
+
|
|
1768
|
+
<ColumnTypeBadge kind="db" />
|
|
1769
|
+
<ColumnTypeBadge kind="field" />
|
|
1770
|
+
<ColumnTypeBadge kind="score" />
|
|
1771
|
+
<ColumnTypeBadge kind="ai" />
|
|
1772
|
+
```
|
|
1773
|
+
|
|
1774
|
+
Small Badge labelling a column's kind: `DB` (neutral), `FIELD` (warning), `SCORE` (success), `AI` (primary).
|
|
1775
|
+
|
|
1776
|
+
| Prop | Values |
|
|
1777
|
+
|---|---|
|
|
1778
|
+
| `kind` | `"db"`, `"field"`, `"score"`, `"ai"` (required) |
|
|
1779
|
+
| `size` | Badge size — `"sm"` (default), `"md"`, `"lg"` |
|
|
1780
|
+
|
|
1781
|
+
---
|
|
1782
|
+
|
|
1783
|
+
### ColumnHeaderMenu
|
|
1784
|
+
|
|
1785
|
+
```tsx
|
|
1786
|
+
import { ColumnHeaderMenu } from "@l3mpire/ui";
|
|
1787
|
+
|
|
1788
|
+
<ColumnHeaderMenu
|
|
1789
|
+
column={column}
|
|
1790
|
+
title="Company"
|
|
1791
|
+
editable={!isBuiltIn}
|
|
1792
|
+
onRename={(name) => renameColumn(name)}
|
|
1793
|
+
onEdit={() => openEditor()}
|
|
1794
|
+
onDuplicate={() => duplicate()}
|
|
1795
|
+
onDelete={() => remove()}
|
|
1796
|
+
>
|
|
1797
|
+
<span>Company</span>
|
|
1798
|
+
</ColumnHeaderMenu>
|
|
1799
|
+
```
|
|
1800
|
+
|
|
1801
|
+
Dropdown attached to a column header: inline rename, sort, pin, hide, and (for editable columns) duplicate / edit / delete. Built-in columns grey the mutation items and surface `builtinReason` as a tooltip.
|
|
1802
|
+
|
|
1803
|
+
| Prop | Values |
|
|
1804
|
+
|---|---|
|
|
1805
|
+
| `column` | `HeaderColumnApi` (required) — TanStack-compatible subset (sort/pin/hide methods) |
|
|
1806
|
+
| `title` | `string` (required) |
|
|
1807
|
+
| `editable` | `boolean` (required) — false greys rename/duplicate/edit/delete |
|
|
1808
|
+
| `onRename` | `(name: string) => void` |
|
|
1809
|
+
| `onEdit` / `onDuplicate` / `onDelete` | `() => void` |
|
|
1810
|
+
| `builtinReason` | `string` — tooltip on greyed items (default `"Built-in columns can't be edited"`) |
|
|
1811
|
+
| `children` | `React.ReactNode` (required) — header content inside the trigger |
|
|
1812
|
+
|
|
1813
|
+
---
|
|
1814
|
+
|
|
1815
|
+
### ColumnManagerPopover
|
|
1816
|
+
|
|
1817
|
+
```tsx
|
|
1818
|
+
import {
|
|
1819
|
+
ColumnManagerPopover,
|
|
1820
|
+
ColumnManagerTrigger,
|
|
1821
|
+
type ColumnManagerItem,
|
|
1822
|
+
} from "@l3mpire/ui";
|
|
1823
|
+
|
|
1824
|
+
const items: ColumnManagerItem[] = [
|
|
1825
|
+
{ id: "name", name: "Company", kind: "db", visible: true },
|
|
1826
|
+
{ id: "score", name: "Fit score", kind: "score", visible: true },
|
|
1827
|
+
];
|
|
1828
|
+
|
|
1829
|
+
<ColumnManagerPopover
|
|
1830
|
+
items={items}
|
|
1831
|
+
trigger={<ColumnManagerTrigger />}
|
|
1832
|
+
onToggleVisible={(id, visible) => setVisible(id, visible)}
|
|
1833
|
+
onDelete={(id) => remove(id)}
|
|
1834
|
+
onAdd={(kind) => createColumn(kind)}
|
|
1835
|
+
/>
|
|
1836
|
+
```
|
|
1837
|
+
|
|
1838
|
+
Popover to search, show/hide, delete, and add columns. When `onAdd` is set it renders three "Add column" cards: Field, Score, AI.
|
|
1839
|
+
|
|
1840
|
+
| Prop | Values |
|
|
1841
|
+
|---|---|
|
|
1842
|
+
| `items` | `ColumnManagerItem[]` (required) — `{ id, name, kind, visible, icon? }` |
|
|
1843
|
+
| `onToggleVisible` | `(id, visible) => void` (required) |
|
|
1844
|
+
| `onDelete` | `(id) => void` — only offered for `kind !== "db"` |
|
|
1845
|
+
| `onAdd` | `(kind: AddColumnKind) => void` — `AddColumnKind` is `"field" \| "score" \| "ai"` |
|
|
1846
|
+
| `trigger` | `React.ReactNode` — e.g. `<ColumnManagerTrigger />` |
|
|
1847
|
+
| `open` / `onOpenChange` | controlled open state |
|
|
1848
|
+
|
|
1849
|
+
---
|
|
1850
|
+
|
|
1851
|
+
### CreateFieldColumnPanel
|
|
1852
|
+
|
|
1853
|
+
```tsx
|
|
1854
|
+
import { CreateFieldColumnPanel } from "@l3mpire/ui";
|
|
1855
|
+
|
|
1856
|
+
<CreateFieldColumnPanel
|
|
1857
|
+
open={open}
|
|
1858
|
+
onOpenChange={setOpen}
|
|
1859
|
+
onSave={(column) => addFieldColumn(column)}
|
|
1860
|
+
/>
|
|
1861
|
+
```
|
|
1862
|
+
|
|
1863
|
+
Side panel to create or edit a user-defined Field column (text / number / date / single select). For `select`, options are entered one per line.
|
|
1864
|
+
|
|
1865
|
+
| Prop | Values |
|
|
1866
|
+
|---|---|
|
|
1867
|
+
| `onSave` | `(column: Omit<FieldColumn, "id" \| "createdAt" \| "kind">) => void` (required) |
|
|
1868
|
+
| `open` / `onOpenChange` | controlled open state |
|
|
1869
|
+
| `initial` | `Partial<Pick<FieldColumn, "name" \| "fieldType" \| "options">>` |
|
|
1870
|
+
| `trigger` | `React.ReactNode` — opens the panel in uncontrolled mode |
|
|
1871
|
+
| `title` | `string` (default `"Create field column"`) |
|
|
1872
|
+
| `saveLabel` | `string` (default `"Create column"`) |
|
|
1873
|
+
|
|
1874
|
+
---
|
|
1875
|
+
|
|
1876
|
+
### CreateScoreColumnPanel
|
|
1877
|
+
|
|
1878
|
+
```tsx
|
|
1879
|
+
import {
|
|
1880
|
+
CreateScoreColumnPanel,
|
|
1881
|
+
type ScorableField,
|
|
1882
|
+
type ScorePreviewRow,
|
|
1883
|
+
} from "@l3mpire/ui";
|
|
1884
|
+
|
|
1885
|
+
<CreateScoreColumnPanel
|
|
1886
|
+
open={open}
|
|
1887
|
+
onOpenChange={setOpen}
|
|
1888
|
+
fields={scorableFields}
|
|
1889
|
+
preview={firstFiveRows}
|
|
1890
|
+
onSave={(column) => addScoreColumn(column)}
|
|
1891
|
+
/>
|
|
1892
|
+
```
|
|
1893
|
+
|
|
1894
|
+
Side panel to build a weighted Score column: add rules (field + operator + value + weight) and see a live preview of the first rows scored via `computeScore`.
|
|
1895
|
+
|
|
1896
|
+
| Prop | Values |
|
|
1897
|
+
|---|---|
|
|
1898
|
+
| `fields` | `ScorableField[]` (required) — `{ id, name, fieldType, options? }` |
|
|
1899
|
+
| `onSave` | `(column: Pick<ScoreColumn, "name" \| "rules">) => void` (required) |
|
|
1900
|
+
| `preview` | `ScorePreviewRow[]` — rows to score in the preview |
|
|
1901
|
+
| `open` / `onOpenChange` | controlled open state |
|
|
1902
|
+
| `initial` | `Partial<Pick<ScoreColumn, "name" \| "rules">>` |
|
|
1903
|
+
| `trigger` | `React.ReactNode` |
|
|
1904
|
+
| `title` | `string` (default `"Score column"`) |
|
|
1905
|
+
| `saveLabel` | `string` (default `"Save"`) |
|
|
1906
|
+
|
|
1907
|
+
---
|
|
1908
|
+
|
|
1909
|
+
### AIBadge
|
|
1910
|
+
|
|
1911
|
+
```tsx
|
|
1912
|
+
import { AIBadge } from "@l3mpire/ui";
|
|
1913
|
+
|
|
1914
|
+
<AIBadge />
|
|
1915
|
+
<AIBadge size="md">Enriched</AIBadge>
|
|
1916
|
+
<AIBadge iconHidden>AI</AIBadge>
|
|
1917
|
+
```
|
|
1918
|
+
|
|
1919
|
+
Marker flagging a value or column as AI-driven. Renders a `<Badge variant="light" type="primary" />` with a leading stars glyph. Children default to `"AI"`.
|
|
1920
|
+
|
|
1921
|
+
| Prop | Values |
|
|
1922
|
+
|---|---|
|
|
1923
|
+
| `iconHidden` | `boolean` — hide the leading stars icon |
|
|
1924
|
+
| `size` | Badge size — `"lg"` (default), `"sm"`, `"md"` |
|
|
1925
|
+
| `children` | `React.ReactNode` (default `"AI"`) |
|
|
1926
|
+
|
|
1927
|
+
---
|
|
1928
|
+
|
|
1929
|
+
### AICell
|
|
1930
|
+
|
|
1931
|
+
```tsx
|
|
1932
|
+
import { AICell, type AICellState } from "@l3mpire/ui";
|
|
1933
|
+
|
|
1934
|
+
const state: AICellState = { status: "done", value: "B2B SaaS", citations: ["crunchbase"] };
|
|
1935
|
+
|
|
1936
|
+
<AICell state={state} seed={row.id} />
|
|
1937
|
+
<AICell state={{ status: "running" }} seed={row.id} />
|
|
1938
|
+
<AICell state={{ status: "error", message: "Rate limited" }} />
|
|
1939
|
+
```
|
|
1940
|
+
|
|
1941
|
+
Renders the four states of an AI-generated cell in one stable shell: `pending` (Queued), `running` (shimmer + spinning verb), `done` (value + optional citation count, tooltip), `error` (red message).
|
|
1942
|
+
|
|
1943
|
+
| Prop | Values |
|
|
1944
|
+
|---|---|
|
|
1945
|
+
| `state` | `AICellState \| undefined` — `{ status: "pending" }` \| `{ status: "running" }` \| `{ status: "done"; value; citations? }` \| `{ status: "error"; message }` |
|
|
1946
|
+
| `seed` | `string` — stable per-cell seed so the running verb is consistent across re-renders |
|
|
1947
|
+
|
|
1948
|
+
Helpers: `AI_RUNNING_VERBS` (verb pool) and `pickRunningVerb(seed)` (stable verb pick).
|
|
1949
|
+
|
|
1950
|
+
---
|
|
1951
|
+
|
|
1952
|
+
### AISuggestionDot
|
|
1953
|
+
|
|
1954
|
+
```tsx
|
|
1955
|
+
import { AISuggestionDot } from "@l3mpire/ui";
|
|
1956
|
+
|
|
1957
|
+
<AISuggestionDot
|
|
1958
|
+
reason="LinkedIn lists a newer title."
|
|
1959
|
+
from="VP Sales"
|
|
1960
|
+
to="Chief Revenue Officer"
|
|
1961
|
+
onApply={() => apply()}
|
|
1962
|
+
onDismiss={() => dismiss()}
|
|
1963
|
+
/>
|
|
1964
|
+
```
|
|
1965
|
+
|
|
1966
|
+
A pulsing dot anchored next to a cell value. Clicking it opens a popover showing the AI's `from → to` suggestion with Apply / Dismiss actions.
|
|
1967
|
+
|
|
1968
|
+
| Prop | Values |
|
|
1969
|
+
|---|---|
|
|
1970
|
+
| `to` | `React.ReactNode` (required) — suggested value |
|
|
1971
|
+
| `onApply` | `() => void` (required) |
|
|
1972
|
+
| `onDismiss` | `() => void` (required) |
|
|
1973
|
+
| `from` | `React.ReactNode` — current value (left of the arrow) |
|
|
1974
|
+
| `reason` | `string` — short explanation in the popover |
|
|
1975
|
+
| `side` | `"top"`, `"right"`, `"bottom"` (default), `"left"` |
|
|
1976
|
+
| `title` / `applyLabel` / `dismissLabel` | localized labels (defaults `"Suggested change"` / `"Apply"` / `"Dismiss"`) |
|
|
1977
|
+
|
|
1978
|
+
---
|
|
1979
|
+
|
|
1980
|
+
### AIColumnHeaderBar
|
|
1981
|
+
|
|
1982
|
+
```tsx
|
|
1983
|
+
import { AIColumnHeaderBar } from "@l3mpire/ui";
|
|
1984
|
+
|
|
1985
|
+
<AIColumnHeaderBar label="Tech stack" onRun={() => runOnAllRows()} />
|
|
1986
|
+
```
|
|
1987
|
+
|
|
1988
|
+
Header bar for an AI column. The Play ("run on all rows") button appears only on header hover.
|
|
1989
|
+
|
|
1990
|
+
| Prop | Values |
|
|
1991
|
+
|---|---|
|
|
1992
|
+
| `label` | `string` (required) |
|
|
1993
|
+
| `onRun` | `() => void` — shows the hover-revealed Play button |
|
|
1994
|
+
| `runLabel` | `string` — tooltip/aria-label (default `"Run on all rows"`) |
|
|
1995
|
+
|
|
1996
|
+
---
|
|
1997
|
+
|
|
1998
|
+
### AIColumnSidePanel
|
|
1999
|
+
|
|
2000
|
+
```tsx
|
|
2001
|
+
import { AIColumnSidePanel, type AIColumnConfig } from "@l3mpire/ui";
|
|
2002
|
+
|
|
2003
|
+
<AIColumnSidePanel
|
|
2004
|
+
open={open}
|
|
2005
|
+
onOpenChange={setOpen}
|
|
2006
|
+
onSave={(config) => createAIColumn(config)}
|
|
2007
|
+
extrasSlot={(extras, setExtras) => <ModelPicker value={extras} onChange={setExtras} />}
|
|
2008
|
+
/>
|
|
2009
|
+
```
|
|
2010
|
+
|
|
2011
|
+
Side panel scaffold to create or edit an AI column: name, prompt, and output format. Product-specific controls (model, sources, timeframe) plug in via `extrasSlot`.
|
|
2012
|
+
|
|
2013
|
+
| Prop | Values |
|
|
2014
|
+
|---|---|
|
|
2015
|
+
| `onSave` | `(config: AIColumnConfig) => void` (required) — `{ name, prompt, outputFormat, extras? }` |
|
|
2016
|
+
| `open` / `onOpenChange` | controlled open state |
|
|
2017
|
+
| `initialConfig` | `Partial<AIColumnConfig>` |
|
|
2018
|
+
| `extrasSlot` | `(extras, setExtras) => React.ReactNode` — render slot for extra controls |
|
|
2019
|
+
| `trigger` | `React.ReactNode` — uncontrolled open |
|
|
2020
|
+
| `title` | `string` (default `"AI column"`) |
|
|
2021
|
+
| `saveLabel` | `string` (default `"Save"`) |
|
|
2022
|
+
|
|
2023
|
+
`AIColumnOutputFormat`: `"text" \| "number" \| "boolean" \| "select" \| "date"`.
|
|
2024
|
+
|
|
2025
|
+
---
|
|
2026
|
+
|
|
1568
2027
|
### EmptyState
|
|
1569
2028
|
|
|
1570
2029
|
```tsx
|