@l3mpire/ui 2.18.0 → 2.19.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/dist/index.d.mts CHANGED
@@ -1013,6 +1013,7 @@ interface SummaryChipProps {
1013
1013
  open?: boolean;
1014
1014
  onOpenChange?: (open: boolean) => void;
1015
1015
  collisionBoundary?: Element | null;
1016
+ tooltipContent?: React.ReactNode;
1016
1017
  }
1017
1018
  declare const SummaryChip: React.FC<SummaryChipProps>;
1018
1019
 
package/dist/index.d.ts CHANGED
@@ -1013,6 +1013,7 @@ interface SummaryChipProps {
1013
1013
  open?: boolean;
1014
1014
  onOpenChange?: (open: boolean) => void;
1015
1015
  collisionBoundary?: Element | null;
1016
+ tooltipContent?: React.ReactNode;
1016
1017
  }
1017
1018
  declare const SummaryChip: React.FC<SummaryChipProps>;
1018
1019
 
package/dist/index.js CHANGED
@@ -5323,7 +5323,7 @@ var DEFAULT_OPERATOR_BY_TYPE = {
5323
5323
  text: "contains",
5324
5324
  number: "=",
5325
5325
  date: "is between",
5326
- enum: "is",
5326
+ enum: "is any of",
5327
5327
  tags: "contains",
5328
5328
  boolean: "is true",
5329
5329
  relation: "is"
@@ -5360,7 +5360,7 @@ function getValueInputType(type, operator) {
5360
5360
  return ["is any of", "is none of"].includes(operator) ? "MultiRelationPicker" : "RelationPicker";
5361
5361
  return null;
5362
5362
  }
5363
- function formatFilterValue(value, dynamicOptions) {
5363
+ function formatFilterValue(value, dynamicOptions, full) {
5364
5364
  if (value == null) return void 0;
5365
5365
  if (typeof value === "boolean") return value ? "Yes" : "No";
5366
5366
  if (value instanceof Date) {
@@ -5379,6 +5379,9 @@ function formatFilterValue(value, dynamicOptions) {
5379
5379
  const fmt = (d) => d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
5380
5380
  return `${fmt(value[0])} \u2013 ${value[1] instanceof Date ? fmt(value[1]) : "\u2026"}`;
5381
5381
  }
5382
+ if (full) {
5383
+ return value.map((v) => resolveDynamic(String(v), dynamicOptions)).join(", ");
5384
+ }
5382
5385
  const resolved = resolveDynamic(String(value[0]), dynamicOptions);
5383
5386
  return resolved;
5384
5387
  }
@@ -5519,7 +5522,7 @@ var FilterBar = React38.forwardRef(
5519
5522
  {
5520
5523
  ref,
5521
5524
  className: cn(
5522
- "flex items-center justify-between w-full",
5525
+ "flex items-start justify-between w-full",
5523
5526
  className
5524
5527
  ),
5525
5528
  role: "toolbar",
@@ -6563,7 +6566,9 @@ var DateCalendarValueInput = ({
6563
6566
  if (isRange) {
6564
6567
  if (Array.isArray(value) && value.length === 2) {
6565
6568
  const [from, to] = value;
6566
- return { from, to };
6569
+ if (from instanceof Date) {
6570
+ return { from, to: to instanceof Date ? to : void 0 };
6571
+ }
6567
6572
  }
6568
6573
  return void 0;
6569
6574
  }
@@ -6578,7 +6583,7 @@ var DateCalendarValueInput = ({
6578
6583
  if (range.from && range.to) {
6579
6584
  onChange([range.from, range.to]);
6580
6585
  } else if (range.from) {
6581
- onChange([range.from, range.from]);
6586
+ onChange([range.from, null]);
6582
6587
  }
6583
6588
  }
6584
6589
  };
@@ -6748,7 +6753,6 @@ var MultiSelectValueInput = ({
6748
6753
  },
6749
6754
  opt.value
6750
6755
  )),
6751
- dynamicOptions && dynamicOptions.length > 0 && options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(DynamicOptionsDivider, {}),
6752
6756
  options.map((opt) => {
6753
6757
  const isSelected = selected.includes(opt);
6754
6758
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
@@ -7895,6 +7899,27 @@ var AdvancedRow = ({
7895
7899
  ] }),
7896
7900
  condition.operator && !isNoValueOperator(condition.operator) && (() => {
7897
7901
  const inputType = getValueInputType(propertyDef.type, condition.operator);
7902
+ const isInline = inputType === "TextInput" || inputType === "NumberInput";
7903
+ if (isInline) {
7904
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7905
+ "input",
7906
+ {
7907
+ type: inputType === "NumberInput" ? "number" : "text",
7908
+ value: condition.value ?? "",
7909
+ onChange: (e) => handleValueChange(
7910
+ inputType === "NumberInput" ? e.target.value === "" ? null : Number(e.target.value) : e.target.value
7911
+ ),
7912
+ placeholder: "Enter value...",
7913
+ className: cn(
7914
+ "flex-1 min-w-[80px] px-base py-sm",
7915
+ "bg-[var(--color-background)] border border-[var(--color-input)] rounded-base",
7916
+ "text-sm font-regular leading-sm text-[var(--color-foreground)]",
7917
+ "placeholder:text-[var(--color-muted-foreground)]",
7918
+ "focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)] focus:ring-offset-0"
7919
+ )
7920
+ }
7921
+ );
7922
+ }
7898
7923
  const dateWide = inputType === "DatePicker" || inputType === "DateRange";
7899
7924
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(PopoverPrimitive11.Root, { open: valueOpen, onOpenChange: setValueOpen, children: [
7900
7925
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(PopoverPrimitive11.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
@@ -7910,7 +7935,8 @@ var AdvancedRow = ({
7910
7935
  "text-sm font-regular leading-sm whitespace-nowrap truncate text-left",
7911
7936
  hasValue ? "text-[var(--color-foreground)]" : "text-[var(--color-muted-foreground)]"
7912
7937
  ),
7913
- children: hasValue ? displayValue : "Enter a value"
7938
+ title: hasValue ? displayValue : void 0,
7939
+ children: hasValue ? displayValue : "Select a value"
7914
7940
  }
7915
7941
  ),
7916
7942
  /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "flex items-center gap-xs shrink-0", children: [
@@ -8337,6 +8363,7 @@ var DraftRow = ({
8337
8363
  // src/components/ui/filter/summary-chip.tsx
8338
8364
  var React52 = __toESM(require("react"));
8339
8365
  var PopoverPrimitive13 = __toESM(require("@radix-ui/react-popover"));
8366
+ var TooltipPrimitive3 = __toESM(require("@radix-ui/react-tooltip"));
8340
8367
  var import_icons37 = require("@l3mpire/icons");
8341
8368
  var import_jsx_runtime59 = require("react/jsx-runtime");
8342
8369
  var ghostBtn2 = [
@@ -8355,7 +8382,8 @@ var SummaryChip = ({
8355
8382
  className,
8356
8383
  open: openProp,
8357
8384
  onOpenChange,
8358
- collisionBoundary
8385
+ collisionBoundary,
8386
+ tooltipContent
8359
8387
  }) => {
8360
8388
  const [uncontrolledOpen, setUncontrolledOpen] = React52.useState(false);
8361
8389
  const isControlled = openProp !== void 0;
@@ -8496,24 +8524,37 @@ var SummaryChip = ({
8496
8524
  node.id
8497
8525
  );
8498
8526
  };
8499
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(PopoverPrimitive13.Root, { open, onOpenChange: setOpen, children: [
8500
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(PopoverPrimitive13.Trigger, { asChild: true, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
8501
- "button",
8527
+ const trigger = children ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
8528
+ "button",
8529
+ {
8530
+ type: "button",
8531
+ className: cn(
8532
+ "inline-flex items-center gap-sm px-base py-sm",
8533
+ "min-h-[32px] max-h-[32px]",
8534
+ "bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
8535
+ "border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
8536
+ "cursor-pointer transition-colors",
8537
+ "hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
8538
+ className
8539
+ ),
8540
+ children: [
8541
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_icons37.Icon, { icon: import_icons37.faFilterOutline, size: "sm", className: "shrink-0 text-[var(--color-foreground)]" }),
8542
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-sm font-semibold leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: "Filters" }),
8543
+ count > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-[10px] font-semibold leading-2xs text-filter-chip-badge-text", children: count }) })
8544
+ ]
8545
+ }
8546
+ );
8547
+ const hasTooltip = tooltipContent && !open;
8548
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TooltipPrimitive3.Provider, { delayDuration: 300, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TooltipPrimitive3.Root, { open: hasTooltip ? void 0 : false, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(PopoverPrimitive13.Root, { open, onOpenChange: setOpen, children: [
8549
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TooltipPrimitive3.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(PopoverPrimitive13.Trigger, { asChild: true, children: trigger }) }),
8550
+ hasTooltip && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TooltipPrimitive3.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
8551
+ TooltipPrimitive3.Content,
8502
8552
  {
8503
- type: "button",
8504
- className: cn(
8505
- "inline-flex items-center gap-sm px-base py-sm",
8506
- "min-h-[32px] max-h-[32px]",
8507
- "bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
8508
- "border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
8509
- "cursor-pointer transition-colors",
8510
- "hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
8511
- className
8512
- ),
8553
+ sideOffset: 4,
8554
+ className: "z-50 px-base py-sm rounded-md shadow-lg bg-tooltip-default-bg text-tooltip-default-text text-sm font-regular leading-sm max-w-[320px] data-[state=delayed-open]:animate-[tooltip-in_150ms_ease-out] data-[state=closed]:animate-[tooltip-out_100ms_ease-in]",
8513
8555
  children: [
8514
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_icons37.Icon, { icon: import_icons37.faFilterOutline, size: "sm", className: "shrink-0 text-[var(--color-foreground)]" }),
8515
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-sm font-semibold leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: "Filters" }),
8516
- count > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-[10px] font-semibold leading-2xs text-filter-chip-badge-text", children: count }) })
8556
+ tooltipContent,
8557
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TooltipPrimitive3.Arrow, { className: "fill-tooltip-default-bg" })
8517
8558
  ]
8518
8559
  }
8519
8560
  ) }),
@@ -8582,7 +8623,7 @@ var SummaryChip = ({
8582
8623
  ]
8583
8624
  }
8584
8625
  ) })
8585
- ] });
8626
+ ] }) }) });
8586
8627
  };
