@elsapiens/ui 0.1.0 → 0.1.6

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/dist/index.d.ts CHANGED
@@ -609,6 +609,12 @@ interface ModalProps {
609
609
  children: ReactNode;
610
610
  /** Optional footer content (typically action buttons) */
611
611
  footer?: ReactNode;
612
+ /** Whether the modal body should be scrollable (default: true) */
613
+ scrollable?: boolean;
614
+ /** Whether the modal body should have padding (default: true) */
615
+ padded?: boolean;
616
+ /** Custom header content, replaces the default title bar */
617
+ header?: ReactNode;
612
618
  }
613
619
  /**
614
620
  * A dialog overlay component for displaying content that requires user attention.
@@ -660,7 +666,7 @@ interface ModalProps {
660
666
  * <ImportantFormThatShouldNotBeAccidentallyClosed />
661
667
  * </Modal>
662
668
  */
663
- declare function Modal({ isOpen, onClose, title, description, size, closeOnOutsideClick, closeOnEscape, showCloseButton, children, footer, }: ModalProps): react.ReactPortal | null;
669
+ declare function Modal({ isOpen, onClose, title, description, size, closeOnOutsideClick, closeOnEscape, showCloseButton, children, footer, scrollable, padded, header, }: ModalProps): react.ReactPortal | null;
664
670
  /**
665
671
  * Props for the ConfirmDialog component.
666
672
  */
@@ -856,6 +862,10 @@ interface TooltipProps {
856
862
  delayDuration?: number;
857
863
  /** Additional CSS classes for the tooltip */
858
864
  className?: string;
865
+ /** Additional CSS classes for the trigger wrapper element */
866
+ wrapperClassName?: string;
867
+ /** Additional inline styles for the trigger wrapper element (useful for fixed positioning) */
868
+ wrapperStyle?: React.CSSProperties;
859
869
  }
860
870
  /**
861
871
  * A floating label that appears on hover/focus to provide additional context.
@@ -892,7 +902,7 @@ interface TooltipProps {
892
902
  * <InfoIcon />
893
903
  * </Tooltip>
894
904
  */
895
- declare function Tooltip({ content, children, side, delayDuration, className, }: TooltipProps): react_jsx_runtime.JSX.Element;
905
+ declare function Tooltip({ content, children, side, delayDuration, className, wrapperClassName, wrapperStyle, }: TooltipProps): react_jsx_runtime.JSX.Element;
896
906
 
897
907
  /**
898
908
  * Hook to detect mobile viewport based on window width.
@@ -1028,8 +1038,13 @@ interface TableProps<T> {
1028
1038
  * - 'first': first column is sticky
1029
1039
  * - 'last': last column is sticky
1030
1040
  * - 'both': first and last columns are sticky
1041
+ * @deprecated Use stickyColumnsLeft/stickyColumnsRight or pass an array of column keys
1031
1042
  */
1032
- stickyColumns?: 'first' | 'last' | 'both';
1043
+ stickyColumns?: 'first' | 'last' | 'both' | string[];
1044
+ /** Number of columns from the left to make sticky (e.g., 2 for first two columns) */
1045
+ stickyColumnsLeft?: number;
1046
+ /** Number of columns from the right to make sticky (e.g., 1 for last column) */
1047
+ stickyColumnsRight?: number;
1033
1048
  /** Make the header row sticky on vertical scroll */
1034
1049
  stickyHeader?: boolean;
1035
1050
  /** Top offset for sticky header (e.g., '64px' to account for a fixed navbar) */
