@l3mpire/ui 3.5.1 → 4.0.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 CHANGED
@@ -156,13 +156,15 @@ icon-spin classes are the load-bearing ones; the rest are decorative.
156
156
 
157
157
  | Class | Usage |
158
158
  |---|---|
159
- | `bg-ai-gradient` | Brand AI gradient (blue → violet → indigo, 125deg) |
159
+ | `bg-ai-gradient` | Decorative brand AI gradient (blue → violet → indigo, 125deg) |
160
+ | `bg-ai-subtle` / `-hover` / `-pressed` | Translucent AI wash (ghost AI surfaces) |
161
+ | `bg-ai-strong` / `-hover` / `-pressed` | Vivid AI gradient (solid AI fill) |
162
+ | `ai-grad-text` | Gradient-clipped text/icons (outlined/ghost AI); follows `[data-ai-text]` host hover/pressed |
160
163
  | `ai-shimmer-text` | Text with a tertiary → info → tertiary sweep (2.1s) |
161
164
  | `ai-icon-spin` | Wrapper that rotates its child icon (see FA Kit caveat below) |
162
165
  | `ai-skeleton` | Surface skeleton with a horizontal sheen sweep |
163
166
  | `ai-cell-reveal` | One-shot blur(3px) → clear, 320ms fade-in for cells |
164
167
  | `ai-pulse` | Breathing scale + opacity for dot indicators |
165
- | `ai-gradient-text` | Flat info-blue accent for AI labels |
166
168
  | `ai-orb` | Decorative gradient disc with a soft glow |
167
169
  | `ai-halo` | Conic-gradient halo that rotates around an orb |
168
170
  | `ai-ring` | Pulsing concentric ring |
@@ -236,12 +238,19 @@ import { faPaperPlaneOutline } from "@l3mpire/icons";
236
238
  <Button appearance="solid" intent="brand" size="md" badge={99}>
237
239
  Notifications
238
240
  </Button>
241
+
242
+ {/* AI intent — brand→violet gradient. Solid = vivid fill + white label;
243
+ outlined/ghost = gradient-clipped label & icons. No disabled-specific
244
+ art (falls back to the appearance's disabled style). */}
245
+ <Button appearance="solid" intent="ai" leftIcon={faStarsOutline}>Ask AI</Button>
246
+ <Button appearance="outlined" intent="ai" leftIcon={faStarsOutline}>Ask AI</Button>
247
+ <Button appearance="ghost" intent="ai" leftIcon={faStarsOutline}>Ask AI</Button>
239
248
  ```
240
249
 
241
250
  | Prop | Values |
242
251
  |---|---|
243
252
  | `appearance` | `"solid"`, `"outlined"`, `"ghost"` |
244
- | `intent` | `"brand"`, `"alert"` |
253
+ | `intent` | `"brand"`, `"alert"`, `"ai"` |
245
254
  | `size` | `"sm"` (24px), `"md"` (32px, radius 10px), `"lg"` (40px, radius 12px) |
246
255
  | `leftIcon` | `IconDefinition` |
247
256
  | `rightIcon` | `IconDefinition` |
@@ -267,13 +276,18 @@ import { faStarOutline } from "@l3mpire/icons";
267
276
  <Badge tone="indigo">SaaS</Badge>
268
277
  <Badge variant="light" tone="amber">Manufacturing</Badge>
269
278
  <Badge variant="outlined" tone="emerald">Finance</Badge>
279
+
280
+ // AI tone — gradient surface (solid = vivid fill + white; light/outlined = gradient-clipped content).
281
+ // Pure variant: pass your own icon + label.
282
+ <Badge tone="ai" icon={faStarsOutline}>AI</Badge>
283
+ <Badge variant="light" tone="ai" icon={faStarsOutline}>Enriched</Badge>
270
284
  ```
271
285
 
272
286
  | Prop | Values |
273
287
  |---|---|
274
288
  | `variant` | `"solid"`, `"light"`, `"outlined"` |
275
289
  | `type` | `"primary"`, `"success"`, `"critical"`, `"warning"`, `"neutral"` |
