@l3mpire/ui 3.6.0 → 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
@@ -276,13 +276,18 @@ import { faStarOutline } from "@l3mpire/icons";
276
276
  <Badge tone="indigo">SaaS</Badge>
277
277
  <Badge variant="light" tone="amber">Manufacturing</Badge>
278
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>
279
284
  ```
280
285
 
281
286
  | Prop | Values |
282
287
  |---|---|
283
288
  | `variant` | `"solid"`, `"light"`, `"outlined"` |
284
289
  | `type` | `"primary"`, `"success"`, `"critical"`, `"warning"`, `"neutral"` |
285
- | `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. |
286
291
  | `size` | `"sm"`, `"md"`, `"lg"` |
287
292
  | `icon` | `IconDefinition` (optional) |
288
293
 
@@ -1139,6 +1144,56 @@ import {
1139
1144
 
1140
1145
  ---
1141
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
+
1142
1197
  ### FilterSystem
1143
1198
 
1144
1199
  Composable filter system with inline chips, sort, property selector, and advanced filter popover.
@@ -1566,11 +1621,24 @@ const columns: ColumnDef<Item>[] = [
1566
1621
  enableDrag: true, // Draggable (requires enableColumnDrag)
1567
1622
  filterType: "string", // Filter popover type: "string" | "number" | "date" | "select"
1568
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
1569
1626
  },
1570
1627
  },
1571
1628
  ];
1572
1629
  ```
1573
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
+
1574
1642
  #### Manage Table (Column Visibility Modal)
1575
1643
 
1576
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.
@@ -1616,7 +1684,7 @@ Pre-built cell components for common patterns:
1616
1684
  ```tsx
1617
1685
  import {
1618
1686
  AvatarCell, StatusCell, NumberCell, DateCell,
1619
- EmailCell, LinkCell, ButtonCell, EditableCell, RowActions,
1687
+ EmailCell, LinkCell, ButtonCell, EditableCell, RowActions, AICell,
1620
1688
  } from "@l3mpire/ui";
1621
1689
 
1622
1690
  // Row cells are a fixed 40px tall; headers 32px; both with 12px horizontal padding.
