@l3mpire/ui 3.5.0 → 3.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/USAGE.md +12 -3
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +89 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/styles/globals.css +25 -13
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` |
|
|
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` |
|
package/dist/index.d.mts
CHANGED
|
@@ -489,7 +489,7 @@ declare const BrowserTab: React.ForwardRefExoticComponent<BrowserTabProps & Reac
|
|
|
489
489
|
|
|
490
490
|
declare const buttonVariants: (props?: ({
|
|
491
491
|
appearance?: "solid" | "outlined" | "ghost" | null | undefined;
|
|
492
|
-
intent?: "alert" | "brand" | null | undefined;
|
|
492
|
+
intent?: "alert" | "brand" | "ai" | null | undefined;
|
|
493
493
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
494
494
|
iconOnly?: boolean | null | undefined;
|
|
495
495
|
fullWidth?: boolean | null | undefined;
|
|
@@ -652,7 +652,7 @@ interface InputLabelProps extends React.ComponentPropsWithoutRef<typeof LabelPri
|
|
|
652
652
|
declare const InputLabel: React.ForwardRefExoticComponent<InputLabelProps & React.RefAttributes<HTMLLabelElement>>;
|
|
653
653
|
|
|
654
654
|
declare const infoMessageVariants: (props?: ({
|
|
655
|
-
type?: "alert" | "success" | "warning" | "
|
|
655
|
+
type?: "alert" | "success" | "warning" | "ai" | "info" | "empty" | null | undefined;
|
|
656
656
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
657
657
|
interface InfoMessageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof infoMessageVariants> {
|
|
658
658
|
title: React.ReactNode;
|
package/dist/index.d.ts
CHANGED
|
@@ -489,7 +489,7 @@ declare const BrowserTab: React.ForwardRefExoticComponent<BrowserTabProps & Reac
|
|
|
489
489
|
|
|
490
490
|
declare const buttonVariants: (props?: ({
|
|
491
491
|
appearance?: "solid" | "outlined" | "ghost" | null | undefined;
|
|
492
|
-
intent?: "alert" | "brand" | null | undefined;
|
|
492
|
+
intent?: "alert" | "brand" | "ai" | null | undefined;
|
|
493
493
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
494
494
|
iconOnly?: boolean | null | undefined;
|
|
495
495
|
fullWidth?: boolean | null | undefined;
|
|
@@ -652,7 +652,7 @@ interface InputLabelProps extends React.ComponentPropsWithoutRef<typeof LabelPri
|
|
|
652
652
|
declare const InputLabel: React.ForwardRefExoticComponent<InputLabelProps & React.RefAttributes<HTMLLabelElement>>;
|
|
653
653
|
|
|
654
654
|
declare const infoMessageVariants: (props?: ({
|
|
655
|
-
type?: "alert" | "success" | "warning" | "
|
|
655
|
+
type?: "alert" | "success" | "warning" | "ai" | "info" | "empty" | null | undefined;
|
|
656
656
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
657
657
|
interface InfoMessageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof infoMessageVariants> {
|
|
658
658
|
title: React.ReactNode;
|
package/dist/index.js
CHANGED
|
@@ -700,7 +700,8 @@ var buttonVariants = (0, import_class_variance_authority3.cva)(
|
|
|
700
700
|
},
|
|
701
701
|
intent: {
|
|
702
702
|
brand: [],
|
|
703
|
-
alert: []
|
|
703
|
+
alert: [],
|
|
704
|
+
ai: []
|
|
704
705
|
},
|
|
705
706
|
size: {
|
|
706
707
|
sm: [
|
|
@@ -822,6 +823,48 @@ var buttonVariants = (0, import_class_variance_authority3.cva)(
|
|
|
822
823
|
"active:text-btn-ghost-alert-text-pressed"
|
|
823
824
|
]
|
|
824
825
|
},
|
|
826
|
+
// ── Solid + AI ─────────────────────────────────────────────────────
|
|
827
|
+
// Vivid brand→violet gradient fill, white label/icons, violet outer
|
|
828
|
+
// border + a translucent-white inner border (via inset shadow).
|
|
829
|
+
{
|
|
830
|
+
appearance: "solid",
|
|
831
|
+
intent: "ai",
|
|
832
|
+
class: [
|
|
833
|
+
"bg-ai-strong",
|
|
834
|
+
"text-[var(--core-text-main-invert-primary)]",
|
|
835
|
+
"border-[var(--violet-500)]",
|
|
836
|
+
"shadow-[inset_0_0_0_1px_rgb(255_255_255/0.6),0_1px_3px_0_var(--shadow-4)]",
|
|
837
|
+
"hover:bg-ai-strong-hover",
|
|
838
|
+
"active:bg-ai-strong-pressed"
|
|
839
|
+
]
|
|
840
|
+
},
|
|
841
|
+
// ── Outlined + AI ──────────────────────────────────────────────────
|
|
842
|
+
// Neutral surface (same as outlined brand), brand-blue border that
|
|
843
|
+
// deepens per state; label/icons are gradient-clipped (see component).
|
|
844
|
+
{
|
|
845
|
+
appearance: "outlined",
|
|
846
|
+
intent: "ai",
|
|
847
|
+
class: [
|
|
848
|
+
"bg-gradient-to-t from-btn-outlined-neutral-bg-default from-[10%] to-btn-outlined-neutral-bg-gradient-to-default",
|
|
849
|
+
"border-[var(--interactive-bg-primary-dark-default)]",
|
|
850
|
+
"shadow-[0_1px_3px_0_var(--shadow-4)]",
|
|
851
|
+
"hover:from-btn-outlined-neutral-bg-hover hover:from-[0%] hover:to-btn-outlined-neutral-bg-gradient-to-hover",
|
|
852
|
+
"hover:border-[var(--interactive-bg-primary-dark-hover)]",
|
|
853
|
+
"active:from-btn-outlined-neutral-bg-pressed active:to-btn-outlined-neutral-bg-gradient-to-pressed",
|
|
854
|
+
"active:border-[var(--interactive-bg-primary-dark-pressed)]"
|
|
855
|
+
]
|
|
856
|
+
},
|
|
857
|
+
// ── Ghost + AI ─────────────────────────────────────────────────────
|
|
858
|
+
// Subtle translucent gradient wash, no border; gradient-clipped text.
|
|
859
|
+
{
|
|
860
|
+
appearance: "ghost",
|
|
861
|
+
intent: "ai",
|
|
862
|
+
class: [
|
|
863
|
+
"bg-ai-subtle border-transparent",
|
|
864
|
+
"hover:bg-ai-subtle-hover",
|
|
865
|
+
"active:bg-ai-subtle-pressed"
|
|
866
|
+
]
|
|
867
|
+
},
|
|
825
868
|
// ── Icon-only size overrides ───────────────────────────────────────
|
|
826
869
|
{ size: "sm", iconOnly: true, class: "w-6 min-w-0 px-0" },
|
|
827
870
|
{ size: "md", iconOnly: true, class: "w-8 min-w-0 px-0" },
|
|
@@ -884,6 +927,8 @@ var Button = React6.forwardRef(
|
|
|
884
927
|
const isDisabled = disabled || loading;
|
|
885
928
|
const isIconOnly = iconOnlyProp ?? !children;
|
|
886
929
|
const iconSize = iconSizeMap[resolvedSize];
|
|
930
|
+
const aiGradientText = intent === "ai" && appearance !== "solid" && !isDisabled;
|
|
931
|
+
const aiTextClass = aiGradientText ? "ai-grad-text" : void 0;
|
|
887
932
|
const variantClasses = buttonVariants({
|
|
888
933
|
appearance,
|
|
889
934
|
intent,
|
|
@@ -893,7 +938,7 @@ var Button = React6.forwardRef(
|
|
|
893
938
|
className
|
|
894
939
|
});
|
|
895
940
|
const labelNode = !isIconOnly ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: textWrapperClass(resolvedSize), children: [
|
|
896
|
-
children,
|
|
941
|
+
aiGradientText ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: aiTextClass, children }) : children,
|
|
897
942
|
badge != null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ButtonBadge, { size: resolvedSize, intent, children: badge })
|
|
898
943
|
] }) : null;
|
|
899
944
|
if (asChild) {
|
|
@@ -906,11 +951,12 @@ var Button = React6.forwardRef(
|
|
|
906
951
|
className: cn(variantClasses),
|
|
907
952
|
disabled: isDisabled,
|
|
908
953
|
"aria-busy": loading || void 0,
|
|
954
|
+
"data-ai-text": aiGradientText || void 0,
|
|
909
955
|
...props,
|
|
910
956
|
children: [
|
|
911
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: import_icons5.faSpinnerSolid, size: iconSize, className: "animate-spin" }) : leftIcon ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: leftIcon, size: iconSize }) : null,
|
|
957
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: import_icons5.faSpinnerSolid, size: iconSize, className: "animate-spin" }) : leftIcon ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: leftIcon, size: iconSize, className: aiTextClass }) : null,
|
|
912
958
|
labelNode,
|
|
913
|
-
rightIcon && !loading && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: rightIcon, size: iconSize })
|
|
959
|
+
rightIcon && !loading && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.Icon, { icon: rightIcon, size: iconSize, className: aiTextClass })
|
|
914
960
|
]
|
|
915
961
|
}
|
|
916
962
|
);
|
|
@@ -7268,6 +7314,18 @@ function ColumnFilterPopover({
|
|
|
7268
7314
|
) })
|
|
7269
7315
|
] });
|
|
7270
7316
|
}
|
|
7317
|
+
function pinnedStickyStyle(pinned, offset, zIndex) {
|
|
7318
|
+
if (pinned === "left") return { position: "sticky", left: offset, zIndex };
|
|
7319
|
+
if (pinned === "right") return { position: "sticky", right: offset, zIndex };
|
|
7320
|
+
return {};
|
|
7321
|
+
}
|
|
7322
|
+
function pinnedDividerClass(pinned) {
|
|
7323
|
+
if (pinned === "left")
|
|
7324
|
+
return "shadow-[1px_0_0_0_var(--core-border-main-primary)]";
|
|
7325
|
+
if (pinned === "right")
|
|
7326
|
+
return "shadow-[-1px_0_0_0_var(--core-border-main-primary)]";
|
|
7327
|
+
return "";
|
|
7328
|
+
}
|
|
7271
7329
|
function DraggableHeaderCell({
|
|
7272
7330
|
header,
|
|
7273
7331
|
enableSorting,
|
|
@@ -7295,6 +7353,7 @@ function DraggableHeaderCell({
|
|
|
7295
7353
|
disabled: !canDrag
|
|
7296
7354
|
});
|
|
7297
7355
|
const pinned = header.column.getIsPinned();
|
|
7356
|
+
const pinOffset = pinned === "left" ? header.column.getStart("left") : pinned === "right" ? header.column.getAfter("right") : void 0;
|
|
7298
7357
|
const style = {
|
|
7299
7358
|
width: enableColumnResizing ? header.getSize() : void 0,
|
|
7300
7359
|
minWidth: enableColumnResizing ? header.column.columnDef.minSize : void 0,
|
|
@@ -7305,18 +7364,7 @@ function DraggableHeaderCell({
|
|
|
7305
7364
|
// Pinning sticky positioning — must override the default `relative` we
|
|
7306
7365
|
// also use for the resize handle. The resize handle is still absolutely
|
|
7307
7366
|
// positioned because it references `right: 0` relative to the cell.
|
|
7308
|
-
...pinned
|
|
7309
|
-
position: "sticky",
|
|
7310
|
-
left: header.column.getStart("left"),
|
|
7311
|
-
zIndex: isDragging ? 5 : 3
|
|
7312
|
-
} : pinned === "right" ? {
|
|
7313
|
-
position: "sticky",
|
|
7314
|
-
right: header.column.getAfter("right"),
|
|
7315
|
-
zIndex: isDragging ? 5 : 3
|
|
7316
|
-
} : {
|
|
7317
|
-
position: "relative",
|
|
7318
|
-
zIndex: isDragging ? 1 : void 0
|
|
7319
|
-
}
|
|
7367
|
+
...pinned ? pinnedStickyStyle(pinned, pinOffset, isDragging ? 5 : 3) : { position: "relative", zIndex: isDragging ? 1 : void 0 }
|
|
7320
7368
|
};
|
|
7321
7369
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
7322
7370
|
TableHead,
|
|
@@ -7330,8 +7378,7 @@ function DraggableHeaderCell({
|
|
|
7330
7378
|
// Pinned columns keep their bg so the scrolling content can pass
|
|
7331
7379
|
// under them. The default `bg-table-head-bg-default` is already on
|
|
7332
7380
|
// <th> so we only need to add a divider on the boundary.
|
|
7333
|
-
pinned
|
|
7334
|
-
pinned === "right" && "shadow-[-1px_0_0_0_var(--core-border-main-primary)]"
|
|
7381
|
+
pinnedDividerClass(pinned)
|
|
7335
7382
|
),
|
|
7336
7383
|
onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
|
|
7337
7384
|
onMouseEnter: () => setIsHovered(true),
|
|
@@ -7560,15 +7607,22 @@ function DataTableInner({
|
|
|
7560
7607
|
}).filter(Boolean),
|
|
7561
7608
|
[columns]
|
|
7562
7609
|
);
|
|
7610
|
+
const lastSyncedColumnIdsRef = React54.useRef(null);
|
|
7563
7611
|
React54.useEffect(() => {
|
|
7564
7612
|
if (!enableColumnDrag) return;
|
|
7613
|
+
const signature = allColumnIds.join(" ");
|
|
7614
|
+
if (signature === lastSyncedColumnIdsRef.current) return;
|
|
7615
|
+
lastSyncedColumnIdsRef.current = signature;
|
|
7565
7616
|
if (columnOrder.length === 0) {
|
|
7566
7617
|
setColumnOrder(allColumnIds);
|
|
7567
7618
|
return;
|
|
7568
7619
|
}
|
|
7569
|
-
const
|
|
7570
|
-
|
|
7571
|
-
|
|
7620
|
+
const pruned = columnOrder.filter((id) => allColumnIds.includes(id));
|
|
7621
|
+
const missing = allColumnIds.filter((id) => !pruned.includes(id));
|
|
7622
|
+
const next = [...pruned, ...missing];
|
|
7623
|
+
const changed = next.length !== columnOrder.length || next.some((id, i) => id !== columnOrder[i]);
|
|
7624
|
+
if (changed) {
|
|
7625
|
+
setColumnOrder(next);
|
|
7572
7626
|
}
|
|
7573
7627
|
}, [enableColumnDrag, columnOrder, allColumnIds, setColumnOrder]);
|
|
7574
7628
|
const table = (0, import_react_table.useReactTable)({
|
|
@@ -7685,6 +7739,16 @@ function DataTableInner({
|
|
|
7685
7739
|
return vars;
|
|
7686
7740
|
}, [enableColumnResizing, table.getState().columnSizing]);
|
|
7687
7741
|
const totalSize = enableColumnResizing ? table.getTotalSize() : void 0;
|
|
7742
|
+
const pinnedOffsets = React54.useMemo(() => {
|
|
7743
|
+
const map = /* @__PURE__ */ new Map();
|
|
7744
|
+
for (const col of table.getVisibleLeafColumns()) {
|
|
7745
|
+
const p = col.getIsPinned();
|
|
7746
|
+
if (p === "left") map.set(col.id, { side: "left", offset: col.getStart("left") });
|
|
7747
|
+
else if (p === "right")
|
|
7748
|
+
map.set(col.id, { side: "right", offset: col.getAfter("right") });
|
|
7749
|
+
}
|
|
7750
|
+
return map;
|
|
7751
|
+
}, [table, table.getState().columnPinning, table.getState().columnSizing]);
|
|
7688
7752
|
const tableContent = /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cn("w-full", className), style: columnSizeVars, children: [
|
|
7689
7753
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
7690
7754
|
Table,
|
|
@@ -7760,17 +7824,10 @@ function DataTableInner({
|
|
|
7760
7824
|
"data-state": row.getIsSelected() ? "selected" : void 0,
|
|
7761
7825
|
children: row.getVisibleCells().map((cell) => {
|
|
7762
7826
|
const cellPinned = cell.column.getIsPinned();
|
|
7827
|
+
const pin = cellPinned ? pinnedOffsets.get(cell.column.id) : void 0;
|
|
7763
7828
|
const cellStyle = {
|
|
7764
7829
|
...enableColumnResizing ? { width: `var(--col-${cell.column.id}-size)` } : {},
|
|
7765
|
-
...cellPinned
|
|
7766
|
-
position: "sticky",
|
|
7767
|
-
left: cell.column.getStart("left"),
|
|
7768
|
-
zIndex: 2
|
|
7769
|
-
} : cellPinned === "right" ? {
|
|
7770
|
-
position: "sticky",
|
|
7771
|
-
right: cell.column.getAfter("right"),
|
|
7772
|
-
zIndex: 2
|
|
7773
|
-
} : {}
|
|
7830
|
+
...pinnedStickyStyle(cellPinned, pin?.offset, 2)
|
|
7774
7831
|
};
|
|
7775
7832
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
7776
7833
|
TableCell,
|
|
@@ -7781,8 +7838,8 @@ function DataTableInner({
|
|
|
7781
7838
|
enableColumnResizing && "truncate",
|
|
7782
7839
|
// Pinned cells need an opaque background so scrolled
|
|
7783
7840
|
// content does not show through.
|
|
7784
|
-
cellPinned
|
|
7785
|
-
cellPinned
|
|
7841
|
+
cellPinned && "bg-table-row-bg-default group-hover/row:bg-table-row-bg-hover data-[state=selected]:bg-table-row-bg-selected",
|
|
7842
|
+
pinnedDividerClass(cellPinned)
|
|
7786
7843
|
),
|
|
7787
7844
|
children: (0, import_react_table.flexRender)(
|
|
7788
7845
|
cell.column.columnDef.cell,
|