276
- | `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"`, `"teal"`, `"sky"`, `"purple"`, `"pink"` — categorical palette; combines with `variant`, overrides `type` |
290
+ | `tone` | `"indigo"`, `"rose"`, `"lime"`, `"violet"`, `"cyan"`, `"orange"`, `"emerald"`, `"fuchsia"`, `"amber"`, `"slate"`, `"teal"`, `"sky"`, `"purple"`, `"pink"`, `"ai"` — categorical/AI palette; combines with `variant`, overrides `type`. `"ai"` uses the shared AI gradient surfaces. |
277
291
  | `size` | `"sm"`, `"md"`, `"lg"` |
278
292
  | `icon` | `IconDefinition` (optional) |
279
293
 
@@ -1130,6 +1144,56 @@ import {
1130
1144
 
1131
1145
  ---
1132
1146
 
1147
+ ### Discreet (inline fields)
1148
+
1149
+ The "discreet" inline-edit pattern: a value reads as plain text at rest, a content-hugging pill +
1150
+ affordance reveal it's editable on hover, and a right-sized overlay opens **in place with zero
1151
+ layout shift** on click. Built on the composable `InlineEdit` engine; each `Discreet*` wrapper
1152
+ **reuses the matching existing component** as its editor (existing components are untouched).
1153
+
1154
+ ```tsx
1155
+ import {
1156
+ DiscreetTextInput, DiscreetLink, DiscreetNumberInput, DiscreetTextarea,
1157
+ DiscreetChipInput, DiscreetSelect, DiscreetOwner, DiscreetTags,
1158
+ DiscreetDate, DiscreetSwitch, InlineEdit,
1159
+ } from "@l3mpire/ui";
1160
+
1161
+ // Controlled: pass `value`, commit in `onCommit` (return a Promise → saving spinner).
1162
+ <DiscreetTextInput label="Job title" value={title} onCommit={setTitle} />
1163
+ <DiscreetSelect label="Status" options={statusOptions} value={status} onCommit={setStatus} />
1164
+ <DiscreetDate label="Follow-up" value={iso} onCommit={setIso} />
1165
+
1166
+ // Build a discreet field for any control with the engine directly:
1167
+ <InlineEdit
1168
+ label="Custom"
1169
+ display={<span>{value}</span>}
1170
+ editView={({ commit, cancel }) => <MyEditor onDone={(v) => { save(v); commit(); }} />}
1171
+ />
1172
+ ```
1173
+
1174
+ Shared axis props (all `Discreet*`): `label`, `labelType` (`default`/`optional`/`mandatory`/
1175
+ `info`, via `InputLabel`), `labelLayout` (`inline` \| `stacked` \| `none`), `reveal` (`subtle` \|
1176
+ `pen` \| `outline`), `edit` (`inplace` \| `bordered`), `size` (`sm` = 32px default \| `md` =
1177
+ 40px), `placeholder`, `readOnly`, `error`, `errorMessage`. Each also takes `value` + `onCommit`.
1178
+
1179
+ | Component | Value type | Editor (reused) |
1180
+ |---|---|---|
1181
+ | `DiscreetTextInput` | `string` (`type`: text/tel) | borderless input |
1182
+ | `DiscreetLink` | `string` (URL) | input; value stays clickable |
1183
+ | `DiscreetNumberInput` | `number \| ""` | borderless numeric input (`prefix`) |
1184
+ | `DiscreetTextarea` | `string` | borderless textarea (⌘+Enter saves) |
1185
+ | `DiscreetChipInput` | `string[]` | chip input + inline `validate` |
1186
+ | `DiscreetSelect` | `string` (`options`) | `DropdownMenu` + colour dot |
1187
+ | `DiscreetOwner` | `string` (`options`) | `DropdownMenu` + `Avatar` |
1188
+ | `DiscreetTags` | `string[]` (`options`) | `DropdownMenu` + `Checkbox` (multi) |
1189
+ | `DiscreetDate` | ISO `YYYY-MM-DD` | `DatePicker` calendar |
1190
+ | `DiscreetSwitch` | `boolean` | `Switch` — commits on click |
1191
+
1192
+ Tokens: `comp.inlineField.*` (pill, value, overlay, menu, affordance, accent, error) →
1193
+ `--color-inline-field-*`.
1194
+
1195
+ ---
1196
+
1133
1197
  ### FilterSystem
1134
1198
 
1135
1199
  Composable filter system with inline chips, sort, property selector, and advanced filter popover.
@@ -1557,11 +1621,24 @@ const columns: ColumnDef<Item>[] = [
1557
1621
  enableDrag: true, // Draggable (requires enableColumnDrag)
1558
1622
  filterType: "string", // Filter popover type: "string" | "number" | "date" | "select"
1559
1623
  filterOptions: ["A", "B"], // Options for "select" filter type
1624
+ onRunColumn: () => runAi(), // AI columns: reveals a hover "run on all rows" Play button
1625
+ runColumnLabel: "Run on all rows", // tooltip/aria-label for that button
1560
1626
  },
1561
1627
  },