@@ -1631,6 +1699,16 @@ import {
1631
1699
  { cell: ({ row }) => <RowActions actions={[{ label: "Edit", onClick: () => {} }]} /> }
1632
1700
  ```
1633
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
+
1634
1712
  ---
1635
1713
 
1636
1714
  ### EntityCell
@@ -1915,124 +1993,6 @@ Side panel to build a weighted Score column: add rules (field + operator + value
1915
1993
 
1916
1994
  ---
1917
1995
 
1918
- ### AIBadge
1919
-
1920
- ```tsx
1921
- import { AIBadge } from "@l3mpire/ui";
1922
-
1923
- <AIBadge />
1924
- <AIBadge size="md">Enriched</AIBadge>
1925
- <AIBadge iconHidden>AI</AIBadge>
1926
- ```
1927
-
1928
- 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"`.
1929
-
1930
- | Prop | Values |
1931
- |---|---|
1932
- | `iconHidden` | `boolean` — hide the leading stars icon |
1933
- | `size` | Badge size — `"lg"` (default), `"sm"`, `"md"` |
1934
- | `children` | `React.ReactNode` (default `"AI"`) |
1935
-
1936
- ---
1937
-
1938
- ### AICell
1939
-
1940
- ```tsx
1941
- import { AICell, type AICellState } from "@l3mpire/ui";
1942
-
1943
- const state: AICellState = { status: "done", value: "B2B SaaS", citations: ["crunchbase"] };
1944
-
1945
- <AICell state={state} seed={row.id} />
1946
- <AICell state={{ status: "running" }} seed={row.id} />
1947
- <AICell state={{ status: "error", message: "Rate limited" }} />
1948
- ```
1949
-
1950
- 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).
1951
-
1952
- | Prop | Values |
1953
- |---|---|
1954
- | `state` | `AICellState \| undefined` — `{ status: "pending" }` \| `{ status: "running" }` \| `{ status: "done"; value; citations? }` \| `{ status: "error"; message }` |
1955
- | `seed` | `string` — stable per-cell seed so the running verb is consistent across re-renders |
1956
-
1957
- Helpers: `AI_RUNNING_VERBS` (verb pool) and `pickRunningVerb(seed)` (stable verb pick).
1958
-
1959
- ---
1960
-
1961
- ### AISuggestionDot
1962
-
1963
- ```tsx
1964
- import { AISuggestionDot } from "@l3mpire/ui";
1965
-
1966
- <AISuggestionDot
1967
- reason="LinkedIn lists a newer title."
1968
- from="VP Sales"
1969
- to="Chief Revenue Officer"
1970
- onApply={() => apply()}
1971
- onDismiss={() => dismiss()}
1972
- />
1973
- ```
1974
-
1975
- 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.
1976
-
1977
- | Prop | Values |
1978
- |---|---|
1979
- | `to` | `React.ReactNode` (required) — suggested value |
1980
- | `onApply` | `() => void` (required) |
1981
- | `onDismiss` | `() => void` (required) |
1982
- | `from` | `React.ReactNode` — current value (left of the arrow) |
1983
- | `reason` | `string` — short explanation in the popover |
1984
- | `side` | `"top"`, `"right"`, `"bottom"` (default), `"left"` |
1985
- | `title` / `applyLabel` / `dismissLabel` | localized labels (defaults `"Suggested change"` / `"Apply"` / `"Dismiss"`) |
1986
-
1987
- ---
1988
-
1989
- ### AIColumnHeaderBar
1990
-
1991
- ```tsx
1992
- import { AIColumnHeaderBar } from "@l3mpire/ui";
1993
-
1994
- <AIColumnHeaderBar label="Tech stack" onRun={() => runOnAllRows()} />
1995
- ```
1996
-
1997
- Header bar for an AI column. The Play ("run on all rows") button appears only on header hover.
1998
-
1999
- | Prop | Values |
2000
- |---|---|
2001
- | `label` | `string` (required) |
2002
- | `onRun` | `() => void` — shows the hover-revealed Play button |
2003
- | `runLabel` | `string` — tooltip/aria-label (default `"Run on all rows"`) |
2004
-
2005
- ---
2006
-
2007
- ### AIColumnSidePanel
2008
-
2009
- ```tsx
2010
- import { AIColumnSidePanel, type AIColumnConfig } from "@l3mpire/ui";
2011
-
2012
- <AIColumnSidePanel
2013
- open={open}
2014
- onOpenChange={setOpen}
2015
- onSave={(config) => createAIColumn(config)}
2016
- extrasSlot={(extras, setExtras) => <ModelPicker value={extras} onChange={setExtras} />}
2017
- />
2018
- ```
2019
-
2020
- 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`.
2021
-
2022
- | Prop | Values |
2023
- |---|---|
2024
- | `onSave` | `(config: AIColumnConfig) => void` (required) — `{ name, prompt, outputFormat, extras? }` |
2025
- | `open` / `onOpenChange` | controlled open state |
2026
- | `initialConfig` | `Partial<AIColumnConfig>` |
2027
- | `extrasSlot` | `(extras, setExtras) => React.ReactNode` — render slot for extra controls |
2028
- | `trigger` | `React.ReactNode` — uncontrolled open |
2029
- | `title` | `string` (default `"AI column"`) |
2030
- | `saveLabel` | `string` (default `"Save"`) |
2031
-
2032
- `AIColumnOutputFormat`: `"text" \| "number" \| "boolean" \| "select" \| "date"`.
2033
-
2034
- ---
2035
-
2036
1996
  ### EmptyState
2037
1997
 
2038
1998
  ```tsx