@proveanything/smartlinks-utils-ui 1.14.1 → 1.14.3
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/{chunk-JNCRSL2H.js → chunk-WJTD5HT7.js} +267 -7
- package/dist/chunk-WJTD5HT7.js.map +1 -0
- package/dist/components/ConditionsEditor/index.d.ts +2 -2
- package/dist/components/ConditionsEditor/index.js +1 -1
- package/dist/components/FacetRuleEditor/index.d.ts +1 -1
- package/dist/components/RecordsAdmin/index.js +61 -16
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{types-BLqki3Zy.d.ts → types-CPGCbjgi.d.ts} +7 -0
- package/package.json +3 -3
- package/dist/chunk-JNCRSL2H.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useFacets } from './chunk-DH5HG5DW.js';
|
|
2
2
|
import { cn } from './chunk-L7FQ52F5.js';
|
|
3
3
|
import { useState, useCallback, useRef, useMemo, useEffect } from 'react';
|
|
4
|
-
import { GitBranch, Plus, Filter, ChevronRight, X, RefreshCw, Trash2, ChevronDown, Layers, ToggleLeft, Package, MapPin, Tag, Monitor, Calendar, User, Hash, Globe, Tags } from 'lucide-react';
|
|
4
|
+
import { GitBranch, Plus, Filter, ChevronRight, X, RefreshCw, Trash2, ChevronDown, Layers, ToggleLeft, Package, MapPin, Tag, Monitor, Calendar, User, Hash, Globe, Tags, Search, Loader2 } from 'lucide-react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import * as SL from '@proveanything/smartlinks';
|
|
6
7
|
|
|
7
8
|
var CONDITION_TYPES = [
|
|
8
9
|
{ value: "version", title: "Version", description: "Match specific versions", icon: "tags", color: "#7c3aed", helpText: "Limit by specific versions of your application or product." },
|
|
@@ -14,7 +15,7 @@ var CONDITION_TYPES = [
|
|
|
14
15
|
{ value: "tag", title: "Label", description: "Match by tags or labels", icon: "tag", color: "#db2777", helpText: "Limit by assigned labels or tags." },
|
|
15
16
|
{ value: "facet", title: "Facet", description: "Match product facet values", icon: "layers", color: "#9333ea", helpText: "Limit by one or more facet values assigned to products in the collection." },
|
|
16
17
|
{ value: "geofence", title: "Geofence", description: "Geographic boundary", icon: "map-pin", color: "#0d9488", helpText: "Limit by geographic boundaries (rectangular area)." },
|
|
17
|
-
{ value: "product", title: "Product
|
|
18
|
+
{ value: "product", title: "Product", description: "Match specific products", icon: "package", color: "#d97706", helpText: "Limit by one or more products in the collection. Search by name, SKU, or ID." },
|
|
18
19
|
{ value: "itemStatus", title: "Item Status", description: "Filter by item state", icon: "toggle-left", color: "#ea580c", helpText: "Limit by item status such as proof, claimable, owner, or virtual." },
|
|
19
20
|
{ value: "condition", title: "Condition", description: "Reference another condition", icon: "git-branch", color: "#4f46e5", helpText: "Reference another saved condition and check if it passes or fails." }
|
|
20
21
|
];
|
|
@@ -109,7 +110,10 @@ function getConditionSummary(cond, options) {
|
|
|
109
110
|
case "product":
|
|
110
111
|
if (cond.productIds?.length) {
|
|
111
112
|
const verb = cond.contains ? "is" : "is not";
|
|
112
|
-
|
|
113
|
+
const names = cond.productIds.map((id) => cond.productNames?.[id] || id);
|
|
114
|
+
const preview = names.slice(0, 2).join(", ");
|
|
115
|
+
const rest = names.length > 2 ? ` +${names.length - 2}` : "";
|
|
116
|
+
summary += ` ${verb} ${preview}${rest}`;
|
|
113
117
|
}
|
|
114
118
|
break;
|
|
115
119
|
case "condition":
|
|
@@ -603,6 +607,253 @@ var CountryPicker = ({
|
|
|
603
607
|
}) })
|
|
604
608
|
] });
|
|
605
609
|
};
|
|
610
|
+
function toHit(p) {
|
|
611
|
+
return {
|
|
612
|
+
id: p?.id ?? p?.productId ?? "",
|
|
613
|
+
name: p?.name ?? p?.id ?? "Untitled",
|
|
614
|
+
sku: p?.sku ?? null
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
async function queryProducts(collectionId, search) {
|
|
618
|
+
const body = {
|
|
619
|
+
page: { limit: 25 },
|
|
620
|
+
sort: [{ field: "name", direction: "asc" }]
|
|
621
|
+
};
|
|
622
|
+
if (search.trim()) body.query = { search: search.trim() };
|
|
623
|
+
const products = SL?.products ?? SL?.product;
|
|
624
|
+
if (!products) return [];
|
|
625
|
+
try {
|
|
626
|
+
if (products.query) {
|
|
627
|
+
const res = await products.query(collectionId, body, true);
|
|
628
|
+
return (res?.items ?? []).map(toHit);
|
|
629
|
+
}
|
|
630
|
+
if (products.list) {
|
|
631
|
+
const list = await products.list(collectionId, true);
|
|
632
|
+
const term = search.trim().toLowerCase();
|
|
633
|
+
const filtered = term ? list.filter((p) => `${p?.name ?? ""} ${p?.sku ?? ""} ${p?.id ?? ""}`.toLowerCase().includes(term)) : list;
|
|
634
|
+
return filtered.slice(0, 25).map(toHit);
|
|
635
|
+
}
|
|
636
|
+
} catch (err) {
|
|
637
|
+
console.warn("[ConditionsEditor] product search failed", err);
|
|
638
|
+
}
|
|
639
|
+
return [];
|
|
640
|
+
}
|
|
641
|
+
var ProductPicker = ({
|
|
642
|
+
collectionId,
|
|
643
|
+
selectedIds,
|
|
644
|
+
names,
|
|
645
|
+
onChange,
|
|
646
|
+
disabled
|
|
647
|
+
}) => {
|
|
648
|
+
const [search, setSearch] = useState("");
|
|
649
|
+
const [results, setResults] = useState([]);
|
|
650
|
+
const [loading, setLoading] = useState(false);
|
|
651
|
+
const [open, setOpen] = useState(false);
|
|
652
|
+
const containerRef = useRef(null);
|
|
653
|
+
const cachedNames = useMemo(() => names ?? {}, [names]);
|
|
654
|
+
const refreshedRef = useRef("");
|
|
655
|
+
useEffect(() => {
|
|
656
|
+
if (!collectionId || selectedIds.length === 0) return;
|
|
657
|
+
const key = selectedIds.slice().sort().join("|");
|
|
658
|
+
if (refreshedRef.current === key) return;
|
|
659
|
+
refreshedRef.current = key;
|
|
660
|
+
const products = SL?.products ?? SL?.product;
|
|
661
|
+
if (!products?.get) return;
|
|
662
|
+
let cancelled = false;
|
|
663
|
+
(async () => {
|
|
664
|
+
const updates = {};
|
|
665
|
+
await Promise.all(selectedIds.map(async (id) => {
|
|
666
|
+
try {
|
|
667
|
+
const p = await products.get(collectionId, id, true);
|
|
668
|
+
const name = p?.name;
|
|
669
|
+
if (name && name !== cachedNames[id]) updates[id] = name;
|
|
670
|
+
} catch {
|
|
671
|
+
}
|
|
672
|
+
}));
|
|
673
|
+
if (cancelled || Object.keys(updates).length === 0) return;
|
|
674
|
+
onChange(selectedIds, { ...cachedNames, ...updates });
|
|
675
|
+
})();
|
|
676
|
+
return () => {
|
|
677
|
+
cancelled = true;
|
|
678
|
+
};
|
|
679
|
+
}, [collectionId, selectedIds.join("|")]);
|
|
680
|
+
useEffect(() => {
|
|
681
|
+
if (!open) return;
|
|
682
|
+
let cancelled = false;
|
|
683
|
+
setLoading(true);
|
|
684
|
+
const t = window.setTimeout(async () => {
|
|
685
|
+
const hits = await queryProducts(collectionId, search);
|
|
686
|
+
if (!cancelled) {
|
|
687
|
+
setResults(hits);
|
|
688
|
+
setLoading(false);
|
|
689
|
+
}
|
|
690
|
+
}, 200);
|
|
691
|
+
return () => {
|
|
692
|
+
cancelled = true;
|
|
693
|
+
window.clearTimeout(t);
|
|
694
|
+
};
|
|
695
|
+
}, [search, open, collectionId]);
|
|
696
|
+
useEffect(() => {
|
|
697
|
+
if (!open) return;
|
|
698
|
+
const onDoc = (e) => {
|
|
699
|
+
if (!containerRef.current?.contains(e.target)) setOpen(false);
|
|
700
|
+
};
|
|
701
|
+
document.addEventListener("mousedown", onDoc);
|
|
702
|
+
return () => document.removeEventListener("mousedown", onDoc);
|
|
703
|
+
}, [open]);
|
|
704
|
+
const addProduct = (hit) => {
|
|
705
|
+
if (selectedIds.includes(hit.id)) return;
|
|
706
|
+
const nextNames = { ...cachedNames, [hit.id]: hit.name };
|
|
707
|
+
onChange([...selectedIds, hit.id], nextNames);
|
|
708
|
+
};
|
|
709
|
+
const removeProduct = (id) => {
|
|
710
|
+
const nextNames = { ...cachedNames };
|
|
711
|
+
delete nextNames[id];
|
|
712
|
+
onChange(selectedIds.filter((i) => i !== id), nextNames);
|
|
713
|
+
};
|
|
714
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
715
|
+
selectedIds.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: selectedIds.map((id) => {
|
|
716
|
+
const name = cachedNames[id];
|
|
717
|
+
return /* @__PURE__ */ jsxs(
|
|
718
|
+
"span",
|
|
719
|
+
{
|
|
720
|
+
title: id,
|
|
721
|
+
style: {
|
|
722
|
+
display: "inline-flex",
|
|
723
|
+
alignItems: "center",
|
|
724
|
+
gap: 6,
|
|
725
|
+
padding: "4px 4px 4px 10px",
|
|
726
|
+
fontSize: 12,
|
|
727
|
+
borderRadius: 9999,
|
|
728
|
+
border: "1px solid #93c5fd",
|
|
729
|
+
backgroundColor: "#dbeafe",
|
|
730
|
+
color: "#1d4ed8"
|
|
731
|
+
},
|
|
732
|
+
children: [
|
|
733
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: name || id }),
|
|
734
|
+
name && /* @__PURE__ */ jsxs("span", { style: { opacity: 0.6, fontSize: 10, fontFamily: "ui-monospace, monospace" }, children: [
|
|
735
|
+
"(",
|
|
736
|
+
id.length > 12 ? `${id.slice(0, 6)}\u2026${id.slice(-4)}` : id,
|
|
737
|
+
")"
|
|
738
|
+
] }),
|
|
739
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
740
|
+
"button",
|
|
741
|
+
{
|
|
742
|
+
type: "button",
|
|
743
|
+
onClick: () => removeProduct(id),
|
|
744
|
+
style: {
|
|
745
|
+
display: "inline-flex",
|
|
746
|
+
alignItems: "center",
|
|
747
|
+
justifyContent: "center",
|
|
748
|
+
width: 18,
|
|
749
|
+
height: 18,
|
|
750
|
+
borderRadius: 9999,
|
|
751
|
+
border: "none",
|
|
752
|
+
backgroundColor: "rgba(29,78,216,0.15)",
|
|
753
|
+
cursor: "pointer",
|
|
754
|
+
color: "#1d4ed8"
|
|
755
|
+
},
|
|
756
|
+
"aria-label": `Remove ${name || id}`,
|
|
757
|
+
children: /* @__PURE__ */ jsx(X, { size: 11 })
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
]
|
|
761
|
+
},
|
|
762
|
+
id
|
|
763
|
+
);
|
|
764
|
+
}) }),
|
|
765
|
+
!disabled && /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
766
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
767
|
+
display: "flex",
|
|
768
|
+
alignItems: "center",
|
|
769
|
+
gap: 6,
|
|
770
|
+
padding: "6px 10px",
|
|
771
|
+
fontSize: 14,
|
|
772
|
+
borderRadius: 6,
|
|
773
|
+
border: "1px solid #d1d5db",
|
|
774
|
+
backgroundColor: "transparent"
|
|
775
|
+
}, children: [
|
|
776
|
+
/* @__PURE__ */ jsx(Search, { size: 14, style: { opacity: 0.5 } }),
|
|
777
|
+
/* @__PURE__ */ jsx(
|
|
778
|
+
"input",
|
|
779
|
+
{
|
|
780
|
+
type: "text",
|
|
781
|
+
value: search,
|
|
782
|
+
onChange: (e) => {
|
|
783
|
+
setSearch(e.target.value);
|
|
784
|
+
setOpen(true);
|
|
785
|
+
},
|
|
786
|
+
onFocus: () => setOpen(true),
|
|
787
|
+
placeholder: "Search products by name, SKU, or ID\u2026",
|
|
788
|
+
style: {
|
|
789
|
+
flex: 1,
|
|
790
|
+
border: "none",
|
|
791
|
+
outline: "none",
|
|
792
|
+
backgroundColor: "transparent",
|
|
793
|
+
fontSize: 14
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
loading && /* @__PURE__ */ jsx(Loader2, { size: 14, className: "animate-spin", style: { opacity: 0.5 } })
|
|
798
|
+
] }),
|
|
799
|
+
open && /* @__PURE__ */ jsxs("div", { style: {
|
|
800
|
+
position: "absolute",
|
|
801
|
+
top: "calc(100% + 4px)",
|
|
802
|
+
left: 0,
|
|
803
|
+
right: 0,
|
|
804
|
+
zIndex: 20,
|
|
805
|
+
maxHeight: 280,
|
|
806
|
+
overflowY: "auto",
|
|
807
|
+
backgroundColor: "#ffffff",
|
|
808
|
+
border: "1px solid #e5e7eb",
|
|
809
|
+
borderRadius: 8,
|
|
810
|
+
boxShadow: "0 8px 20px rgba(0,0,0,0.08)"
|
|
811
|
+
}, children: [
|
|
812
|
+
results.length === 0 && !loading && /* @__PURE__ */ jsx("div", { style: { padding: 12, fontSize: 12, color: "#9ca3af", textAlign: "center" }, children: search ? "No products found" : "Start typing to search products" }),
|
|
813
|
+
results.map((hit) => {
|
|
814
|
+
const isSelected = selectedIds.includes(hit.id);
|
|
815
|
+
return /* @__PURE__ */ jsxs(
|
|
816
|
+
"button",
|
|
817
|
+
{
|
|
818
|
+
type: "button",
|
|
819
|
+
disabled: isSelected,
|
|
820
|
+
onClick: () => {
|
|
821
|
+
addProduct(hit);
|
|
822
|
+
setSearch("");
|
|
823
|
+
},
|
|
824
|
+
style: {
|
|
825
|
+
display: "flex",
|
|
826
|
+
alignItems: "center",
|
|
827
|
+
justifyContent: "space-between",
|
|
828
|
+
width: "100%",
|
|
829
|
+
padding: "8px 12px",
|
|
830
|
+
border: "none",
|
|
831
|
+
borderBottom: "1px solid #f3f4f6",
|
|
832
|
+
backgroundColor: isSelected ? "#f9fafb" : "transparent",
|
|
833
|
+
cursor: isSelected ? "default" : "pointer",
|
|
834
|
+
textAlign: "left",
|
|
835
|
+
color: "#111827",
|
|
836
|
+
fontSize: 13,
|
|
837
|
+
opacity: isSelected ? 0.5 : 1
|
|
838
|
+
},
|
|
839
|
+
children: [
|
|
840
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
|
|
841
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: hit.name }),
|
|
842
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 10, color: "#9ca3af", fontFamily: "ui-monospace, monospace" }, children: [
|
|
843
|
+
hit.sku ? `${hit.sku} \xB7 ` : "",
|
|
844
|
+
hit.id
|
|
845
|
+
] })
|
|
846
|
+
] }),
|
|
847
|
+
isSelected && /* @__PURE__ */ jsx("span", { style: { fontSize: 10, color: "#9ca3af", marginLeft: 8 }, children: "Added" })
|
|
848
|
+
]
|
|
849
|
+
},
|
|
850
|
+
hit.id
|
|
851
|
+
);
|
|
852
|
+
})
|
|
853
|
+
] })
|
|
854
|
+
] })
|
|
855
|
+
] });
|
|
856
|
+
};
|
|
606
857
|
var ContainsToggle = ({ value = true, onChange, trueLabel = "Is One Of", falseLabel = "Is Not One Of", disabled }) => /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 4, backgroundColor: "#f3f4f6", borderRadius: 6, padding: 4, width: "fit-content" }, children: [{ v: true, label: trueLabel }, { v: false, label: falseLabel }].map((opt) => /* @__PURE__ */ jsx(
|
|
607
858
|
"button",
|
|
608
859
|
{
|
|
@@ -950,7 +1201,16 @@ var ConditionConfig = ({
|
|
|
950
1201
|
case "product":
|
|
951
1202
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
952
1203
|
/* @__PURE__ */ jsx(ContainsToggle, { value: cond.contains, onChange: (v) => update({ contains: v }), disabled: readOnly }),
|
|
953
|
-
editorProps.
|
|
1204
|
+
editorProps.collectionId ? /* @__PURE__ */ jsx(
|
|
1205
|
+
ProductPicker,
|
|
1206
|
+
{
|
|
1207
|
+
collectionId: editorProps.collectionId,
|
|
1208
|
+
selectedIds: cond.productIds || [],
|
|
1209
|
+
names: cond.productNames,
|
|
1210
|
+
onChange: (ids, names) => update({ productIds: ids, productNames: names }),
|
|
1211
|
+
disabled: readOnly
|
|
1212
|
+
}
|
|
1213
|
+
) : editorProps.products?.length ? /* @__PURE__ */ jsx(
|
|
954
1214
|
ChipSelect,
|
|
955
1215
|
{
|
|
956
1216
|
options: editorProps.products,
|
|
@@ -1159,7 +1419,7 @@ var ConditionsEditorContent = ({
|
|
|
1159
1419
|
className
|
|
1160
1420
|
}) => {
|
|
1161
1421
|
const resolvedFacets = useFacets(collectionId, facets, getFacets);
|
|
1162
|
-
const editorProps = { versions, tags, products, savedConditions, userGroups, facets: resolvedFacets };
|
|
1422
|
+
const editorProps = { versions, tags, products, savedConditions, userGroups, facets: resolvedFacets, collectionId };
|
|
1163
1423
|
const updateCondition = useCallback((index, updated) => {
|
|
1164
1424
|
const next = { ...value, conditions: [...value.conditions] };
|
|
1165
1425
|
next.conditions[index] = updated;
|
|
@@ -1314,5 +1574,5 @@ var ConditionsEditor = (props) => {
|
|
|
1314
1574
|
};
|
|
1315
1575
|
|
|
1316
1576
|
export { ConditionsEditor };
|
|
1317
|
-
//# sourceMappingURL=chunk-
|
|
1318
|
-
//# sourceMappingURL=chunk-
|
|
1577
|
+
//# sourceMappingURL=chunk-WJTD5HT7.js.map
|
|
1578
|
+
//# sourceMappingURL=chunk-WJTD5HT7.js.map
|