8587
8628
  SummaryChip.displayName = "SummaryChip";
8588
8629
  var DraftRow2 = ({ properties, onSelect, open: openProp, onOpenChange }) => {
@@ -8744,7 +8785,7 @@ var FilterSystem = ({
8744
8785
  const advancedFilterCount = filterState.advancedFilters.length;
8745
8786
  const showAdvancedChip = hasAdvanced || advancedOpen;
8746
8787
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(FilterBar, { ref: containerRef, className, children: [
8747
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(FilterBarLeft, { className: "flex-nowrap flex-1 min-w-0 overflow-x-auto scrollbar-none outline-none [&>*]:shrink-0", children: [
8788
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(FilterBarLeft, { className: "flex-wrap flex-1 min-w-0", children: [
8748
8789
  children,
8749
8790
  sortFields && filterState.sort && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8750
8791
  SortButton,
@@ -8773,12 +8814,12 @@ var FilterSystem = ({
8773
8814
  open: summaryOpen,
8774
8815
  onOpenChange: setSummaryOpen,
8775
8816
  collisionBoundary,
8817
+ tooltipContent: totalCount > 0 ? buildFilterTooltip([...filterState.basicFilters, ...filterState.advancedFilters], properties) : void 0,
8776
8818
  children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8777
8819
  FilterBarButton,
8778
8820
  {
8779
8821
  iconOnly: isIconOnly,
8780
- count: totalCount > 0 ? totalCount : void 0,
8781
- title: buildFilterSummary(filterState.basicFilters, filterState.advancedFilters.length, properties)
8822
+ count: totalCount > 0 ? totalCount : void 0
8782
8823
  }
8783
8824
  )
8784
8825
  }
@@ -8855,23 +8896,46 @@ var FilterSystem = ({
8855
8896
  }
8856
8897
  )
8857
8898
  ] }),
8858
- actions && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FilterBarRight, { className: "shrink-0 -ml-2xl pl-2xl relative z-10 bg-[linear-gradient(to_right,transparent_0px,var(--filter-bar-bg,var(--color-background,#fff))_24px)]", children: actions })
8899
+ actions && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FilterBarRight, { className: "shrink-0", children: actions })
8859
8900
  ] });
8860
8901
  };
8861
8902
  FilterSystem.displayName = "FilterSystem";
8862
- function buildFilterSummary(filters, advancedCount, properties) {
8863
- if (filters.length === 0 && advancedCount === 0) return void 0;
8864
- const lines = [];
8865
- for (const f of filters) {
8866
- const prop = properties.find((p) => p.id === f.propertyId);
8867
- if (!prop) continue;
8868
- const val = formatFilterValue(f.value, prop.dynamicOptions);
8869
- lines.push(val ? `${prop.label} ${f.operator} ${val}` : `${prop.label} ${f.operator ?? ""}`);
8870
- }
8871
- if (advancedCount > 0) {
8872
- lines.push(`+ ${advancedCount} advanced filter${advancedCount > 1 ? "s" : ""}`);
8873
- }
8874
- return lines.join("\n");
8903
+ function buildFilterTooltip(nodes, properties) {
8904
+ const renderNodes = (items, depth) => {
8905
+ const result = [];
8906
+ for (let i = 0; i < items.length; i++) {
8907
+ const node = items[i];
8908
+ const connector = i > 0 ? (node.logicOperator ?? "and").toUpperCase() : null;
8909
+ if ("children" in node && node.type === "group") {
8910
+ if (connector) {
8911
+ result.push(
8912
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { style: { paddingLeft: depth * 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "opacity-50 text-xs", children: connector }) }, `${node.id}-conn`)
8913
+ );
8914
+ }
8915
+ result.push(...renderNodes(node.children, depth + 1));
8916
+ } else {
8917
+ const f = node;
8918
+ const prop = properties.find((p) => p.id === f.propertyId);
8919
+ if (!prop) continue;
8920
+ const val = formatFilterValue(f.value, prop.dynamicOptions, true);
8921
+ result.push(
8922
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: { paddingLeft: depth * 8 }, children: [
8923
+ connector && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "opacity-50 text-xs", children: [
8924
+ connector,
8925
+ " "
8926
+ ] }),
8927
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "font-semibold", children: prop.label }),
8928
+ " ",
8929
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "opacity-60", children: f.operator }),
8930
+ " ",
8931
+ val && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: val })
8932
+ ] }, f.id)
8933
+ );
8934
+ }
8935
+ }
8936
+ return result;
8937
+ };
8938
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "flex flex-col gap-2xs", children: renderNodes(nodes, 0) });
8875
8939
  }
8876
8940
  // Annotate the CommonJS export names for ESM import in node:
8877
8941
  0 && (module.exports = {