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

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.esm.js CHANGED
@@ -289,23 +289,43 @@ var contextCriteriaMenuOperators = [
289
289
  {
290
290
  name: "has the weakest score",
291
291
  value: "-"
292
- },
292
+ }
293
+ ];
294
+ var enrichmentCriteriaMenuOperators = [
295
+ ...contextCriteriaMenuOperators,
293
296
  {
294
297
  name: "has strongest category score",
295
298
  value: "^"
296
299
  }
297
300
  ];
298
- function CriteriaOperatorMenu({ onChange, value, ...props }) {
301
+ var quirkCriteriaMenuOperators = [
302
+ {
303
+ name: "=",
304
+ description: "equals",
305
+ value: "="
306
+ },
307
+ {
308
+ name: "\u2260",
309
+ description: "not equal",
310
+ value: "!="
311
+ }
312
+ ];
313
+ function getValidCriteriaOperatorsFor(rhsType) {
314
+ return rhsType === "QUIRK" ? quirkCriteriaMenuOperators : rhsType === "ENR" ? enrichmentCriteriaMenuOperators : contextCriteriaMenuOperators;
315
+ }
316
+ function CriteriaOperatorMenu({ onChange, value, rhsType, ...props }) {
299
317
  var _a, _b;
318
+ const operators = getValidCriteriaOperatorsFor(rhsType);
300
319
  return /* @__PURE__ */ jsx6(
301
320
  InputComboBox,
302
321
  {
303
322
  ...props,
323
+ isDisabled: props.disabled,
304
324
  value: {
305
- label: (_b = (_a = contextCriteriaMenuOperators.find((e) => e.value === value)) == null ? void 0 : _a.name) != null ? _b : value,
325
+ label: (_b = (_a = operators.find((e) => e.value === value)) == null ? void 0 : _a.name) != null ? _b : value,
306
326
  value
307
327
  },
308
- options: contextCriteriaMenuOperators.map((option) => ({
328
+ options: operators.map((option) => ({
309
329
  label: option.description ? `${option.name}:${option.description}` : option.name,
310
330
  value: option.value
311
331
  })),
@@ -537,24 +557,29 @@ function useDimensionsDataContext() {
537
557
 
538
558
  // src/components/DimensionMenu/CriteriaMatchMenu.tsx
539
559
  import { InputComboBox as InputComboBox3 } from "@uniformdev/design-system";
540
- import { useState as useState5 } from "react";
560
+ import { useEffect as useEffect4, useRef, useState as useState5 } from "react";
541
561
 
542
562
  // src/components/DimensionMenu/DimensionGroupHeading.tsx
543
563
  import { Icon } from "@uniformdev/design-system";
544
564
 
545
565
  // src/components/DimensionMenu/utils.ts
566
+ import { useMemo } from "react";
546
567
  function dimensionToMenuOption(dimension) {
568
+ if ("dim" in dimension) {
569
+ return {
570
+ label: dimension.displayName,
571
+ value: dimension.dim,
572
+ original: dimension
573
+ };
574
+ }
575
+ const quirk = dimension;
547
576
  return {
548
- label: dimension.displayName,
549
- value: dimension.dim,
550
- isDisabled: false
577
+ label: `Quirk:${quirk.name}`,
578
+ value: quirk.id,
579
+ original: quirk
551
580
  };
552
581
  }
553
- function dimensionIcon(displayName) {
554
- if (!displayName) {
555
- return "unavailable";
556
- }
557
- const [type] = displayName.split(":");
582
+ function dimensionIcon(type) {
558
583
  switch (type.toLowerCase()) {
559
584
  case "signal":
560
585
  return "data";
@@ -566,25 +591,42 @@ function dimensionIcon(displayName) {
566
591
  return "user-list";
567
592
  }
568
593
  }
569
- function groupDimensions(dimensions) {
570
- const result = [];
571
- let lastType = "";
572
- for (const dim of dimensions) {
573
- const [type] = dim.displayName.split(":");
574
- if (lastType !== type) {
575
- result.push({ label: type, options: [] });
576
- lastType = type;
594
+ function useGroupedDimensions(dimensions, quirks) {
595
+ return useMemo(() => {
596
+ const result = [];
597
+ let lastType = "";
598
+ for (const dim of dimensions) {
599
+ const { type } = dimensionDisplayName(dim.displayName);
600
+ if (lastType !== type) {
601
+ result.push({ label: type != null ? type : "", options: [] });
602
+ lastType = type != null ? type : "";
603
+ }
604
+ result[result.length - 1].options.push(dimensionToMenuOption(dim));
577
605
  }
578
- result[result.length - 1].options.push(dimensionToMenuOption(dim));
606
+ if (quirks == null ? void 0 : quirks.length) {
607
+ result.push({
608
+ label: "Quirks",
609
+ options: quirks.map(dimensionToMenuOption)
610
+ });
611
+ }
612
+ return result;
613
+ }, [dimensions, quirks]);
614
+ }
615
+ function dimensionDisplayName(displayName) {
616
+ if (!displayName) {
617
+ return {};
579
618
  }
580
- return result;
619
+ const colonIndex = displayName.indexOf(":");
620
+ const type = colonIndex >= 0 ? displayName.substring(0, colonIndex) : void 0;
621
+ const name = colonIndex >= 0 ? displayName.substring(colonIndex + 1) : displayName;
622
+ return { type, name };
581
623
  }
582
624
 
583
625
  // src/components/DimensionMenu/DimensionGroupHeading.tsx
584
626
  import { jsx as jsx8, jsxs as jsxs3 } from "@emotion/react/jsx-runtime";
585
627
  var DimensionGroupHeading = (props) => {
586
- var _a;
587
628
  const { data, getStyles, className } = props;
629
+ const { type } = dimensionDisplayName(data.label);
588
630
  return /* @__PURE__ */ jsx8(
589
631
  "div",
590
632
  {
@@ -599,7 +641,7 @@ var DimensionGroupHeading = (props) => {
599
641
  {
600
642
  css: { color: "var(--gray-500)", display: "flex", alignItems: "center", gap: "var(--spacing-xs)" },
601
643
  children: [
602
- /* @__PURE__ */ jsx8(Icon, { icon: dimensionIcon((_a = data.label) != null ? _a : ""), iconColor: "currentColor", size: 16 }),
644
+ type ? /* @__PURE__ */ jsx8(Icon, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
603
645
  /* @__PURE__ */ jsx8("span", { children: data.label })
604
646
  ]
605
647
  }
@@ -630,9 +672,8 @@ function DimensionMenuErrorMessage({ message }) {
630
672
  // src/components/DimensionMenu/DimensionOption.tsx
631
673
  import { jsx as jsx10 } from "@emotion/react/jsx-runtime";
632
674
  var DimensionOption = (props) => {
633
- var _a, _b;
634
675
  const { data, getStyles, cx, isDisabled, isFocused, isSelected, className, innerRef, innerProps } = props;
635
- const [, value] = (_b = (_a = data.label) == null ? void 0 : _a.split(":")) != null ? _b : [];
676
+ const { name } = dimensionDisplayName(data.label);
636
677
  return /* @__PURE__ */ jsx10(
637
678
  "div",
638
679
  {
@@ -649,38 +690,44 @@ var DimensionOption = (props) => {
649
690
  ref: innerRef,
650
691
  "aria-disabled": isDisabled,
651
692
  ...innerProps,
652
- children: /* @__PURE__ */ jsx10("div", { css: { color: "var(--gray-700)" }, children: value != null ? value : data.label })
693
+ children: /* @__PURE__ */ jsx10("div", { css: { color: "var(--gray-700)" }, children: name != null ? name : data.label })
653
694
  }
654
695
  );
655
696
  };
656
697
 
657
698
  // src/components/DimensionMenu/DimensionValue.tsx
658
- import { Icon as Icon2 } from "@uniformdev/design-system";
699
+ import { css as css4 } from "@emotion/react";
700
+ import { Icon as Icon2, Tooltip } from "@uniformdev/design-system";
659
701
  import { jsx as jsx11, jsxs as jsxs4 } from "@emotion/react/jsx-runtime";
702
+ var styles = {
703
+ dimensionValueWrapper: css4`
704
+ white-space: normal;
705
+ overflow: hidden;
706
+ `,
707
+ dimensionName: css4`
708
+ color: var(--gray-500);
709
+ display: flex;
710
+ align-items: center;
711
+ gap: var(--spacing-xs);
712
+ `,
713
+ dimensionValue: css4`
714
+ color: var(--gray-700);
715
+ text-overflow: ellipsis;
716
+ overflow: hidden;
717
+ white-space: nowrap;
718
+ `
719
+ };
660
720
  function DimensionValue({ displayName }) {
661
- const [type, name] = displayName.split(":");
662
- return /* @__PURE__ */ jsxs4(
663
- "div",
664
- {
665
- css: {
666
- whiteSpace: "normal",
667
- overflow: "hidden"
668
- },
669
- children: [
670
- name ? /* @__PURE__ */ jsxs4(
671
- "small",
672
- {
673
- css: { color: "var(--gray-500)", display: "flex", alignItems: "center", gap: "var(--spacing-xs)" },
674
- children: [
675
- type ? /* @__PURE__ */ jsx11(Icon2, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
676
- /* @__PURE__ */ jsx11("span", { "data-testid": "dimension-name", children: type })
677
- ]
678
- }
679
- ) : null,
680
- /* @__PURE__ */ jsx11("div", { css: { color: "var(--gray-700)" }, "data-testid": "dimension-value", children: name != null ? name : type })
681
- ]
682
- }
683
- );
721
+ var _a;
722
+ const { type, name } = dimensionDisplayName(displayName);
723
+ const tooltip = (_a = name != null ? name : type) != null ? _a : "";
724
+ return /* @__PURE__ */ jsxs4("div", { css: styles.dimensionValueWrapper, children: [
725
+ type ? /* @__PURE__ */ jsxs4("small", { css: styles.dimensionName, children: [
726
+ type ? /* @__PURE__ */ jsx11(Icon2, { icon: dimensionIcon(type), iconColor: "currentColor", size: 16 }) : null,
727
+ /* @__PURE__ */ jsx11("span", { "data-testid": "dimension-name", children: type })
728
+ ] }) : null,
729
+ /* @__PURE__ */ jsx11(Tooltip, { title: tooltip, children: /* @__PURE__ */ jsx11("div", { css: styles.dimensionValue, "data-testid": "dimension-value", children: name != null ? name : type }) })
730
+ ] });
684
731
  }
685
732
 
686
733
  // src/components/DimensionMenu/DimensionSingleValue.tsx
@@ -703,13 +750,24 @@ function CriteriaMatchMenu({
703
750
  const [inputValue, setInputValue] = useState5(
704
751
  typeof criteriaMatch.r !== "undefined" && isInt(criteriaMatch.r) !== null ? criteriaMatch.r.toString(10) : ""
705
752
  );
753
+ const currentInputValue = useRef(inputValue);
754
+ currentInputValue.current = inputValue;
755
+ useEffect4(() => {
756
+ if (currentInputValue.current !== criteriaMatch.r && !criteriaMatch.rDim) {
757
+ setInputValue(
758
+ typeof criteriaMatch.r !== "undefined" && isInt(criteriaMatch.r) !== null ? criteriaMatch.r.toString(10) : ""
759
+ );
760
+ }
761
+ }, [criteriaMatch.r, criteriaMatch.rDim]);
706
762
  const rDim = criteriaMatch.rDim;
707
763
  const targetDim = criteriaMatch.rDim ? dimensions.dimIndex[criteriaMatch.rDim] : void 0;
764
+ const groupedDimensions = useGroupedDimensions(dimensions.dimensions, void 0);
708
765
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
709
766
  /* @__PURE__ */ jsx13(
710
767
  InputComboBox3,
711
768
  {
712
769
  ...props,
770
+ isDisabled: props.disabled,
713
771
  inputValue,
714
772
  menuShouldScrollIntoView: true,
715
773
  value: {
@@ -723,7 +781,7 @@ function CriteriaMatchMenu({
723
781
  value: "",
724
782
  isDisabled: true
725
783
  },
726
- ...groupDimensions(dimensions.dimensions)
784
+ ...groupedDimensions
727
785
  ],
728
786
  styles: {
729
787
  ...props.styles,
@@ -802,14 +860,25 @@ function isInt(value) {
802
860
  // src/components/DimensionMenu/DimensionMenu.tsx
803
861
  import { InputComboBox as InputComboBox4 } from "@uniformdev/design-system";
804
862
  import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs6 } from "@emotion/react/jsx-runtime";
805
- function DimensionMenu({ onChange, value, dimensions, errorMessage, ...props }) {
863
+ function DimensionMenu({
864
+ onChange,
865
+ value,
866
+ dimensions,
867
+ errorMessage,
868
+ quirks,
869
+ ...props
870
+ }) {
871
+ const groupedDimensions = useGroupedDimensions(dimensions, quirks);
872
+ const valueAsMenuOption = value ? dimensionToMenuOption(value) : void 0;
806
873
  return /* @__PURE__ */ jsxs6(Fragment4, { children: [
807
874
  /* @__PURE__ */ jsx14(
808
875
  InputComboBox4,
809
876
  {
810
877
  ...props,
811
- value: value ? dimensionToMenuOption(value) : void 0,
812
- options: groupDimensions(dimensions),
878
+ isDisabled: props.disabled,
879
+ value: valueAsMenuOption,
880
+ options: groupedDimensions,
881
+ getOptionValue: (option) => option.label,
813
882
  styles: {
814
883
  ...props.styles,
815
884
  valueContainer: (provided, state) => {
@@ -822,8 +891,10 @@ function DimensionMenu({ onChange, value, dimensions, errorMessage, ...props })
822
891
  }
823
892
  },
824
893
  onChange: (e) => {
825
- if (e) {
826
- onChange(dimensions.find((d) => d.dim === e.value));
894
+ if (e == null ? void 0 : e.original) {
895
+ onChange(e.original);
896
+ } else {
897
+ onChange(void 0);
827
898
  }
828
899
  },
829
900
  components: {
@@ -843,8 +914,8 @@ import { CgChevronRight } from "@react-icons/all-files/cg/CgChevronRight";
843
914
  import { Icon as Icon3 } from "@uniformdev/design-system";
844
915
 
845
916
  // src/components/EditLink/EditLink.styles.ts
846
- import { css as css4 } from "@emotion/react";
847
- var editLink = css4`
917
+ import { css as css5 } from "@emotion/react";
918
+ var editLink = css5`
848
919
  display: flex;
849
920
  align-items: center;
850
921
  font-weight: var(--fw-bold);
@@ -877,7 +948,7 @@ var EditLink = ({ linkTo, name, linkText = `Edit ${name} Component` }) => {
877
948
  };
878
949
 
879
950
  // src/components/EnrichmentTag/EnrichmentTag.tsx
880
- import { css as css5 } from "@emotion/react";
951
+ import { css as css6 } from "@emotion/react";
881
952
  import { CgCloseO } from "@react-icons/all-files/cg/CgCloseO";
882
953
  import { CgMathMinus } from "@react-icons/all-files/cg/CgMathMinus";
883
954
  import { CgMathPlus } from "@react-icons/all-files/cg/CgMathPlus";
@@ -892,9 +963,9 @@ import {
892
963
  LoadingIndicator as LoadingIndicator3
893
964
  } from "@uniformdev/design-system";
894
965
  import { produce } from "immer";
895
- import { useMemo, useState as useState6 } from "react";
966
+ import { useMemo as useMemo2, useState as useState6 } from "react";
896
967
  import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs8 } from "@emotion/react/jsx-runtime";
897
- var addEnrichmentLink = css5`
968
+ var addEnrichmentLink = css6`
898
969
  flex: 2;
899
970
  display: flex;
900
971
  width: 50%;
@@ -913,10 +984,10 @@ var EnrichmentTag = ({
913
984
  displayTitle = true
914
985
  }) => {
915
986
  const { loading, result: dimensions, error } = useDimensions(contextConfig);
916
- const allEnrichments = useMemo(() => {
987
+ const allEnrichments = useMemo2(() => {
917
988
  if (dimensions) return dimensions.dimensions.filter((dimension) => dimension.category === "ENR");
918
989
  }, [dimensions]);
919
- const remainingEnrichments = useMemo(() => {
990
+ const remainingEnrichments = useMemo2(() => {
920
991
  if (!value) return allEnrichments;
921
992
  if (allEnrichments)
922
993
  return allEnrichments.filter(
@@ -1083,7 +1154,7 @@ var NoEnrichmentsView = ({ contextConfig }) => /* @__PURE__ */ jsx16(Callout2, {
1083
1154
  var getCappedValue = (value, maxCap = 100, minCap = 0) => {
1084
1155
  return Math.max(Math.min(value, maxCap), minCap);
1085
1156
  };
1086
- var scoreCounterMinusButtonStyles = css5`
1157
+ var scoreCounterMinusButtonStyles = css6`
1087
1158
  position: absolute;
1088
1159
  bottom: 0.875rem;
1089
1160
  left: var(--spacing-sm);
@@ -1096,7 +1167,7 @@ var scoreCounterMinusButtonStyles = css5`
1096
1167
  border: 1px solid var(--gray-300);
1097
1168
  border-radius: var(--rounded-full);
1098
1169
  `;
1099
- var scoreCounterPlusButtonStyles = css5`
1170
+ var scoreCounterPlusButtonStyles = css6`
1100
1171
  ${scoreCounterMinusButtonStyles}
1101
1172
  left: auto;
1102
1173
  right: var(--spacing-sm);
@@ -1260,20 +1331,30 @@ function opHasRhs(op) {
1260
1331
  }
1261
1332
 
1262
1333
  // src/components/PersonalizationCriteria/PersonalizationCriteriaStatic.tsx
1263
- import { css as css7 } from "@emotion/react";
1334
+ import { css as css8 } from "@emotion/react";
1264
1335
  import { CgCloseO as CgCloseO2 } from "@react-icons/all-files/cg/CgCloseO";
1265
- import { AddListButton as AddListButton3, Callout as Callout3, Icon as Icon5, InputInlineSelect, Paragraph } from "@uniformdev/design-system";
1336
+ import {
1337
+ AddListButton as AddListButton3,
1338
+ Callout as Callout3,
1339
+ Heading as Heading2,
1340
+ Icon as Icon5,
1341
+ Input as Input2,
1342
+ InputInlineSelect,
1343
+ InputSelect as InputSelect2,
1344
+ Paragraph,
1345
+ VerticalRhythm
1346
+ } from "@uniformdev/design-system";
1266
1347
  import { produce as produce2 } from "immer";
1267
1348
 
1268
1349
  // src/components/PersonalizationCriteria/PersonalizationCriteriaStatic.styles.ts
1269
- import { css as css6 } from "@emotion/react";
1350
+ import { css as css7 } from "@emotion/react";
1270
1351
  var spaceBetweenCriteriaItems = "6rem";
1271
- var criteriaItem = css6`
1352
+ var criteriaItem = css7`
1272
1353
  position: relative;
1273
1354
  padding: var(--spacing-md) var(--spacing-base);
1274
1355
  border: 1px solid var(--gray-300);
1275
- box-shadow: var(--shadow-base);
1276
- background-color: white;
1356
+ box-shadow: var(--elevation-200);
1357
+ background-color: var(--white);
1277
1358
  border-radius: var(--rounded-base);
1278
1359
  margin-top: ${spaceBetweenCriteriaItems};
1279
1360
  display: flex;
@@ -1290,35 +1371,37 @@ var criteriaItem = css6`
1290
1371
  }
1291
1372
 
1292
1373
  &:first-of-type {
1293
- margin-top: var(--spacing-md);
1374
+ margin-top: 0;
1294
1375
  &:before {
1295
1376
  display: none;
1296
1377
  }
1297
1378
  }
1298
1379
  `;
1299
- var criteriaItemInner = css6`
1380
+ var criteriaItemInner = css7`
1300
1381
  display: flex;
1301
- gap: var(--spacing-base);
1382
+ row-gap: var(--spacing-base);
1383
+ column-gap: var(--spacing-xs);
1302
1384
  flex-grow: 1;
1303
1385
  flex-wrap: wrap;
1304
1386
  margin-right: var(--spacing-base);
1305
1387
  `;
1306
- var criteriaWrapper = css6`
1388
+ var criteriaWrapper = css7`
1307
1389
  width: 100%;
1308
1390
  display: flex;
1309
1391
  align-items: stretch;
1310
1392
  position: relative;
1311
1393
  `;
1312
- var criteriaOperandWrapper = css6`
1394
+ var criteriaOperandWrapper = css7`
1313
1395
  flex: 2;
1314
1396
  height: 52px;
1315
1397
  min-width: 200px;
1316
1398
  `;
1317
- var criteriaOperatorWrapper = css6`
1399
+ var criteriaOperatorWrapper = css7`
1318
1400
  flex: 1;
1401
+ flex-wrap: nowrap;
1319
1402
  min-width: 80px;
1320
1403
  `;
1321
- var expand = css6`
1404
+ var expand = css7`
1322
1405
  height: 100%;
1323
1406
  width: 100%;
1324
1407
  `;
@@ -1329,13 +1412,15 @@ var PersonalizationCriteriaStatic = ({
1329
1412
  value,
1330
1413
  setValue,
1331
1414
  dimensions,
1415
+ quirks,
1332
1416
  onMenuOpen,
1333
1417
  onMenuClose,
1334
1418
  onAddCriteria,
1335
1419
  onRemoveCriteria,
1336
1420
  displayTitle = true,
1337
1421
  components,
1338
- errors = {}
1422
+ errors = {},
1423
+ readOnly
1339
1424
  }) => {
1340
1425
  var _a;
1341
1426
  const currentValue = { crit: [], ...value };
@@ -1378,148 +1463,207 @@ var PersonalizationCriteriaStatic = ({
1378
1463
  fontSize: "var(--fs-md)",
1379
1464
  fontWeight: "var(--fw-bold)"
1380
1465
  },
1381
- children: "Personalize This"
1466
+ children: /* @__PURE__ */ jsx17(Heading2, { level: 5, withMarginBottom: false, children: "Personalization Variation" })
1382
1467
  }
1383
1468
  ) : null,
1384
- (components == null ? void 0 : components.CustomVariantName) ? /* @__PURE__ */ jsx17(components.CustomVariantName, {}) : null,
1385
- (components == null ? void 0 : components.ControlPercentage) ? /* @__PURE__ */ jsx17(components.ControlPercentage, {}) : null,
1386
- !currentValue.crit.length ? /* @__PURE__ */ jsx17(Callout3, { title: "Default variant", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ jsx17(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__ */ jsx17("div", { children: currentValue.crit.map((currentCriteria, index) => {
1387
- var _a2, _b, _c, _d;
1388
- const critHasLhs = ((_a2 = currentCriteria.l) == null ? void 0 : _a2.length) > 0;
1389
- const critHasRhs = opHasRhs(currentCriteria.op);
1390
- return /* @__PURE__ */ jsxs9("div", { css: criteriaItem, "data-testid": "criteria-container", children: [
1391
- /* @__PURE__ */ jsxs9(
1392
- "div",
1393
- {
1394
- css: css7`
1395
- ${criteriaItemInner}/* grid-template-columns: minmax(0, 1fr) ${critHasRhs ? "minmax(0, 79px) minmax(0, 1fr)" : "minmax(0, 1fr)"} */
1396
- `,
1397
- className: "criteriaItemInner",
1398
- children: [
1399
- /* @__PURE__ */ jsx17(
1400
- "div",
1401
- {
1402
- css: [criteriaWrapper, criteriaOperandWrapper],
1403
- className: "criteria-wrapper",
1404
- "data-testid": "select-criteria",
1405
- children: /* @__PURE__ */ jsx17(
1406
- DimensionMenu,
1407
- {
1408
- errorMessage: (_b = errors.lhs) == null ? void 0 : _b[index],
1409
- css: expand,
1410
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1411
- dimensions: dimensions.dimensions,
1412
- onChange: (dim) => {
1413
- update({ ...currentCriteria, l: dim.dim }, index);
1414
- },
1415
- value: dimensions.dimIndex[currentCriteria.l],
1416
- onMenuOpen,
1417
- onMenuClose
1418
- }
1419
- )
1420
- }
1421
- ),
1422
- /* @__PURE__ */ jsx17(
1423
- "div",
1424
- {
1425
- css: [criteriaWrapper, criteriaOperatorWrapper],
1426
- className: "criteria-wrapper",
1427
- "data-testid": "select-operator",
1428
- children: /* @__PURE__ */ jsx17(
1429
- CriteriaOperatorMenu,
1430
- {
1431
- name: `op-${index}`,
1432
- css: expand,
1433
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1434
- value: currentCriteria.op,
1435
- onChange: (op) => {
1436
- if (op === "+" || op === "-") {
1437
- update({ ...currentCriteria, op, r: void 0, rDim: void 0 }, index);
1438
- } else {
1439
- update({ ...currentCriteria, op }, index);
1440
- }
1441
- },
1442
- onMenuOpen,
1443
- onMenuClose
1444
- }
1445
- )
1446
- }
1447
- ),
1448
- critHasRhs ? /* @__PURE__ */ jsx17(
1449
- "div",
1450
- {
1451
- css: [criteriaWrapper, criteriaOperandWrapper],
1452
- className: "criteria-wrapper",
1453
- "data-testid": "select-match-criteria",
1454
- children: /* @__PURE__ */ jsx17(
1455
- CriteriaMatchMenu,
1456
- {
1457
- errorMessage: (_c = errors.rhs) == null ? void 0 : _c[index],
1458
- css: expand,
1459
- styles: { control: (base) => ({ ...base, height: "100%" }) },
1460
- criteriaMatch: currentCriteria,
1461
- onChange: (match) => {
1462
- update(match, index);
1463
- },
1464
- isDisabled: !critHasLhs,
1465
- dimensions,
1466
- onMenuOpen,
1467
- onMenuClose
1468
- }
1469
- )
1470
- }
1471
- ) : null
1472
- ]
1473
- }
1474
- ),
1475
- /* @__PURE__ */ jsx17(
1476
- "button",
1477
- {
1478
- type: "button",
1479
- onClick: () => removeFromList(index),
1480
- title: `Delete Personalization`,
1481
- css: { backgroundColor: "transparent", backgroundImage: "none", borderWidth: 0 },
1482
- "data-testid": "button-delete",
1483
- children: /* @__PURE__ */ jsx17(Icon5, { icon: CgCloseO2, iconColor: "red", size: "1.5rem" })
1484
- }
1485
- ),
1486
- index > 0 ? /* @__PURE__ */ jsx17(
1487
- "div",
1488
- {
1489
- className: "criteria-group-operation",
1490
- css: {
1491
- position: "absolute",
1492
- top: "-4rem",
1493
- transform: "translateX(calc(1.5rem - 50%))"
1494
- },
1495
- children: /* @__PURE__ */ jsx17(
1496
- InputInlineSelect,
1469
+ /* @__PURE__ */ jsxs9(VerticalRhythm, { children: [
1470
+ (components == null ? void 0 : components.CustomVariantName) ? /* @__PURE__ */ jsx17(components.CustomVariantName, {}) : null,
1471
+ (components == null ? void 0 : components.ControlPercentage) ? /* @__PURE__ */ jsx17(components.ControlPercentage, {}) : null,
1472
+ !currentValue.crit.length ? /* @__PURE__ */ jsx17(Callout3, { title: "Default variant", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ jsx17(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__ */ jsx17("div", { children: currentValue.crit.map((currentCriteria, index) => {
1473
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1474
+ const critHasLhs = ((_a2 = currentCriteria.l) == null ? void 0 : _a2.length) > 0;
1475
+ const critHasRhs = opHasRhs(currentCriteria.op);
1476
+ const selectedValueIsQuirk = "t" in currentCriteria && currentCriteria.t === "q";
1477
+ const currentDimension = selectedValueIsQuirk ? void 0 : dimensions.dimIndex[currentCriteria.l];
1478
+ const currentQuirk = selectedValueIsQuirk ? quirks == null ? void 0 : quirks.find((q) => q.id === currentCriteria.l) : void 0;
1479
+ return /* @__PURE__ */ jsxs9("div", { css: criteriaItem, "data-testid": "criteria-container", children: [
1480
+ /* @__PURE__ */ jsxs9("div", { css: criteriaItemInner, className: "criteriaItemInner", children: [
1481
+ /* @__PURE__ */ jsx17(
1482
+ "div",
1497
1483
  {
1498
- "data-testid": "dropdown-button-combine",
1499
- disabled: index > 1,
1500
- value: (_d = currentValue.op) != null ? _d : "&",
1501
- options: [
1502
- { label: "AND", value: "&" },
1503
- { label: "OR", value: "|" }
1504
- ],
1505
- onChange: (v) => {
1506
- setOp(v.value);
1507
- }
1484
+ css: [criteriaWrapper, criteriaOperandWrapper],
1485
+ className: "criteria-wrapper",
1486
+ "data-testid": "select-criteria",
1487
+ children: /* @__PURE__ */ jsx17(
1488
+ DimensionMenu,
1489
+ {
1490
+ errorMessage: (_b = errors.lhs) == null ? void 0 : _b[index],
1491
+ css: expand,
1492
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1493
+ dimensions: dimensions.dimensions,
1494
+ quirks,
1495
+ onChange: (selection) => {
1496
+ if (!selection) {
1497
+ return;
1498
+ }
1499
+ if ("dim" in selection) {
1500
+ const validOperators = getValidCriteriaOperatorsFor(selection.category);
1501
+ const existingOpRemainsValid = !("t" in currentCriteria && currentCriteria.t === "q") && validOperators.some((op) => op.value === currentCriteria.op);
1502
+ const newCriteria = {
1503
+ ...currentCriteria,
1504
+ l: selection.dim,
1505
+ t: void 0,
1506
+ op: existingOpRemainsValid ? currentCriteria.op : ">",
1507
+ r: existingOpRemainsValid ? currentCriteria.r : 0,
1508
+ rDim: existingOpRemainsValid ? currentCriteria.rDim : void 0
1509
+ };
1510
+ update(newCriteria, index);
1511
+ } else {
1512
+ update({ ...currentCriteria, l: selection.id, t: "q", op: "=", r: "" }, index);
1513
+ }
1514
+ },
1515
+ value: currentDimension != null ? currentDimension : currentQuirk,
1516
+ onMenuOpen,
1517
+ onMenuClose,
1518
+ disabled: readOnly
1519
+ }
1520
+ )
1508
1521
  }
1509
- )
1510
- }
1511
- ) : null
1512
- ] }, index);
1513
- }) }),
1514
- dimensions.dimensions.length === 0 ? (components == null ? void 0 : components.NoDimensionsDefined) ? /* @__PURE__ */ jsx17(components.NoDimensionsDefined, {}) : /* @__PURE__ */ jsx17(Callout3, { title: "Dimensions", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ jsx17("p", { children: "You do not have any dimensions configured." }) }) : /* @__PURE__ */ jsx17(
1515
- AddListButton3,
1516
- {
1517
- "data-testid": "button-add-criteria",
1518
- className: "add-more",
1519
- buttonText: "Add Criteria",
1520
- onButtonClick: addToList
1521
- }
1522
- )
1522
+ ),
1523
+ /* @__PURE__ */ jsx17(
1524
+ "div",
1525
+ {
1526
+ css: [criteriaWrapper, criteriaOperatorWrapper],
1527
+ className: "criteria-wrapper",
1528
+ "data-testid": "select-operator",
1529
+ children: /* @__PURE__ */ jsx17(
1530
+ CriteriaOperatorMenu,
1531
+ {
1532
+ name: `op-${index}`,
1533
+ css: expand,
1534
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1535
+ value: currentCriteria.op,
1536
+ rhsType: currentQuirk ? "QUIRK" : currentDimension == null ? void 0 : currentDimension.category,
1537
+ onChange: (op) => {
1538
+ if (op === "+" || op === "-") {
1539
+ update({ ...currentCriteria, op, r: void 0, rDim: void 0 }, index);
1540
+ } else {
1541
+ update({ ...currentCriteria, op }, index);
1542
+ }
1543
+ },
1544
+ onMenuOpen,
1545
+ onMenuClose,
1546
+ disabled: readOnly
1547
+ }
1548
+ )
1549
+ }
1550
+ ),
1551
+ critHasRhs ? /* @__PURE__ */ jsx17(
1552
+ "div",
1553
+ {
1554
+ css: [criteriaWrapper, criteriaOperandWrapper],
1555
+ className: "criteria-wrapper",
1556
+ "data-testid": "select-match-criteria",
1557
+ children: currentQuirk ? /* @__PURE__ */ jsx17(
1558
+ "div",
1559
+ {
1560
+ css: css8`
1561
+ width: 100%;
1562
+ // InputSelect wrapper is unstylable so need a descendant selector
1563
+ // to full-width it
1564
+ & > * {
1565
+ width: 100%;
1566
+ }
1567
+ `,
1568
+ children: currentQuirk.options ? /* @__PURE__ */ jsx17(
1569
+ InputSelect2,
1570
+ {
1571
+ label: "quirk match value",
1572
+ showLabel: false,
1573
+ value: (_c = currentCriteria.r) != null ? _c : "",
1574
+ errorMessage: (_d = errors.rhs) == null ? void 0 : _d[index],
1575
+ onChange: (e) => update({ ...currentCriteria, r: e.currentTarget.value }, index),
1576
+ options: [
1577
+ { label: "Select\u2026", value: "" },
1578
+ ...currentQuirk.options.map((o) => ({ label: o.name, value: o.value }))
1579
+ ],
1580
+ disabled: readOnly
1581
+ }
1582
+ ) : /* @__PURE__ */ jsx17(
1583
+ Input2,
1584
+ {
1585
+ type: "text",
1586
+ label: "quirk match value",
1587
+ showLabel: false,
1588
+ value: (_e = currentCriteria.r) != null ? _e : "",
1589
+ errorMessage: (_f = errors.rhs) == null ? void 0 : _f[index],
1590
+ onChange: (e) => update({ ...currentCriteria, r: e.currentTarget.value }, index),
1591
+ placeholder: "Enter a value",
1592
+ disabled: readOnly
1593
+ }
1594
+ )
1595
+ }
1596
+ ) : /* @__PURE__ */ jsx17(
1597
+ CriteriaMatchMenu,
1598
+ {
1599
+ errorMessage: (_g = errors.rhs) == null ? void 0 : _g[index],
1600
+ css: expand,
1601
+ styles: { control: (base) => ({ ...base, height: "100%" }) },
1602
+ criteriaMatch: currentCriteria,
1603
+ onChange: (match) => {
1604
+ update(match, index);
1605
+ },
1606
+ isDisabled: !critHasLhs,
1607
+ dimensions,
1608
+ onMenuOpen,
1609
+ onMenuClose,
1610
+ disabled: readOnly
1611
+ }
1612
+ )
1613
+ }
1614
+ ) : null
1615
+ ] }),
1616
+ /* @__PURE__ */ jsx17(
1617
+ "button",
1618
+ {
1619
+ type: "button",
1620
+ onClick: () => removeFromList(index),
1621
+ title: `Delete Personalization`,
1622
+ css: { backgroundColor: "transparent", backgroundImage: "none", borderWidth: 0 },
1623
+ "data-testid": "button-delete",
1624
+ disabled: readOnly,
1625
+ children: /* @__PURE__ */ jsx17(Icon5, { icon: CgCloseO2, iconColor: "red", size: "1.5rem" })
1626
+ }
1627
+ ),
1628
+ index > 0 ? /* @__PURE__ */ jsx17(
1629
+ "div",
1630
+ {
1631
+ className: "criteria-group-operation",
1632
+ css: {
1633
+ position: "absolute",
1634
+ top: "-4rem",
1635
+ transform: "translateX(calc(1.5rem - 50%))"
1636
+ },
1637
+ children: /* @__PURE__ */ jsx17(
1638
+ InputInlineSelect,
1639
+ {
1640
+ "data-testid": "dropdown-button-combine",
1641
+ disabled: index > 1 || readOnly,
1642
+ value: (_h = currentValue.op) != null ? _h : "&",
1643
+ options: [
1644
+ { label: "AND", value: "&" },
1645
+ { label: "OR", value: "|" }
1646
+ ],
1647
+ onChange: (v) => {
1648
+ setOp(v.value);
1649
+ }
1650
+ }
1651
+ )
1652
+ }
1653
+ ) : null
1654
+ ] }, index);
1655
+ }) }),
1656
+ dimensions.dimensions.length === 0 && !(quirks == null ? void 0 : quirks.length) ? (components == null ? void 0 : components.NoDimensionsDefined) ? /* @__PURE__ */ jsx17(components.NoDimensionsDefined, {}) : /* @__PURE__ */ jsx17(Callout3, { title: "Dimensions", type: "info", css: { marginBlock: "var(--spacing-base)" }, children: /* @__PURE__ */ jsx17("p", { children: "You do not have any dimensions configured." }) }) : /* @__PURE__ */ jsx17(
1657
+ AddListButton3,
1658
+ {
1659
+ "data-testid": "button-add-criteria",
1660
+ className: "add-more",
1661
+ buttonText: "Add Criteria",
1662
+ onButtonClick: addToList,
1663
+ disabled: readOnly
1664
+ }
1665
+ )
1666
+ ] })
1523
1667
  ] });
1524
1668
  };
1525
1669
 
@@ -1648,7 +1792,7 @@ function ProjectUIVersion({ children, versionMap, contextConfig }) {
1648
1792
  }
1649
1793
 
1650
1794
  // src/hooks/useValidateContextConfig.ts
1651
- import { useEffect as useEffect4, useState as useState8 } from "react";
1795
+ import { useEffect as useEffect5, useState as useState8 } from "react";
1652
1796
 
1653
1797
  // src/utils/validateContextConfig.ts
1654
1798
  import { UncachedManifestClient } from "@uniformdev/context/api";
@@ -1689,7 +1833,7 @@ var useValidateContextConfig = (contextConfig) => {
1689
1833
  error: void 0
1690
1834
  });
1691
1835
  const { apiKey, apiHost, projectId } = contextConfig || {};
1692
- useEffect4(() => {
1836
+ useEffect5(() => {
1693
1837
  if (!apiKey || !apiHost) {
1694
1838
  return;
1695
1839
  }
@@ -1729,6 +1873,8 @@ export {
1729
1873
  addEnrichmentLink,
1730
1874
  contextCriteriaMenuOperators,
1731
1875
  convertErrorsToObj,
1876
+ enrichmentCriteriaMenuOperators,
1877
+ getValidCriteriaOperatorsFor,
1732
1878
  isEnrichmentTagData,
1733
1879
  isPersonalizationCriteriaData,
1734
1880
  opHasRhs,