1562
1628
  ];
1563
1629
  ```
1564
1630
 
1631
+ For an AI column, pair `meta.onRunColumn` (the header run button) with an `AICell` renderer and a `<Badge tone="ai">` header marker:
1632
+
1633
+ ```tsx
1634
+ {
1635
+ id: "summary",
1636
+ header: () => <span className="inline-flex items-center gap-xs">Summary <Badge tone="ai" size="sm" icon={faStarsOutline}>AI</Badge></span>,
1637
+ cell: ({ row }) => <AICell state={row.original.aiState} seed={row.id} />,
1638
+ meta: { onRunColumn: () => runAi() },
1639
+ }
1640
+ ```
1641
+
1565
1642
  #### Manage Table (Column Visibility Modal)
1566
1643
 
1567
1644
  Set `enableTableSettings` to render a sticky-right "Manage table" button in the header row. The button is hidden by default and reveals on header-row hover. Clicking it opens a modal with a search input and a checkbox per column. Locked columns (those with `enableHiding: false`, plus any column with id `select`) are filtered out.
@@ -1607,7 +1684,7 @@ Pre-built cell components for common patterns:
1607
1684
  ```tsx
1608
1685
  import {
1609
1686
  AvatarCell, StatusCell, NumberCell, DateCell,
1610
- EmailCell, LinkCell, ButtonCell, EditableCell, RowActions,
1687
+ EmailCell, LinkCell, ButtonCell, EditableCell, RowActions, AICell,
1611
1688
  } from "@l3mpire/ui";
1612
1689
 
1613
1690
  // Row cells are a fixed 40px tall; headers 32px; both with 12px horizontal padding.
@@ -1622,6 +1699,16 @@ import {
1622
1699
  { cell: ({ row }) => <RowActions actions={[{ label: "Edit", onClick: () => {} }]} /> }
1623
1700
  ```
1624
1701
 
1702
+ `AICell` renders an asynchronous AI result through one stable shell across four states — `{ status: "pending" }`, `{ status: "running" }`, `{ status: "done"; value; citations? }`, `{ status: "error"; message }`. Pass a stable `seed` so the running verb stays consistent across re-renders. Helpers `AI_RUNNING_VERBS` / `pickRunningVerb(seed)` back the running label.
1703
+
1704
+ ```tsx
1705
+ import { AICell, type AICellState } from "@l3mpire/ui";
1706
+
1707
+ <AICell state={{ status: "running" }} seed={row.id} />
1708
+ <AICell state={{ status: "done", value: "B2B SaaS", citations: ["crunchbase"] }} seed={row.id} />
1709
+ <AICell state={{ status: "error", message: "Rate limited" }} />
1710
+ ```
1711
+
1625
1712
  ---
1626
1713
 
1627
1714
  ### EntityCell
@@ -1906,124 +1993,6 @@ Side panel to build a weighted Score column: add rules (field + operator + value
1906
1993
 
1907
1994
  ---
1908
1995
 
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
-
2027
1996
  ### EmptyState
2028
1997
 
2029
1998
  ```tsx