@proteos/ui 0.55.0 → 0.56.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.cjs CHANGED
@@ -6218,7 +6218,8 @@ var OPERATORS = [
6218
6218
  "relation",
6219
6219
  "user",
6220
6220
  "principal",
6221
- "contact-address"
6221
+ "contact-address",
6222
+ "array"
6222
6223
  ]
6223
6224
  },
6224
6225
  {
@@ -6234,10 +6235,19 @@ var OPERATORS = [
6234
6235
  "relation",
6235
6236
  "user",
6236
6237
  "principal",
6237
- "contact-address"
6238
+ "contact-address",
6239
+ "array"
6238
6240
  ]
6239
6241
  },
6240
6242
  { id: "contains", label: "contains", arity: 1, types: ["string", "array", "contact-address"] },
6243
+ {
6244
+ id: "not_contains",
6245
+ label: "does not contain",
6246
+ arity: 1,
6247
+ types: ["string", "array", "contact-address"]
6248
+ },
6249
+ // Array-only: "has every one of these". On a scalar the backend rejects it.
6250
+ { id: "contains_all", label: "has all of", arity: "n", types: ["array"] },
6241
6251
  { id: "starts_with", label: "starts with", arity: 1, types: ["string", "contact-address"] },
6242
6252
  { id: "ends_with", label: "ends with", arity: 1, types: ["string", "contact-address"] },
6243
6253
  {
@@ -6300,14 +6310,33 @@ var OP_LABEL_OVERRIDES = {
6300
6310
  integer: { gt: "is greater than", lt: "is less than", eq: "equals", ne: "does not equal" },
6301
6311
  currency: { gt: "is greater than", lt: "is less than", eq: "equals", ne: "does not equal" },
6302
6312
  datetime: { eq: "is on", ne: "is not on", gt: "is after", lt: "is before" },
6303
- array: { contains: "contains", empty: "is empty", not_empty: "is not empty" },
6313
+ // Arrays filter by set membership, in the words every CRM uses for it.
6314
+ array: {
6315
+ contains: "has",
6316
+ not_contains: "does not have",
6317
+ in: "has any of",
6318
+ not_in: "has none of",
6319
+ contains_all: "has all of",
6320
+ empty: "is empty",
6321
+ not_empty: "is not empty"
6322
+ },
6304
6323
  boolean: { eq: "is", ne: "is not" }
6305
6324
  };
6325
+ var OP_ORDER_OVERRIDES = {
6326
+ array: ["contains", "not_contains", "in", "contains_all", "not_in", "empty", "not_empty"]
6327
+ };
6306
6328
  function operatorsForType(type) {
6307
- return OPERATORS.filter((op) => op.types.includes(type)).map((op) => {
6329
+ const ops = OPERATORS.filter((op) => op.types.includes(type)).map((op) => {
6308
6330
  const override = OP_LABEL_OVERRIDES[type]?.[op.id];
6309
6331
  return override ? { ...op, label: override } : op;
6310
6332
  });
6333
+ const order = OP_ORDER_OVERRIDES[type];
6334
+ if (!order) return ops;
6335
+ return [...ops].sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id));
6336
+ }
6337
+ function isEnumLike(field) {
6338
+ if (field.type === "enum") return true;
6339
+ return field.type === "array" && (field.options?.length ?? 0) > 0;
6311
6340
  }
6312
6341
  function operatorById(id) {
6313
6342
  return OPERATORS.find((o) => o.id === id);
@@ -6379,7 +6408,7 @@ function ChipItem({
6379
6408
  const custom = effectiveRenderer({ field, operator, value });
6380
6409
  if (custom !== void 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
6381
6410
  }
6382
- if (field.type === "enum") {
6411
+ if (isEnumLike(field)) {
6383
6412
  const option = findEnumOption(field, value);
6384
6413
  return /* @__PURE__ */ jsxRuntime.jsx(
6385
6414
  Badge,
@@ -6407,7 +6436,7 @@ function formatValue(field, operator, value) {
6407
6436
  if (arity === "n") {
6408
6437
  const arr = Array.isArray(value) ? value : typeof value === "string" && value.length > 0 ? value.split(",") : [];
6409
6438
  if (arr.length === 0) return "\u2014";
6410
- if (field.type === "enum") {
6439
+ if (isEnumLike(field)) {
6411
6440
  const labels = arr.map((v) => findEnumOption(field, v)?.label ?? v);
6412
6441
  return labels.length <= 2 ? labels.join(", ") : `${labels[0]}, ${labels[1]} +${labels.length - 2}`;
6413
6442
  }
@@ -6415,7 +6444,7 @@ function formatValue(field, operator, value) {
6415
6444
  }
6416
6445
  if (field.type === "boolean") return value === true || value === "true" ? "true" : "false";
6417
6446
  if (value === "" || value == null) return "\u2014";
6418
- if (field.type === "enum") {
6447
+ if (isEnumLike(field)) {
6419
6448
  return findEnumOption(field, String(value))?.label ?? String(value);
6420
6449
  }
6421
6450
  if (field.type === "number" || field.type === "integer") {
@@ -6663,7 +6692,7 @@ function FilterValueInput({
6663
6692
  }
6664
6693
  const leaf = (() => {
6665
6694
  if (arity === "n") {
6666
- if (field.type === "enum") {
6695
+ if (isEnumLike(field)) {
6667
6696
  return /* @__PURE__ */ jsxRuntime.jsx(
6668
6697
  EnumMultiValue,
6669
6698
  {
@@ -6690,7 +6719,7 @@ function FilterValueInput({
6690
6719
  }
6691
6720
  );
6692
6721
  }
6693
- if (field.type === "enum") {
6722
+ if (isEnumLike(field)) {
6694
6723
  return /* @__PURE__ */ jsxRuntime.jsx(
6695
6724
  EnumSingleValue,
6696
6725
  {
@@ -6851,7 +6880,9 @@ function placeholderFor(field, operator) {
6851
6880
  if (field.type === "number" || field.type === "integer" || field.type === "currency") return "0";
6852
6881
  if (operator === "starts_with") return "starts with\u2026";
6853
6882
  if (operator === "ends_with") return "ends with\u2026";
6854
- if (operator === "contains") return "contains\u2026";
6883
+ if (operator === "contains") return field.type === "array" ? "has\u2026" : "contains\u2026";
6884
+ if (operator === "not_contains")
6885
+ return field.type === "array" ? "does not have\u2026" : "does not contain\u2026";
6855
6886
  return "value";
6856
6887
  }
6857
6888
  function OperatorPicker({