@@ -1099,12 +1114,23 @@ interface TableProps<T> {
1099
1114
  * columns={transactionColumns}
1100
1115
  * inCard="full"
1101
1116
  * stickyHeader
1102
- * stickyColumns="first"
1117
+ * stickyColumnsLeft={2} // First 2 columns sticky
1118
+ * stickyColumnsRight={1} // Last column sticky
1103
1119
  * stickyScrollbar
1104
1120
  * />
1105
1121
  * ```
1122
+ *
1123
+ * @example
1124
+ * ```tsx
1125
+ * // Sticky columns by key
1126
+ * <Table
1127
+ * data={data}
1128
+ * columns={columns}
1129
+ * stickyColumns={['id', 'name', 'actions']}
1130
+ * />
1131
+ * ```
1106
1132
  */
1107
- declare function Table<T extends Record<string, unknown>>({ data, columns, onRowClick, emptyMessage, className, striped, hoverable, aligned, size, inCard, cardPadding: _cardPadding, stickyColumns, stickyHeader, stickyHeaderTop, stickyColumnsOffset, scrollable, stickyScrollbar, }: TableProps<T>): react_jsx_runtime.JSX.Element;
1133
+ declare function Table<T extends Record<string, unknown>>({ data, columns, onRowClick, emptyMessage, className, striped, hoverable, aligned, size, inCard, cardPadding: _cardPadding, stickyColumns, stickyColumnsLeft, stickyColumnsRight, stickyHeader, stickyHeaderTop, stickyColumnsOffset, scrollable, stickyScrollbar, }: TableProps<T>): react_jsx_runtime.JSX.Element;
1108
1134
 
1109
1135
  type FilterOperator = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with' | 'greater_than' | 'less_than' | 'greater_or_equal' | 'less_or_equal' | 'between' | 'is_empty' | 'is_not_empty';
1110
1136
  interface FilterField {
@@ -1254,8 +1280,14 @@ interface FilterBarProps {
1254
1280
  onConditionsChange?: (conditions: FilterBarCondition[]) => void;
1255
1281
  /** Callback when user saves current filters as a new view */
1256
1282
  onSaveFilter?: (name: string, conditions: FilterBarCondition[]) => void;
1283
+ /** Callback when refresh button is clicked */
1284
+ onRefresh?: () => void;
1257
1285
  /** Apply negative margin for edge-to-edge display inside a Card */
1258
1286
  inCard?: boolean;
1287
+ /** When true, adds rounded top corners, negative top margin, and removes top border to merge with card header */
1288
+ firstInCard?: boolean;
1289
+ /** When true, adds rounded bottom corners, negative bottom margin, and removes bottom border to merge with card footer */
1290
+ lastInCard?: boolean;
1259
1291
  /** Additional CSS classes */
1260
1292
  className?: string;
1261
1293
  }
@@ -1317,7 +1349,7 @@ interface FilterBarProps {
1317
1349
  * />
1318
1350
  * ```
1319
1351
  */
1320
- declare function FilterBar({ tabs, activeTab, onTabChange, allowAddTab: _allowAddTab, onAddTab: _onAddTab, search, sort, fields, conditions, onConditionsChange, onSaveFilter, inCard, className, }: FilterBarProps): react_jsx_runtime.JSX.Element | null;
1352
+ declare function FilterBar({ tabs, activeTab, onTabChange, allowAddTab: _allowAddTab, onAddTab: _onAddTab, search, sort, fields, conditions, onConditionsChange, onSaveFilter, onRefresh, inCard, firstInCard, lastInCard, className, }: FilterBarProps): react_jsx_runtime.JSX.Element | null;
1321
1353
 
1322
1354
  /**
1323
1355
  * Internal context value for Form component.
package/dist/index.js CHANGED
@@ -2838,7 +2838,10 @@ function Modal({
2838
2838
  closeOnEscape = true,
2839
2839
  showCloseButton = true,
2840
2840
  children,
2841
- footer
2841
+ footer,
2842
+ scrollable = true,
2843
+ padded = true,
2844
+ header
2842
2845
  }) {
2843
2846
  const modalRef = useRef7(null);
2844
2847
  const previousActiveElement = useRef7(null);
@@ -2911,7 +2914,7 @@ function Modal({
2911
2914
  ),
2912
2915
  onClick: (e) => e.stopPropagation(),
2913
2916
  children: [
2914
- (title || showCloseButton) && /* @__PURE__ */ jsxs10(
2917
+ header ? /* @__PURE__ */ jsx10("div", { className: "flex-none rounded-t-lg bg-card border-b border-border", children: header }) : title || showCloseButton ? /* @__PURE__ */ jsxs10(
2915
2918
  "div",
2916
2919
  {
2917
2920
  className: "flex items-start justify-between border-b border-border bg-card rounded-t-lg",
@@ -2958,12 +2961,15 @@ function Modal({
2958
2961
  )
2959
2962
  ]
2960
2963
  }
2961
- ),
2964
+ ) : null,
2962
2965
  /* @__PURE__ */ jsx10(
2963
2966
  "div",
2964
2967
  {
2965
- className: "overflow-y-auto flex-1 min-h-0",
2966
- style: { padding: "var(--modal-padding)" },
2968
+ className: cn10(
2969
+ "flex-1 min-h-0",
2970
+ scrollable ? "overflow-y-auto" : "overflow-hidden"
2971
+ ),
2972
+ style: padded ? { padding: "var(--modal-padding)" } : void 0,
2967
2973
  children
2968
2974
  }
2969
2975
  ),
@@ -3238,7 +3244,9 @@ function Tooltip({
3238
3244
  children,
3239
3245
  side = "top",
3240
3246
  delayDuration = 200,
3241
- className
3247
+ className,
3248
+ wrapperClassName,
3249
+ wrapperStyle
3242
3250
  }) {
3243
3251
  const [isOpen, setIsOpen] = useState9(false);
3244
3252
  const [position, setPosition] = useState9({ top: 0, left: 0 });
@@ -3290,7 +3298,8 @@ function Tooltip({
3290
3298
  "div",
3291
3299
  {
3292
3300
  ref: triggerRef,
3293
- className: "inline-block",
3301
+ className: cn12("inline-block", wrapperClassName),
3302
+ style: wrapperStyle,
3294
3303
  onMouseEnter: showTooltip,
3295
3304
  onMouseLeave: hideTooltip,
3296
3305
  onFocus: showTooltip,
@@ -3314,11 +3323,11 @@ function Tooltip({
3314
3323
  style: {
3315
3324
  top: position.top,
3316
3325
  left: position.left,
3317
- paddingLeft: "var(--el-tooltip-px)",
3318
- paddingRight: "var(--el-tooltip-px)",
3319
- paddingTop: "var(--el-tooltip-py)",
3320
- paddingBottom: "var(--el-tooltip-py)",
3321
- fontSize: "var(--el-font-size-md)"
3326
+ paddingLeft: "var(--el-tooltip-px, 0.5rem)",
3327
+ paddingRight: "var(--el-tooltip-px, 0.5rem)",
3328
+ paddingTop: "var(--el-tooltip-py, 0.25rem)",
3329
+ paddingBottom: "var(--el-tooltip-py, 0.25rem)",
3330
+ fontSize: "var(--el-font-size-sm, 0.8125rem)"
3322
3331
  },
3323
3332
  role: "tooltip",
3324
3333
  children: content
@@ -3346,6 +3355,8 @@ function Table({
3346
3355
  inCard = false,
3347
3356
  cardPadding: _cardPadding = "md",
3348
3357
  stickyColumns,
3358
+ stickyColumnsLeft,
3359
+ stickyColumnsRight,
3349
3360
  stickyHeader = false,
3350
3361
  stickyHeaderTop,
3351
3362
  stickyColumnsOffset,
@@ -3414,11 +3425,26 @@ function Table({
3414
3425
  handleScroll();
3415
3426
  return () => scrollParent.removeEventListener("scroll", handleScroll);
3416
3427
  }, [stickyHeader]);
3428
+ const getStickyConfig = () => {
3429
+ const leftCount = stickyColumnsLeft ?? (stickyColumns === "first" || stickyColumns === "both" ? 1 : 0);
3430
+ const rightCount = stickyColumnsRight ?? (stickyColumns === "last" || stickyColumns === "both" ? 1 : 0);
3431
+ const keys = Array.isArray(stickyColumns) ? stickyColumns : [];
3432
+ return { leftCount, rightCount, keys };
3433
+ };
3434
+ const { leftCount: stickyLeftCount, rightCount: stickyRightCount, keys: stickyKeys } = getStickyConfig();
3435
+ const needsColumnMeasurement = stickyLeftCount > 1 || stickyRightCount > 1 || stickyKeys.length > 0;
3417
3436
  useEffect9(() => {
3418
- if (!stickyScrollbar && !stickyHeader || !tableContainerRef.current) return;
3437
+ if (!stickyScrollbar && !stickyHeader && !needsColumnMeasurement || !tableContainerRef.current) return;
3419
3438
  const updateDimensions = () => {
3420
3439
  if (tableContainerRef.current) {
3421
3440
  setScrollWidth(tableContainerRef.current.scrollWidth);
3441
+ if (theadRef.current && needsColumnMeasurement) {
3442
+ const headerCells = theadRef.current.querySelectorAll("th:not(.el-table-spacer)");
3443
+ headerCells.forEach((cell, idx) => {
3444
+ const width = cell.getBoundingClientRect().width;
3445
+ tableContainerRef.current?.style.setProperty(`--el-table-col-${idx}-width`, `${width}px`);
3446
+ });
3447
+ }
3422
3448
  }
3423
3449
  if (theadRef.current && stickyHeader) {
3424
3450
  const headerCells = theadRef.current.querySelectorAll("th");
@@ -3430,7 +3456,7 @@ function Table({
3430
3456
  const resizeObserver = new ResizeObserver(updateDimensions);
3431
3457
  resizeObserver.observe(tableContainerRef.current);
3432
3458
  return () => resizeObserver.disconnect();
3433
- }, [stickyScrollbar, stickyHeader, data, columns]);
3459
+ }, [stickyScrollbar, stickyHeader, needsColumnMeasurement, data, columns]);
3434
3460
  const handleSort = (key) => {
3435
3461
  if (sortColumn === key) {
3436
3462
  if (sortDirection === "asc") {
@@ -3482,12 +3508,43 @@ function Table({
3482
3508
  return "text-left";
3483
3509
  }
3484
3510
  };
3485
- const isFirstSticky = stickyColumns === "first" || stickyColumns === "both";
3486
- const isLastSticky = stickyColumns === "last" || stickyColumns === "both";
3511
+ const isColumnSticky = (idx, columnKey) => {
3512
+ if (stickyKeys.includes(columnKey)) return true;
3513
+ if (idx < stickyLeftCount) return true;
3514
+ if (idx >= columns.length - stickyRightCount) return true;
3515
+ return false;
3516
+ };
3517
+ const getStickyPosition = (idx, columnKey) => {
3518
+ if (stickyKeys.includes(columnKey)) {
3519
+ const isLeftSide = idx < columns.length / 2;
3520
+ return isLeftSide ? "left" : "right";
3521
+ }
3522
+ if (idx < stickyLeftCount) return "left";
3523
+ if (idx >= columns.length - stickyRightCount) return "right";
3524
+ return null;
3525
+ };
3487
3526
  const getOffsetValue = (offset) => {
3488
3527
  if (!offset) return "0";
3489
3528
  return typeof offset === "number" ? `${offset}px` : offset;
3490
3529
  };
3530
+ const getStickyOffset = (idx, position) => {
3531
+ const baseOffset = stickyColumnsOffset ? getOffsetValue(stickyColumnsOffset) : "0px";
3532
+ const spacerWidth = "var(--el-table-spacer-width)";
3533
+ if (position === "left") {
3534
+ if (idx === 0) {
3535
+ return stickyColumnsOffset ? `calc(${baseOffset} + ${spacerWidth})` : spacerWidth;
3536
+ }
3537
+ const prevWidths = Array.from({ length: idx }, (_, i) => `var(--el-table-col-${i}-width, 0px)`).join(" + ");
3538
+ return stickyColumnsOffset ? `calc(${baseOffset} + ${spacerWidth} + ${prevWidths})` : `calc(${spacerWidth} + ${prevWidths})`;
3539
+ } else {
3540
+ const colsFromRight = columns.length - 1 - idx;
3541
+ if (colsFromRight === 0) {
3542
+ return stickyColumnsOffset ? `calc(${baseOffset} + ${spacerWidth})` : spacerWidth;
3543
+ }
3544
+ const nextWidths = Array.from({ length: colsFromRight }, (_, i) => `var(--el-table-col-${idx + 1 + i}-width, 0px)`).join(" + ");
3545
+ return stickyColumnsOffset ? `calc(${baseOffset} + ${spacerWidth} + ${nextWidths})` : `calc(${spacerWidth} + ${nextWidths})`;
3546
+ }
3547
+ };
3491
3548
  const SpacerCell = ({ isHeader = false, position, isStriped = false, isHoverable = false }) => {
3492
3549
  if (!aligned) return null;
3493
3550
  const Component = isHeader ? "th" : "td";
@@ -3550,8 +3607,9 @@ function Table({
3550
3607
  columns.map((column, idx) => {
3551
3608
  const isFirst = idx === 0;
3552
3609
  const isLast = idx === columns.length - 1;
3553
- const shouldStickyFirst = isFirst && isFirstSticky;
3554
- const shouldStickyLast = isLast && isLastSticky;
3610
+ const columnKey = String(column.key);
3611
+ const isSticky = isColumnSticky(idx, columnKey);
3612
+ const stickyPosition = getStickyPosition(idx, columnKey);
3555
3613
  const measuredWidth = isDummy && columnWidths.length > 0 && columnWidths[idx + 1] ? columnWidths[idx + 1] : void 0;
3556
3614
  return /* @__PURE__ */ jsx13(
3557
3615
  "th",
@@ -3562,8 +3620,7 @@ function Table({
3562
3620
  column.sortable && "cursor-pointer select-none hover:bg-wisteria-200 dark:hover:bg-wisteria-700",
3563
3621
  aligned && isFirst && "el-table-header-first",
3564
3622
  aligned && isLast && "el-table-header-last",
3565
- shouldStickyFirst && "sticky z-10 bg-wisteria-100 dark:bg-wisteria-800",
3566
- shouldStickyLast && "sticky z-10 bg-wisteria-100 dark:bg-wisteria-800",
3623
+ isSticky && "sticky z-10 bg-wisteria-100 dark:bg-wisteria-800",
3567
3624
  column.className
3568
3625
  ),
3569
3626
  style: {
@@ -3572,12 +3629,12 @@ function Table({
3572
3629
  ...aligned && isLast && { paddingRight: 0 },
3573
3630
  ...column.width && { width: column.width },
3574
3631
  ...column.maxWidth && { maxWidth: column.maxWidth },
3575
- ...shouldStickyFirst && { left: stickyColumnsOffset ? `calc(${getOffsetValue(stickyColumnsOffset)} + var(--el-table-spacer-width))` : "var(--el-table-spacer-width)" },
3576
- ...shouldStickyLast && { right: stickyColumnsOffset ? `calc(${getOffsetValue(stickyColumnsOffset)} + var(--el-table-spacer-width))` : "var(--el-table-spacer-width)" },
3632
+ ...isSticky && stickyPosition === "left" && { left: getStickyOffset(idx, "left") },
3633
+ ...isSticky && stickyPosition === "right" && { right: getStickyOffset(idx, "right") },
3577
3634
  // Use measured width for dummy header to match main table exactly
3578
3635
  ...measuredWidth && { width: measuredWidth, minWidth: measuredWidth, maxWidth: measuredWidth, boxSizing: "border-box" }
3579
3636
  },
3580
- onClick: () => column.sortable && handleSort(String(column.key)),
3637
+ onClick: () => column.sortable && handleSort(columnKey),
3581
3638
  children: /* @__PURE__ */ jsxs13("div", { className: cn13(
3582
3639
  "flex items-center el-gap-sm",
3583
3640
  column.align === "right" && "justify-end",
@@ -3585,10 +3642,10 @@ function Table({
3585
3642
  !column.wrap && "whitespace-nowrap overflow-hidden text-ellipsis"
3586
3643
  ), children: [
3587
3644
  column.header,
3588
- column.sortable && sortColumn === String(column.key) && /* @__PURE__ */ jsx13("span", { className: "text-xs flex-shrink-0", children: sortDirection === "asc" ? "\u2191" : "\u2193" })
3645
+ column.sortable && sortColumn === columnKey && /* @__PURE__ */ jsx13("span", { className: "text-xs flex-shrink-0", children: sortDirection === "asc" ? "\u2191" : "\u2193" })
3589
3646
  ] })
3590
3647
  },
3591
- String(column.key)
3648
+ columnKey
3592
3649
  );
3593
3650
  }),
3594
3651
  /* @__PURE__ */ jsx13(SpacerCell, { isHeader: true, position: "right" })
@@ -3670,8 +3727,9 @@ function Table({
3670
3727
  columns.map((column, idx) => {
3671
3728
  const isFirst = idx === 0;
3672
3729
  const isLast = idx === columns.length - 1;
3673
- const shouldStickyFirst = isFirst && isFirstSticky;
3674
- const shouldStickyLast = isLast && isLastSticky;
3730
+ const columnKey = String(column.key);
3731
+ const isSticky = isColumnSticky(idx, columnKey);
3732
+ const stickyPosition = getStickyPosition(idx, columnKey);
3675
3733
  const getStickyBgClass = () => {
3676
3734
  if (isStripedRow) {
3677
3735
  return "bg-wisteria-50 dark:bg-[hsl(var(--wisteria-850))]";
@@ -3692,9 +3750,9 @@ function Table({
3692
3750
  getAlignClass(column.align),
3693
3751
  aligned && isFirst && "el-table-cell-first",
3694
3752
  aligned && isLast && "el-table-cell-last",
3695
- (shouldStickyFirst || shouldStickyLast) && "sticky z-10 transition-colors duration-150",
3696
- (shouldStickyFirst || shouldStickyLast) && getStickyBgClass(),
3697
- (shouldStickyFirst || shouldStickyLast) && getStickyHoverClass(),
3753
+ isSticky && "sticky z-10 transition-colors duration-150",
3754
+ isSticky && getStickyBgClass(),
3755
+ isSticky && getStickyHoverClass(),
3698
3756
  !column.wrap && "whitespace-nowrap overflow-hidden text-ellipsis",
3699
3757
  column.className
3700
3758
  ),
@@ -3703,16 +3761,16 @@ function Table({
3703
3761
  ...aligned && isFirst && { paddingLeft: 0 },
3704
3762
  ...aligned && isLast && { paddingRight: 0 },
3705
3763
  ...column.maxWidth && { maxWidth: column.maxWidth },
3706
- ...shouldStickyFirst && {
3707
- left: stickyColumnsOffset ? `calc(${getOffsetValue(stickyColumnsOffset)} + var(--el-table-spacer-width))` : "var(--el-table-spacer-width)"
3764
+ ...isSticky && stickyPosition === "left" && {
3765
+ left: getStickyOffset(idx, "left")
3708
3766
  },
3709
- ...shouldStickyLast && {
3710
- right: stickyColumnsOffset ? `calc(${getOffsetValue(stickyColumnsOffset)} + var(--el-table-spacer-width))` : "var(--el-table-spacer-width)"
3767
+ ...isSticky && stickyPosition === "right" && {
3768
+ right: getStickyOffset(idx, "right")
3711
3769
  }
3712
3770
  },
3713
3771
  children: column.render ? column.render(item, index) : String(item[column.key] ?? "")
3714
3772
  },
3715
- String(column.key)
3773
+ columnKey
3716
3774
  );
3717
3775
  }),
3718
3776
  /* @__PURE__ */ jsx13(SpacerCell, { position: "right", isStriped: isStripedRow, isHoverable: hoverable })
@@ -3984,6 +4042,7 @@ var CloseIcon = ({ className, style }) => /* @__PURE__ */ jsx15("svg", { classNa
3984
4042
  var PlusIcon = ({ className, style }) => /* @__PURE__ */ jsx15("svg", { className, width: "16", height: "16", style: { width: "var(--el-icon-size-sm, 1rem)", height: "var(--el-icon-size-sm, 1rem)", ...style }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) });
3985
4043
  var SortIcon = ({ className, style }) => /* @__PURE__ */ jsx15("svg", { className, width: "16", height: "16", style: { width: "var(--el-icon-size-sm, 1rem)", height: "var(--el-icon-size-sm, 1rem)", ...style }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) });
3986
4044
  var FilterIcon = ({ className, style }) => /* @__PURE__ */ jsx15("svg", { className, width: "16", height: "16", style: { width: "var(--el-icon-size-sm, 1rem)", height: "var(--el-icon-size-sm, 1rem)", ...style }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" }) });
4045
+ var RefreshIcon = ({ className, style }) => /* @__PURE__ */ jsx15("svg", { className, width: "16", height: "16", style: { width: "var(--el-icon-size-sm, 1rem)", height: "var(--el-icon-size-sm, 1rem)", ...style }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) });
3987
4046
  function useIsMobile2(breakpoint = 768) {
3988
4047
  const [isMobile, setIsMobile] = useState12(false);
3989
4048
  useEffect11(() => {
@@ -5092,7 +5151,10 @@ function FilterBar({
5092
5151
  conditions = [],
5093
5152
  onConditionsChange,
5094
5153
  onSaveFilter,
5154
+ onRefresh,
5095
5155
  inCard = false,
5156
+ firstInCard = false,
5157
+ lastInCard = false,
5096
5158
  className
5097
5159
  }) {
5098
5160
  const isMobile = useIsMobile2();
@@ -5352,12 +5414,28 @@ function FilterBar({
5352
5414
  ] });
5353
5415
  }
5354
5416
  const showMainBar = tabs.length > 0 || search || sort;
5355
- return /* @__PURE__ */ jsxs15("div", { className: cn15("flex flex-col", className), style: { gap: "var(--el-filter-gap)" }, children: [
5417
+ const seamlessConnection = inCard && showMainBar && isFilterPanelOpen && fields.length > 0;
5418
+ return /* @__PURE__ */ jsxs15("div", { className: cn15("flex flex-col", className), style: { gap: seamlessConnection ? 0 : "var(--el-filter-gap)" }, children: [
5356
5419
  showMainBar && /* @__PURE__ */ jsxs15(
5357
5420
  "div",
5358
5421
  {
5359
- className: cn15("flex items-center justify-between", inCard && "el-filter-bar"),
5360
- style: { gap: "var(--el-gap-lg)" },
5422
+ className: cn15(
5423
+ "flex items-center justify-between bg-slate-100 dark:bg-slate-800 border-slate-300 dark:border-slate-600",
5424
+ inCard ? cn15(
5425
+ "el-filter-bar",
5426
+ firstInCard && "el-filter-bar-first",
5427
+ firstInCard && !seamlessConnection && "border-b",
5428
+ !firstInCard && "border-t",
5429
+ !seamlessConnection && !lastInCard && "border-b",
5430
+ lastInCard && !seamlessConnection && "el-filter-bar-last border-t"
5431
+ ) : "border rounded-lg"
5432
+ ),
5433
+ style: {
5434
+ gap: "var(--el-gap-lg)",
5435
+ paddingTop: "var(--el-gap-md)",
5436
+ paddingBottom: "var(--el-gap-md)",
5437
+ ...!inCard && { paddingInline: "var(--el-gap-md)" }
5438
+ },
5361
5439
  children: [
5362
5440
  /* @__PURE__ */ jsxs15("div", { className: "flex items-center min-w-0 flex-1 overflow-x-auto hide-native-scrollbar", style: { gap: "var(--el-gap-sm)" }, children: [
5363
5441
  tabs.map((tab) => /* @__PURE__ */ jsxs15(
@@ -5421,6 +5499,16 @@ function FilterBar({
5421
5499
  children: "Save"
5422
5500
  }
5423
5501
  ),
5502
+ onRefresh && /* @__PURE__ */ jsx15(
5503
+ "button",
5504
+ {
5505
+ onClick: onRefresh,
5506
+ className: "text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors",
5507
+ style: { padding: "var(--el-filter-pill-py)" },
5508
+ title: "Refresh",
5509
+ children: /* @__PURE__ */ jsx15(RefreshIcon, {})
5510
+ }
5511
+ ),
5424
5512
  search && /* @__PURE__ */ jsx15("div", { className: "relative", children: isSearchOpen ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center", children: [
5425
5513
  /* @__PURE__ */ jsx15(
5426
5514
  "input",
@@ -5568,11 +5656,22 @@ function FilterBar({
5568
5656
  isFilterPanelOpen && fields.length > 0 && /* @__PURE__ */ jsxs15(
5569
5657
  "div",
5570
5658
  {
5571
- className: "el-filter-bar flex items-center bg-slate-100 dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg",
5659
+ className: cn15(
5660
+ "flex items-center bg-slate-100 dark:bg-slate-800 border-slate-300 dark:border-slate-600",
5661
+ inCard ? cn15(
5662
+ "el-filter-bar",
5663
+ // If no main bar, filter pills can be first
5664
+ !showMainBar && firstInCard && "el-filter-bar-first",
5665
+ lastInCard && "el-filter-bar-last",
5666
+ !lastInCard && "border-b",
5667
+ !seamlessConnection && !(!showMainBar && firstInCard) && "border-t"
5668
+ ) : "border rounded-lg"
5669
+ ),
5572
5670
  style: {
5573
5671
  gap: "var(--el-gap-md)",
5574
5672
  paddingTop: "var(--el-gap-md)",
5575
- paddingBottom: "var(--el-gap-md)"
5673
+ paddingBottom: "var(--el-gap-md)",
5674
+ ...!inCard && { paddingInline: "var(--el-gap-md)" }
5576
5675
  },
5577
5676
  children: [
5578
5677
  /* @__PURE__ */ jsxs15(
@@ -6515,7 +6614,7 @@ var NumericInput = forwardRef12(
6515
6614
  const displayValue = value !== null && value !== void 0 ? String(value) : "";
6516
6615
  return /* @__PURE__ */ jsxs21("div", { className: "w-full", children: [
6517
6616
  /* @__PURE__ */ jsxs21("div", { className: "relative", children: [
6518
- prefix && /* @__PURE__ */ jsx22("div", { className: "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-muted-foreground", children: prefix }),
6617
+ prefix && /* @__PURE__ */ jsx22("div", { className: "el-input-prefix-icon", children: prefix }),
6519
6618
  /* @__PURE__ */ jsx22(
6520
6619
  "input",
6521
6620
  {
@@ -6529,14 +6628,14 @@ var NumericInput = forwardRef12(
6529
6628
  className: cn22(
6530
6629
  "el-input el-input-md el-numeric-input",
6531
6630
  error && "el-input-invalid",
6532
- prefix && "pl-8",
6533
- suffix && "pr-8",
6631
+ prefix && "el-input-has-prefix-narrow",
6632
+ suffix && "el-input-has-suffix",
6534
6633
  className
6535
6634
  ),
6536
6635
  ...props
6537
6636
  }
6538
6637
  ),
6539
- suffix && /* @__PURE__ */ jsx22("div", { className: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none text-muted-foreground", children: suffix })
6638
+ suffix && /* @__PURE__ */ jsx22("div", { className: "el-input-suffix-icon", children: suffix })
6540
6639
  ] }),
6541
6640
  !hideMessage && error && /* @__PURE__ */ jsx22("div", { className: "el-field-message", children: /* @__PURE__ */ jsx22("p", { className: "el-field-error", children: error }) })
6542
6641
  ] });
@@ -6665,10 +6764,10 @@ function PhoneInput({
6665
6764
  hasError && "el-input-invalid"
6666
6765
  ),
6667
6766
  children: [
6668
- /* @__PURE__ */ jsx23("div", { className: "flex-shrink-0 border-r border-input flex items-stretch overflow-hidden pl-2", children: /* @__PURE__ */ jsx23(
6767
+ /* @__PURE__ */ jsx23("div", { className: "flex-shrink-0 border-r border-input flex items-center el-pl-md", children: /* @__PURE__ */ jsx23(
6669
6768
  SearchableSelect,
6670
6769
  {
6671
- className: "!border-0 !h-full !shadow-none !ring-0 !outline-none focus:!ring-0 focus:!outline-none focus-within:!ring-0 focus-within:!outline-none !rounded-none min-w-[100px] [&>button]:!border-0 [&>button]:!shadow-none [&>button]:!ring-0 [&>button]:!rounded-none [&>button]:h-full [&>button]:!ml-0",
6770
+ className: "!border-0 !shadow-none !ring-0 !outline-none focus:!ring-0 focus:!outline-none focus-within:!ring-0 focus-within:!outline-none !rounded-none [&>button]:!border-0 [&>button]:!shadow-none [&>button]:!ring-0 [&>button]:!rounded-none [&>button]:!bg-transparent [&>button>svg]:hidden [&>button]:el-px-md",
6672
6771
  disabled,
6673
6772
  options: COUNTRY_OPTIONS,
6674
6773
  placeholder: "Country",
@@ -12995,9 +13094,9 @@ var Summary = forwardRef44(
12995
13094
  ref: scrollContainerRef,
12996
13095
  className: "overflow-x-auto hide-native-scrollbar",
12997
13096
  onScroll: handleScroll,
12998
- children: /* @__PURE__ */ jsx58("div", { ref: itemsContainerRef, className: "flex items-center", children: items.map((item, index) => /* @__PURE__ */ jsxs49("div", { className: "flex items-center", children: [
13097
+ children: /* @__PURE__ */ jsx58("div", { ref: itemsContainerRef, className: "flex items-center el-px-md", children: items.map((item, index) => /* @__PURE__ */ jsxs49("div", { className: "flex items-center", children: [
12999
13098
  /* @__PURE__ */ jsx58(SummaryItem, { ...item }),
13000
- showDividers && index < items.length - 1 && /* @__PURE__ */ jsx58("div", { className: "w-px h-8 bg-border flex-shrink-0" })
13099
+ showDividers && index < items.length - 1 && /* @__PURE__ */ jsx58("div", { className: "w-px h-8 bg-border flex-shrink-0 el-mx-md" })
13001
13100
  ] }, index)) })
13002
13101
  }
13003
13102
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elsapiens/ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.6",
4
4
  "description": "UI components for elSapiens SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,11 +20,14 @@
20
20
  "files": [
21
21
  "dist"
22
22
  ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
23
26
  "dependencies": {
27
+ "@elsapiens/utils": "^0.1.0",
24
28
  "date-fns": "^3.6.0",
25
29
  "lucide-react": "^0.468.0",
26
- "recharts": "^3.7.0",
27
- "@elsapiens/utils": "0.1.0"
30
+ "recharts": "^3.7.0"
28
31
  },
29
32
  "devDependencies": {
30
33
  "@testing-library/react": "^16.3.0",