@uniformdev/context-ui 20.7.1-alpha.12 → 20.7.1-alpha.121

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.js CHANGED
@@ -46,6 +46,8 @@ __export(src_exports, {
46
46
  addEnrichmentLink: () => addEnrichmentLink,
47
47
  contextCriteriaMenuOperators: () => contextCriteriaMenuOperators,
48
48
  convertErrorsToObj: () => convertErrorsToObj,
49
+ enrichmentCriteriaMenuOperators: () => enrichmentCriteriaMenuOperators,
50
+ getValidCriteriaOperatorsFor: () => getValidCriteriaOperatorsFor,
49
51
  isEnrichmentTagData: () => isEnrichmentTagData,
50
52
  isPersonalizationCriteriaData: () => isPersonalizationCriteriaData,
51
53
  opHasRhs: () => opHasRhs,
@@ -341,23 +343,43 @@ var contextCriteriaMenuOperators = [
341
343
  {
342
344
  name: "has the weakest score",
343
345
  value: "-"
344
- },
346
+ }
347
+ ];
348
+ var enrichmentCriteriaMenuOperators = [
349
+ ...contextCriteriaMenuOperators,
345
350
  {
346
351
  name: "has strongest category score",
347
352
  value: "^"
348
353
  }
349
354
  ];
350
- function CriteriaOperatorMenu({ onChange, value, ...props }) {
355
+ var quirkCriteriaMenuOperators = [
356
+ {
357
+ name: "=",
358
+ description: "equals",
359
+ value: "="
360
+ },
361
+ {
362
+ name: "\u2260",
363
+ description: "not equal",
364
+ value: "!="
365
+ }
366
+ ];
367
+ function getValidCriteriaOperatorsFor(rhsType) {
368
+ return rhsType === "QUIRK" ? quirkCriteriaMenuOperators : rhsType === "ENR" ? enrichmentCriteriaMenuOperators : contextCriteriaMenuOperators;
369
+ }
370
+ function CriteriaOperatorMenu({ onChange, value, rhsType, ...props }) {
351
371
  var _a, _b;
372
+ const operators = getValidCriteriaOperatorsFor(rhsType);
352
373
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
353
374
  import_design_system2.InputComboBox,
354
375
  {
355
376
  ...props,
377
+ isDisabled: props.disabled,
356
378
  value: {
357
- label: (_b = (_a = contextCriteriaMenuOperators.find((e) => e.value === value)) == null ? void 0 : _a.name) != null ? _b : value,
379
+ label: (_b = (_a = operators.find((e) => e.value === value)) == null ? void 0 : _a.name) != null ? _b : value,
358
380
  value
359
381
  },
360
- options: contextCriteriaMenuOperators.map((option) => ({
382
+ options: operators.map((option) => ({
361
383
  label: option.description ? `${option.name}:${option.description}` : option.name,
362
384
  value: option.value
363
385
  })),
@@ -589,24 +611,29 @@ function useDimensionsDataContext() {
589
611
 
590
612
  // src/components/DimensionMenu/CriteriaMatchMenu.tsx
591
613
  var import_design_system6 = require("@uniformdev/design-system");
592
- var import_react10 = require("react");
614
+ var import_react12 = require("react");
593
615
 
594
616
  // src/components/DimensionMenu/DimensionGroupHeading.tsx
595
617
  var import_design_system4 = require("@uniformdev/design-system");
596
618
 
597
619
  // src/components/DimensionMenu/utils.ts
620
+ var import_react9 = require("react");
598
621
  function dimensionToMenuOption(dimension) {
622
+ if ("dim" in dimension) {
623
+ return {
624
+ label: dimension.displayName,
625
+ value: dimension.dim,
626
+ original: dimension
627
+ };
628
+ }
629
+ const quirk = dimension;
599
630
  return {
600
- label: dimension.displayName,
601
- value: dimension.dim,
602
- isDisabled: false
631
+ label: `Quirk:${quirk.name}`,
632
+ value: quirk.id,
633
+ original: quirk
603
634
  };
604
635
  }
605
- function dimensionIcon(displayName) {
606
- if (!displayName) {
607
- return "unavailable";
608
- }
609
- const [type] = displayName.split(":");
636
+ function dimensionIcon(type) {
610
637
  switch (type.toLowerCase()) {
611
638
  case "signal":
612
639
  return "data";
@@ -618,25 +645,42 @@ function dimensionIcon(displayName) {
618
645
  return "user-list";
619
646
  }
620
647
  }
621
- function groupDimensions(dimensions) {
622
- const result = [];
623
- let lastType = "";
624
- for (const dim of dimensions) {
625
- const [type] = dim.displayName.split(":");
626
- if (lastType !== type) {
627
- result.push({ label: type, options: [] });
628
- lastType = type;
648
+ function useGroupedDimensions(dimensions, quirks) {
649
+ return (0, import_react9.useMemo)(() => {
650
+ const result = [];
651
+ let lastType = "";
652
+ for (const dim of dimensions) {
653
+ const { type } = dimensionDisplayName(dim.displayName);
654
+ if (lastType !== type) {
655
+ result.push({ label: type != null ? type : "", options: [] });
656
+ lastType = type != null ? type : "";
657
+ }
658
+ result[result.length - 1].options.push(dimensionToMenuOption(dim));
659
+ }
660
+ if (quirks == null ? void 0 : quirks.length) {
661
+ result.push({
662
+ label: "Quirks",
663
+ options: quirks.map(dimensionToMenuOption)
664
+ });
629
665
  }
630
- result[result.length - 1].options.push(dimensionToMenuOption(dim));
666
+ return result;
667
+ }, [dimensions, quirks]);
668
+ }
669
+ function dimensionDisplayName(displayName) {
670
+ if (!displayName) {
671
+ return {};
631
672
  }
632
- return result;
673
+ const colonIndex = displayName.indexOf(":");
674
+ const type = colonIndex >= 0 ? displayName.substring(0, colonIndex) : void 0;
675
+ const name = colonIndex >= 0 ? displayName.substring(colonIndex + 1) : displayName;
676
+ return { type, name };
633
677
  }
634
678
 
635
679
  // src/components/DimensionMenu/DimensionGroupHeading.tsx
636
680
  var import_jsx_runtime7 = require("@emotion/react/jsx-runtime");
637
681
  var DimensionGroupHeading = (props) => {
638
- var _a;
639
682
  const { data, getStyles, className } = props;
683
+ const { type } = dimensionDisplayName(data.label);
640
684
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
641
685
  "div",
642
686
  {
@@ -651,7 +695,7 @@ var DimensionGroupHeading = (props) => {
651
695
  {
652
696
  css: { color: "var(--gray-500)", display: "flex", alignItems: "center", gap: "var(--spacing-xs)" },
653
697
  children: [
654
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Icon, { icon: dimensionIcon((_a = data.label) != null ? _a : ""), iconColor: "currentColor", size: 16 }),
698
+ type ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Icon, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
655
699
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: data.label })
656
700
  ]
657
701
  }
@@ -661,14 +705,14 @@ var DimensionGroupHeading = (props) => {
661
705
  };
662
706
 
663
707
  // src/components/DimensionMenu/DimensionMenuErrorMessage.tsx
664
- var import_react9 = require("@emotion/react");
708
+ var import_react10 = require("@emotion/react");
665
709
  var import_jsx_runtime8 = require("@emotion/react/jsx-runtime");
666
710
  function DimensionMenuErrorMessage({ message }) {
667
711
  if (!message) return null;
668
712
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
669
713
  "div",
670
714
  {
671
- css: import_react9.css`
715
+ css: import_react10.css`
672
716
  color: var(--brand-primary-2);
673
717
  font-size: var(--fs-xs);
674
718
  position: absolute;
@@ -682,9 +726,8 @@ function DimensionMenuErrorMessage({ message }) {
682
726
  // src/components/DimensionMenu/DimensionOption.tsx
683
727
  var import_jsx_runtime9 = require("@emotion/react/jsx-runtime");
684
728
  var DimensionOption = (props) => {
685
- var _a, _b;
686
729
  const { data, getStyles, cx, isDisabled, isFocused, isSelected, className, innerRef, innerProps } = props;
687
- const [, value] = (_b = (_a = data.label) == null ? void 0 : _a.split(":")) != null ? _b : [];
730
+ const { name } = dimensionDisplayName(data.label);
688
731
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
689
732
  "div",
690
733
  {
@@ -701,38 +744,44 @@ var DimensionOption = (props) => {
701
744
  ref: innerRef,
702
745
  "aria-disabled": isDisabled,
703
746
  ...innerProps,
704
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { css: { color: "var(--gray-700)" }, children: value != null ? value : data.label })
747
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { css: { color: "var(--gray-700)" }, children: name != null ? name : data.label })
705
748
  }
706
749
  );
707
750
  };
708
751
 
709
752
  // src/components/DimensionMenu/DimensionValue.tsx
753
+ var import_react11 = require("@emotion/react");
710
754
  var import_design_system5 = require("@uniformdev/design-system");
711
755
  var import_jsx_runtime10 = require("@emotion/react/jsx-runtime");
756
+ var styles = {
757
+ dimensionValueWrapper: import_react11.css`
758
+ white-space: normal;
759
+ overflow: hidden;
760
+ `,
761
+ dimensionName: import_react11.css`
762
+ color: var(--gray-500);
763
+ display: flex;
764
+ align-items: center;
765
+ gap: var(--spacing-xs);
766
+ `,
767
+ dimensionValue: import_react11.css`
768
+ color: var(--gray-700);
769
+ text-overflow: ellipsis;
770
+ overflow: hidden;
771
+ white-space: nowrap;
772
+ `
773
+ };
712
774
  function DimensionValue({ displayName }) {
713
- const [type, name] = displayName.split(":");
714
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
715
- "div",
716
- {
717
- css: {
718
- whiteSpace: "normal",
719
- overflow: "hidden"
720
- },
721
- children: [
722
- name ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
723
- "small",
724
- {
725
- css: { color: "var(--gray-500)", display: "flex", alignItems: "center", gap: "var(--spacing-xs)" },
726
- children: [
727
- type ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system5.Icon, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
728
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-testid": "dimension-name", children: type })
729
- ]
730
- }
731
- ) : null,
732
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { css: { color: "var(--gray-700)" }, "data-testid": "dimension-value", children: name != null ? name : type })
733
- ]
734
- }
735
- );
775
+ var _a;
776
+ const { type, name } = dimensionDisplayName(displayName);
777
+ const tooltip = (_a = name != null ? name : type) != null ? _a : "";
778
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { css: styles.dimensionValueWrapper, children: [
779
+ type ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("small", { css: styles.dimensionName, children: [
780
+ type ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system5.Icon, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
781
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-testid": "dimension-name", children: type })
782
+ ] }) : null,
783
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system5.Tooltip, { title: tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { css: styles.dimensionValue, "data-testid": "dimension-value", children: name != null ? name : type }) })
784
+ ] });
736
785
  }
737
786
 
738
787
  // src/components/DimensionMenu/DimensionSingleValue.tsx
@@ -752,16 +801,27 @@ function CriteriaMatchMenu({
752
801
  ...props
753
802
  }) {
754
803
  var _a, _b;
755
- const [inputValue, setInputValue] = (0, import_react10.useState)(
804
+ const [inputValue, setInputValue] = (0, import_react12.useState)(
756
805
  typeof criteriaMatch.r !== "undefined" && isInt(criteriaMatch.r) !== null ? criteriaMatch.r.toString(10) : ""
757
806
  );
807
+ const currentInputValue = (0, import_react12.useRef)(inputValue);
808
+ currentInputValue.current = inputValue;
809
+ (0, import_react12.useEffect)(() => {
810
+ if (currentInputValue.current !== criteriaMatch.r && !criteriaMatch.rDim) {
811
+ setInputValue(
812
+ typeof criteriaMatch.r !== "undefined" && isInt(criteriaMatch.r) !== null ? criteriaMatch.r.toString(10) : ""
813
+ );
814
+ }
815
+ }, [criteriaMatch.r, criteriaMatch.rDim]);
758
816
  const rDim = criteriaMatch.rDim;
759
817
  const targetDim = criteriaMatch.rDim ? dimensions.dimIndex[criteriaMatch.rDim] : void 0;
818
+ const groupedDimensions = useGroupedDimensions(dimensions.dimensions, void 0);
760
819
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
761
820
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
762
821
  import_design_system6.InputComboBox,
763
822
  {
764
823
  ...props,
824
+ isDisabled: props.disabled,
765
825
  inputValue,
766
826
  menuShouldScrollIntoView: true,
767
827
  value: {
@@ -775,7 +835,7 @@ function CriteriaMatchMenu({
775
835
  value: "",
776
836
  isDisabled: true
777
837
  },
778
- ...groupDimensions(dimensions.dimensions)
838
+ ...groupedDimensions
779
839
  ],
780
840
  styles: {
781
841
  ...props.styles,
@@ -854,14 +914,25 @@ function isInt(value) {
854
914
  // src/components/DimensionMenu/DimensionMenu.tsx
855
915
  var import_design_system7 = require("@uniformdev/design-system");
856
916
  var import_jsx_runtime13 = require("@emotion/react/jsx-runtime");
857
- function DimensionMenu({ onChange, value, dimensions, errorMessage, ...props }) {
917
+ function DimensionMenu({
918
+ onChange,
919
+ value,
920
+ dimensions,
921
+ errorMessage,
922
+ quirks,
923
+ ...props
924
+ }) {
925
+ const groupedDimensions = useGroupedDimensions(dimensions, quirks);
926
+ const valueAsMenuOption = value ? dimensionToMenuOption(value) : void 0;
858
927
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
859
928
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
860
929
  import_design_system7.InputComboBox,
861
930
  {
862
931
  ...props,
863
- value: value ? dimensionToMenuOption(value) : void 0,
864
- options: groupDimensions(dimensions),
932
+ isDisabled: props.disabled,
933
+ value: valueAsMenuOption,
934
+ options: groupedDimensions,
935
+ getOptionValue: (option) => option.label,
865
936
  styles: {
866
937
  ...props.styles,
867
938
  valueContainer: (provided, state) => {
@@ -874,8 +945,10 @@ function DimensionMenu({ onChange, value, dimensions, errorMessage, ...props })
874
945
  }
875
946
  },
876
947
  onChange: (e) => {
877
- if (e) {
878
- onChange(dimensions.find((d) => d.dim === e.value));
948
+ if (e == null ? void 0 : e.original) {
949
+ onChange(e.original);
950
+ } else {
951
+ onChange(void 0);
879
952
  }
880
953
  },
881
954
  components: {
@@ -895,8 +968,8 @@ var import_CgChevronRight = require("@react-icons/all-files/cg/CgChevronRight");
895
968
  var import_design_system8 = require("@uniformdev/design-system");
896
969
 
897
970
  // src/components/EditLink/EditLink.styles.ts
898
- var import_react11 = require("@emotion/react");
899
- var editLink = import_react11.css`
971
+ var import_react13 = require("@emotion/react");
972
+ var editLink = import_react13.css`
900
973
  display: flex;
901
974
  align-items: center;
902
975
  font-weight: var(--fw-bold);
@@ -929,16 +1002,16 @@ var EditLink = ({ linkTo, name, linkText = `Edit ${name} Component` }) => {
929
1002
  };
930
1003
 
931
1004
  // src/components/EnrichmentTag/EnrichmentTag.tsx
932
- var import_react12 = require("@emotion/react");
1005
+ var import_react14 = require("@emotion/react");
933
1006
  var import_CgCloseO = require("@react-icons/all-files/cg/CgCloseO");
934
1007
  var import_CgMathMinus = require("@react-icons/all-files/cg/CgMathMinus");
935
1008
  var import_CgMathPlus = require("@react-icons/all-files/cg/CgMathPlus");
936
1009
  var import_context = require("@uniformdev/context");
937
1010
  var import_design_system9 = require("@uniformdev/design-system");
938
1011
  var import_immer = require("immer");
939
- var import_react13 = require("react");
1012
+ var import_react15 = require("react");
940
1013
  var import_jsx_runtime15 = require("@emotion/react/jsx-runtime");
941
- var addEnrichmentLink = import_react12.css`
1014
+ var addEnrichmentLink = import_react14.css`
942
1015
  flex: 2;
943
1016
  display: flex;
944
1017
  width: 50%;
@@ -957,19 +1030,19 @@ var EnrichmentTag = ({
957
1030
  displayTitle = true
958
1031
  }) => {
959
1032
  const { loading, result: dimensions, error } = useDimensions(contextConfig);
960
- const allEnrichments = (0, import_react13.useMemo)(() => {
1033
+ const allEnrichments = (0, import_react15.useMemo)(() => {
961
1034
  if (dimensions) return dimensions.dimensions.filter((dimension) => dimension.category === "ENR");
962
1035
  }, [dimensions]);
963
- const remainingEnrichments = (0, import_react13.useMemo)(() => {
1036
+ const remainingEnrichments = (0, import_react15.useMemo)(() => {
964
1037
  if (!value) return allEnrichments;
965
1038
  if (allEnrichments)
966
1039
  return allEnrichments.filter(
967
1040
  (enr) => !value.some((val) => (0, import_context.getEnrichmentVectorKey)(val.cat, val.key) === enr.dim)
968
1041
  );
969
1042
  }, [allEnrichments, value]);
970
- const [selectValue, setSelectValue] = (0, import_react13.useState)("");
971
- const [score, setScore] = (0, import_react13.useState)(50);
972
- const [showAddNewEnrichmentTagPanel, setShowAddNewEnrichmentTagPanel] = (0, import_react13.useState)(false);
1043
+ const [selectValue, setSelectValue] = (0, import_react15.useState)("");
1044
+ const [score, setScore] = (0, import_react15.useState)(50);
1045
+ const [showAddNewEnrichmentTagPanel, setShowAddNewEnrichmentTagPanel] = (0, import_react15.useState)(false);
973
1046
  const selectedEnrichment = allEnrichments == null ? void 0 : allEnrichments.find((dimension) => dimension.dim === selectValue);
974
1047
  const addEnrichment = () => {
975
1048
  const [cat, key] = selectValue.split("_");
@@ -1127,7 +1200,7 @@ var NoEnrichmentsView = ({ contextConfig }) => /* @__PURE__ */ (0, import_jsx_ru
1127
1200
  var getCappedValue = (value, maxCap = 100, minCap = 0) => {
1128
1201
  return Math.max(Math.min(value, maxCap), minCap);
1129
1202
  };
1130
- var scoreCounterMinusButtonStyles = import_react12.css`
1203
+ var scoreCounterMinusButtonStyles = import_react14.css`
1131
1204
  position: absolute;
1132
1205
  bottom: 0.875rem;
1133
1206
  left: var(--spacing-sm);
@@ -1140,7 +1213,7 @@ var scoreCounterMinusButtonStyles = import_react12.css`
1140
1213
  border: 1px solid var(--gray-300);
1141
1214
  border-radius: var(--rounded-full);
1142
1215
  `;
1143
- var scoreCounterPlusButtonStyles = import_react12.css`
1216
+ var scoreCounterPlusButtonStyles = import_react14.css`
1144
1217
  ${scoreCounterMinusButtonStyles}
1145
1218
  left: auto;
1146
1219
  right: var(--spacing-sm);
@@ -1288,7 +1361,7 @@ var SelectedEnrichments = ({ list, setList, dimIndex }) => {
1288
1361
 
1289
1362
  // src/components/PersonalizationCriteria/PersonalizationCriteria.tsx
1290
1363
  var import_design_system11 = require("@uniformdev/design-system");
1291
- var import_react16 = require("react");
1364
+ var import_react18 = require("react");
1292
1365
  var import_react_use = require("react-use");
1293
1366
  var yup = __toESM(require("yup"));
1294
1367
 
@@ -1304,20 +1377,20 @@ function opHasRhs(op) {
1304
1377
  }
1305
1378
 
1306
1379
  // src/components/PersonalizationCriteria/PersonalizationCriteriaStatic.tsx
1307
- var import_react15 = require("@emotion/react");
1380
+ var import_react17 = require("@emotion/react");
1308
1381
  var import_CgCloseO2 = require("@react-icons/all-files/cg/CgCloseO");
1309
1382
  var import_design_system10 = require("@uniformdev/design-system");
1310
1383
  var import_immer2 = require("immer");
1311
1384
 
1312
1385
  // src/components/PersonalizationCriteria/PersonalizationCriteriaStatic.styles.ts
1313
- var import_react14 = require("@emotion/react");
1386
+ var import_react16 = require("@emotion/react");
1314
1387
  var spaceBetweenCriteriaItems = "6rem";
1315
- var criteriaItem = import_react14.css`
1388
+ var criteriaItem = import_react16.css`
1316
1389
  position: relative;
1317
1390
  padding: var(--spacing-md) var(--spacing-base);
1318
1391
  border: 1px solid var(--gray-300);
1319
- box-shadow: var(--shadow-base);
1320
- background-color: white;
1392
+ box-shadow: var(--elevation-200);
1393
+ background-color: var(--white);
1321
1394
  border-radius: var(--rounded-base);
1322
1395
  margin-top: ${spaceBetweenCriteriaItems};
1323
1396
  display: flex;
@@ -1334,35 +1407,37 @@ var criteriaItem = import_react14.css`
1334
1407
  }
1335
1408
 
1336
1409
  &:first-of-type {
1337
- margin-top: var(--spacing-md);
1410
+ margin-top: 0;
1338
1411
  &:before {
1339
1412
  display: none;
1340
1413
  }
1341
1414
  }
1342
1415
  `;
1343
- var criteriaItemInner = import_react14.css`
1416
+ var criteriaItemInner = import_react16.css`
1344
1417
  display: flex;
1345
- gap: var(--spacing-base);
1418
+ row-gap: var(--spacing-base);
1419
+ column-gap: var(--spacing-xs);
1346
1420
  flex-grow: 1;
1347
1421
  flex-wrap: wrap;
1348
1422
  margin-right: var(--spacing-base);
1349
1423
  `;
1350
- var criteriaWrapper = import_react14.css`
1424
+ var criteriaWrapper = import_react16.css`
1351
1425
  width: 100%;
1352
1426
  display: flex;
1353
1427
  align-items: stretch;
1354
1428
  position: relative;
1355
1429
  `;
1356
- var criteriaOperandWrapper = import_react14.css`
1430
+ var criteriaOperandWrapper = import_react16.css`
1357
1431
  flex: 2;
1358
1432
  height: 52px;
1359
1433
  min-width: 200px;
1360
1434
  `;
1361
- var criteriaOperatorWrapper = import_react14.css`
1435
+ var criteriaOperatorWrapper = import_react16.css`
1362
1436
  flex: 1;
1437
+ flex-wrap: nowrap;
1363
1438
  min-width: 80px;
1364
1439
  `;
1365
- var expand = import_react14.css`
1440
+ var expand = import_react16.css`
1366
1441
  height: 100%;
1367
1442
  width: 100%;
1368
1443
  `;
@@ -1373,13 +1448,15 @@ var PersonalizationCriteriaStatic = ({
1373
1448
  value,
1374
1449
  setValue,
1375
1450
  dimensions,
1451
+ quirks,
1376
1452
  onMenuOpen,
1377
1453
  onMenuClose,
1378
1454
  onAddCriteria,
1379
1455
  onRemoveCriteria,
1380
1456
  displayTitle = true,
1381
1457
  components,
1382
- errors = {}
1458
+ errors = {},
1459
+ readOnly
1383
1460
  }) => {
1384
1461
  var _a;
1385
1462
  const currentValue = { crit: [], ...value };
@@ -1422,148 +1499,207 @@ var PersonalizationCriteriaStatic = ({
1422
1499
  fontSize: "var(--fs-md)",
1423
1500
  fontWeight: "var(--fw-bold)"
1424
1501
  },
1425
- children: "Personalize This"
1502
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Heading, { level: 5, withMarginBottom: false, children: "Personalization Variation" })
1426
1503
  }
1427
1504
  ) : null,
1428
- (components == null ? void 0 : components.CustomVariantName) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.CustomVariantName, {}) : null,
1429
- (components == null ? void 0 : components.ControlPercentage) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.ControlPercentage, {}) : null,
1430
- !currentValue.crit.length ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Callout, { title: "Default variant", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Paragraph, { children: 'This personalized variant has no match criteria and will be shown to any visitor that does not match any preceding variants. Ensure that default variants come last in the variant list. Personalize this variant by clicking "Add Criteria" to get started.' }) }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: currentValue.crit.map((currentCriteria, index) => {
1431
- var _a2, _b, _c, _d;
1432
- const critHasLhs = ((_a2 = currentCriteria.l) == null ? void 0 : _a2.length) > 0;
1433
- const critHasRhs = opHasRhs(currentCriteria.op);
1434
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { css: criteriaItem, "data-testid": "criteria-container", children: [
1435
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1436
- "div",
1437
- {
1438
- css: import_react15.css`
1439
- ${criteriaItemInner}/* grid-template-columns: minmax(0, 1fr) ${critHasRhs ? "minmax(0, 79px) minmax(0, 1fr)" : "minmax(0, 1fr)"} */
1440
- `,
1441
- className: "criteriaItemInner",
1442
- children: [
1443
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1444
- "div",
1445
- {
1446
- css: [criteriaWrapper, criteriaOperandWrapper],
1447
- className: "criteria-wrapper",
1448
- "data-testid": "select-criteria",
1449
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1450
- DimensionMenu,
1451
- {
1452
- errorMessage: (_b = errors.lhs) == null ? void 0 : _b[index],
1453
- css: expand,
1454
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1455
- dimensions: dimensions.dimensions,
1456
- onChange: (dim) => {
1457
- update({ ...currentCriteria, l: dim.dim }, index);
1458
- },
1459
- value: dimensions.dimIndex[currentCriteria.l],
1460
- onMenuOpen,
1461
- onMenuClose
1462
- }
1463
- )
1464
- }
1465
- ),
1466
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1467
- "div",
1468
- {
1469
- css: [criteriaWrapper, criteriaOperatorWrapper],
1470
- className: "criteria-wrapper",
1471
- "data-testid": "select-operator",
1472
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1473
- CriteriaOperatorMenu,
1474
- {
1475
- name: `op-${index}`,
1476
- css: expand,
1477
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1478
- value: currentCriteria.op,
1479
- onChange: (op) => {
1480
- if (op === "+" || op === "-") {
1481
- update({ ...currentCriteria, op, r: void 0, rDim: void 0 }, index);
1482
- } else {
1483
- update({ ...currentCriteria, op }, index);
1484
- }
1485
- },
1486
- onMenuOpen,
1487
- onMenuClose
1488
- }
1489
- )
1490
- }
1491
- ),
1492
- critHasRhs ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1493
- "div",
1494
- {
1495
- css: [criteriaWrapper, criteriaOperandWrapper],
1496
- className: "criteria-wrapper",
1497
- "data-testid": "select-match-criteria",
1498
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1499
- CriteriaMatchMenu,
1500
- {
1501
- errorMessage: (_c = errors.rhs) == null ? void 0 : _c[index],
1502
- css: expand,
1503
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1504
- criteriaMatch: currentCriteria,
1505
- onChange: (match) => {
1506
- update(match, index);
1507
- },
1508
- isDisabled: !critHasLhs,
1509
- dimensions,
1510
- onMenuOpen,
1511
- onMenuClose
1512
- }
1513
- )
1514
- }
1515
- ) : null
1516
- ]
1517
- }
1518
- ),
1519
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1520
- "button",
1521
- {
1522
- type: "button",
1523
- onClick: () => removeFromList(index),
1524
- title: `Delete Personalization`,
1525
- css: { backgroundColor: "transparent", backgroundImage: "none", borderWidth: 0 },
1526
- "data-testid": "button-delete",
1527
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Icon, { icon: import_CgCloseO2.CgCloseO, iconColor: "red", size: "1.5rem" })
1528
- }
1529
- ),
1530
- index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1531
- "div",
1532
- {
1533
- className: "criteria-group-operation",
1534
- css: {
1535
- position: "absolute",
1536
- top: "-4rem",
1537
- transform: "translateX(calc(1.5rem - 50%))"
1538
- },
1539
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1540
- import_design_system10.InputInlineSelect,
1505
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_design_system10.VerticalRhythm, { children: [
1506
+ (components == null ? void 0 : components.CustomVariantName) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.CustomVariantName, {}) : null,
1507
+ (components == null ? void 0 : components.ControlPercentage) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.ControlPercentage, {}) : null,
1508
+ !currentValue.crit.length ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Callout, { title: "Default variant", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Paragraph, { children: 'This personalized variant has no match criteria and will be shown to any visitor that does not match any preceding variants. Ensure that default variants come last in the variant list. Personalize this variant by clicking "Add Criteria" to get started.' }) }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: currentValue.crit.map((currentCriteria, index) => {
1509
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1510
+ const critHasLhs = ((_a2 = currentCriteria.l) == null ? void 0 : _a2.length) > 0;
1511
+ const critHasRhs = opHasRhs(currentCriteria.op);
1512
+ const selectedValueIsQuirk = "t" in currentCriteria && currentCriteria.t === "q";
1513
+ const currentDimension = selectedValueIsQuirk ? void 0 : dimensions.dimIndex[currentCriteria.l];
1514
+ const currentQuirk = selectedValueIsQuirk ? quirks == null ? void 0 : quirks.find((q) => q.id === currentCriteria.l) : void 0;
1515
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { css: criteriaItem, "data-testid": "criteria-container", children: [
1516
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { css: criteriaItemInner, className: "criteriaItemInner", children: [
1517
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1518
+ "div",
1541
1519
  {
1542
- "data-testid": "dropdown-button-combine",
1543
- disabled: index > 1,
1544
- value: (_d = currentValue.op) != null ? _d : "&",
1545
- options: [
1546
- { label: "AND", value: "&" },
1547
- { label: "OR", value: "|" }
1548
- ],
1549
- onChange: (v) => {
1550
- setOp(v.value);
1551
- }
1520
+ css: [criteriaWrapper, criteriaOperandWrapper],
1521
+ className: "criteria-wrapper",
1522
+ "data-testid": "select-criteria",
1523
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1524
+ DimensionMenu,
1525
+ {
1526
+ errorMessage: (_b = errors.lhs) == null ? void 0 : _b[index],
1527
+ css: expand,
1528
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1529
+ dimensions: dimensions.dimensions,
1530
+ quirks,
1531
+ onChange: (selection) => {
1532
+ if (!selection) {
1533
+ return;
1534
+ }
1535
+ if ("dim" in selection) {
1536
+ const validOperators = getValidCriteriaOperatorsFor(selection.category);
1537
+ const existingOpRemainsValid = !("t" in currentCriteria && currentCriteria.t === "q") && validOperators.some((op) => op.value === currentCriteria.op);
1538
+ const newCriteria = {
1539
+ ...currentCriteria,
1540
+ l: selection.dim,
1541
+ t: void 0,
1542
+ op: existingOpRemainsValid ? currentCriteria.op : ">",
1543
+ r: existingOpRemainsValid ? currentCriteria.r : 0,
1544
+ rDim: existingOpRemainsValid ? currentCriteria.rDim : void 0
1545
+ };
1546
+ update(newCriteria, index);
1547
+ } else {
1548
+ update({ ...currentCriteria, l: selection.id, t: "q", op: "=", r: "" }, index);
1549
+ }
1550
+ },
1551
+ value: currentDimension != null ? currentDimension : currentQuirk,
1552
+ onMenuOpen,
1553
+ onMenuClose,
1554
+ disabled: readOnly
1555
+ }
1556
+ )
1552
1557
  }
1553
- )
1554
- }
1555
- ) : null
1556
- ] }, index);
1557
- }) }),
1558
- dimensions.dimensions.length === 0 ? (components == null ? void 0 : components.NoDimensionsDefined) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.NoDimensionsDefined, {}) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Callout, { title: "Dimensions", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "You do not have any dimensions configured." }) }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1559
- import_design_system10.AddListButton,
1560
- {
1561
- "data-testid": "button-add-criteria",
1562
- className: "add-more",
1563
- buttonText: "Add Criteria",
1564
- onButtonClick: addToList
1565
- }
1566
- )
1558
+ ),
1559
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1560
+ "div",
1561
+ {
1562
+ css: [criteriaWrapper, criteriaOperatorWrapper],
1563
+ className: "criteria-wrapper",
1564
+ "data-testid": "select-operator",
1565
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1566
+ CriteriaOperatorMenu,
1567
+ {
1568
+ name: `op-${index}`,
1569
+ css: expand,
1570
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1571
+ value: currentCriteria.op,
1572
+ rhsType: currentQuirk ? "QUIRK" : currentDimension == null ? void 0 : currentDimension.category,
1573
+ onChange: (op) => {
1574
+ if (op === "+" || op === "-") {
1575
+ update({ ...currentCriteria, op, r: void 0, rDim: void 0 }, index);
1576
+ } else {
1577
+ update({ ...currentCriteria, op }, index);
1578
+ }
1579
+ },
1580
+ onMenuOpen,
1581
+ onMenuClose,
1582
+ disabled: readOnly
1583
+ }
1584
+ )
1585
+ }
1586
+ ),
1587
+ critHasRhs ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1588
+ "div",
1589
+ {
1590
+ css: [criteriaWrapper, criteriaOperandWrapper],
1591
+ className: "criteria-wrapper",
1592
+ "data-testid": "select-match-criteria",
1593
+ children: currentQuirk ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1594
+ "div",
1595
+ {
1596
+ css: import_react17.css`
1597
+ width: 100%;
1598
+ // InputSelect wrapper is unstylable so need a descendant selector
1599
+ // to full-width it
1600
+ & > * {
1601
+ width: 100%;
1602
+ }
1603
+ `,
1604
+ children: currentQuirk.options ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1605
+ import_design_system10.InputSelect,
1606
+ {
1607
+ label: "quirk match value",
1608
+ showLabel: false,
1609
+ value: (_c = currentCriteria.r) != null ? _c : "",
1610
+ errorMessage: (_d = errors.rhs) == null ? void 0 : _d[index],
1611
+ onChange: (e) => update({ ...currentCriteria, r: e.currentTarget.value }, index),
1612
+ options: [
1613
+ { label: "Select\u2026", value: "" },
1614
+ ...currentQuirk.options.map((o) => ({ label: o.name, value: o.value }))
1615
+ ],
1616
+ disabled: readOnly
1617
+ }
1618
+ ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1619
+ import_design_system10.Input,
1620
+ {
1621
+ type: "text",
1622
+ label: "quirk match value",
1623
+ showLabel: false,
1624
+ value: (_e = currentCriteria.r) != null ? _e : "",
1625
+ errorMessage: (_f = errors.rhs) == null ? void 0 : _f[index],
1626
+ onChange: (e) => update({ ...currentCriteria, r: e.currentTarget.value }, index),
1627
+ placeholder: "Enter a value",
1628
+ disabled: readOnly
1629
+ }
1630
+ )
1631
+ }
1632
+ ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1633
+ CriteriaMatchMenu,
1634
+ {
1635
+ errorMessage: (_g = errors.rhs) == null ? void 0 : _g[index],
1636
+ css: expand,
1637
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1638
+ criteriaMatch: currentCriteria,
1639
+ onChange: (match) => {
1640
+ update(match, index);
1641
+ },
1642
+ isDisabled: !critHasLhs,
1643
+ dimensions,
1644
+ onMenuOpen,
1645
+ onMenuClose,
1646
+ disabled: readOnly
1647
+ }
1648
+ )
1649
+ }
1650
+ ) : null
1651
+ ] }),
1652
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1653
+ "button",
1654
+ {
1655
+ type: "button",
1656
+ onClick: () => removeFromList(index),
1657
+ title: `Delete Personalization`,
1658
+ css: { backgroundColor: "transparent", backgroundImage: "none", borderWidth: 0 },
1659
+ "data-testid": "button-delete",
1660
+ disabled: readOnly,
1661
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Icon, { icon: import_CgCloseO2.CgCloseO, iconColor: "red", size: "1.5rem" })
1662
+ }
1663
+ ),
1664
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1665
+ "div",
1666
+ {
1667
+ className: "criteria-group-operation",
1668
+ css: {
1669
+ position: "absolute",
1670
+ top: "-4rem",
1671
+ transform: "translateX(calc(1.5rem - 50%))"
1672
+ },
1673
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1674
+ import_design_system10.InputInlineSelect,
1675
+ {
1676
+ "data-testid": "dropdown-button-combine",
1677
+ disabled: index > 1 || readOnly,
1678
+ value: (_h = currentValue.op) != null ? _h : "&",
1679
+ options: [
1680
+ { label: "AND", value: "&" },
1681
+ { label: "OR", value: "|" }
1682
+ ],
1683
+ onChange: (v) => {
1684
+ setOp(v.value);
1685
+ }
1686
+ }
1687
+ )
1688
+ }
1689
+ ) : null
1690
+ ] }, index);
1691
+ }) }),
1692
+ dimensions.dimensions.length === 0 && !(quirks == null ? void 0 : quirks.length) ? (components == null ? void 0 : components.NoDimensionsDefined) ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(components.NoDimensionsDefined, {}) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_design_system10.Callout, { title: "Dimensions", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "You do not have any dimensions configured." }) }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1693
+ import_design_system10.AddListButton,
1694
+ {
1695
+ "data-testid": "button-add-criteria",
1696
+ className: "add-more",
1697
+ buttonText: "Add Criteria",
1698
+ onButtonClick: addToList,
1699
+ disabled: readOnly
1700
+ }
1701
+ )
1702
+ ] })
1567
1703
  ] });
1568
1704
  };
1569
1705
 
@@ -1628,7 +1764,7 @@ var PersonalizationCriteria = ({
1628
1764
  ...staticProps
1629
1765
  }) => {
1630
1766
  var _a, _b;
1631
- const [validationError, setValidationError] = (0, import_react16.useState)(void 0);
1767
+ const [validationError, setValidationError] = (0, import_react18.useState)(void 0);
1632
1768
  const { loading, result: dimensions, error } = useDimensions(contextConfig);
1633
1769
  (0, import_react_use.useAsync)(async () => {
1634
1770
  if (value && dimensions) {
@@ -1692,7 +1828,7 @@ function ProjectUIVersion({ children, versionMap, contextConfig }) {
1692
1828
  }
1693
1829
 
1694
1830
  // src/hooks/useValidateContextConfig.ts
1695
- var import_react17 = require("react");
1831
+ var import_react19 = require("react");
1696
1832
 
1697
1833
  // src/utils/validateContextConfig.ts
1698
1834
  var import_api4 = require("@uniformdev/context/api");
@@ -1728,12 +1864,12 @@ var validateContextConfig = async (contextConfig) => {
1728
1864
 
1729
1865
  // src/hooks/useValidateContextConfig.ts
1730
1866
  var useValidateContextConfig = (contextConfig) => {
1731
- const [state, setState] = (0, import_react17.useState)({
1867
+ const [state, setState] = (0, import_react19.useState)({
1732
1868
  validating: false,
1733
1869
  error: void 0
1734
1870
  });
1735
1871
  const { apiKey, apiHost, projectId } = contextConfig || {};
1736
- (0, import_react17.useEffect)(() => {
1872
+ (0, import_react19.useEffect)(() => {
1737
1873
  if (!apiKey || !apiHost) {
1738
1874
  return;
1739
1875
  }
@@ -1774,6 +1910,8 @@ __reExport(src_exports, require("@uniformdev/design-system"), module.exports);
1774
1910
  addEnrichmentLink,
1775
1911
  contextCriteriaMenuOperators,
1776
1912
  convertErrorsToObj,
1913
+ enrichmentCriteriaMenuOperators,
1914
+ getValidCriteriaOperatorsFor,
1777
1915
  isEnrichmentTagData,
1778
1916
  isPersonalizationCriteriaData,
1779
1917
  opHasRhs,