@proveanything/smartlinks-utils-ui 1.14.0 → 1.14.2

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.
@@ -1,7 +1,7 @@
1
1
  import { assertStylesLoaded } from './chunk-OLYC54YT.js';
2
2
  import { cn } from './chunk-L7FQ52F5.js';
3
3
  import { useState, useEffect, useMemo } from 'react';
4
- import { Link2, AppWindow, ExternalLink, Loader2 } from 'lucide-react';
4
+ import { Link2, AppWindow, ExternalLink, Loader2, Plus, X } from 'lucide-react';
5
5
  import * as SL from '@proveanything/smartlinks';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
7
 
@@ -263,6 +263,13 @@ var AppDeepForm = ({ kind, value, apps, linkables, onChange }) => {
263
263
  target
264
264
  });
265
265
  }
266
+ function updateParams(nextParams) {
267
+ if (!selectedAppId || value?.kind !== "deep") return;
268
+ onChange({
269
+ ...value,
270
+ params: nextParams && Object.keys(nextParams).length > 0 ? nextParams : void 0
271
+ });
272
+ }
266
273
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
267
274
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
268
275
  /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-muted-foreground", children: "App" }),
@@ -298,9 +305,97 @@ var AppDeepForm = ({ kind, value, apps, linkables, onChange }) => {
298
305
  }
299
306
  )
300
307
  ] }),
308
+ kind === "deep" && value?.kind === "deep" && selectedDeepId && /* @__PURE__ */ jsx(
309
+ ParamsEditor,
310
+ {
311
+ params: value.params,
312
+ onChange: updateParams
313
+ }
314
+ ),
301
315
  selectedAppId && /* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground", children: "Resolved at runtime within the surrounding container \u2014 context params are added automatically." })
302
316
  ] });
303
317
  };
318
+ var ParamsEditor = ({ params, onChange }) => {
319
+ const [rows, setRows] = useState(
320
+ () => Object.entries(params ?? {}).map(([key, value]) => ({ key, value }))
321
+ );
322
+ const paramsKey = JSON.stringify(params ?? {});
323
+ useEffect(() => {
324
+ const incoming = Object.entries(params ?? {}).map(([key, value]) => ({ key, value }));
325
+ const currentKey = JSON.stringify(
326
+ Object.fromEntries(rows.filter((r) => r.key).map((r) => [r.key, r.value]))
327
+ );
328
+ if (currentKey !== paramsKey) setRows(incoming);
329
+ }, [paramsKey]);
330
+ function commit(next) {
331
+ setRows(next);
332
+ const obj = {};
333
+ for (const r of next) {
334
+ const k = r.key.trim();
335
+ if (k) obj[k] = r.value;
336
+ }
337
+ onChange(Object.keys(obj).length > 0 ? obj : void 0);
338
+ }
339
+ function updateRow(i, patch) {
340
+ commit(rows.map((r, idx) => idx === i ? { ...r, ...patch } : r));
341
+ }
342
+ function removeRow(i) {
343
+ commit(rows.filter((_, idx) => idx !== i));
344
+ }
345
+ function addRow() {
346
+ setRows([...rows, { key: "", value: "" }]);
347
+ }
348
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
349
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
350
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-muted-foreground", children: "Custom parameters" }),
351
+ /* @__PURE__ */ jsxs(
352
+ "button",
353
+ {
354
+ type: "button",
355
+ onClick: addRow,
356
+ className: "inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground",
357
+ children: [
358
+ /* @__PURE__ */ jsx(Plus, { className: "w-3 h-3" }),
359
+ "Add"
360
+ ]
361
+ }
362
+ )
363
+ ] }),
364
+ rows.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground italic", children: "No custom parameters. The page's defaults will be used." }) : /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: rows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 items-center", children: [
365
+ /* @__PURE__ */ jsx(
366
+ "input",
367
+ {
368
+ type: "text",
369
+ placeholder: "key",
370
+ value: row.key,
371
+ onChange: (e) => updateRow(i, { key: e.target.value }),
372
+ className: "flex-1 min-w-0 px-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring"
373
+ }
374
+ ),
375
+ /* @__PURE__ */ jsx(
376
+ "input",
377
+ {
378
+ type: "text",
379
+ placeholder: "value",
380
+ value: row.value,
381
+ onChange: (e) => updateRow(i, { value: e.target.value }),
382
+ className: "flex-1 min-w-0 px-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring"
383
+ }
384
+ ),
385
+ /* @__PURE__ */ jsx(
386
+ "button",
387
+ {
388
+ type: "button",
389
+ onClick: () => removeRow(i),
390
+ "aria-label": "Remove parameter",
391
+ className: "p-1 text-muted-foreground hover:text-foreground rounded",
392
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
393
+ }
394
+ )
395
+ ] }, i)) }),
396
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "Platform context (proof, product, collection\u2026) is added automatically \u2014 don't repeat it here." })
397
+ ] });
398
+ };
304
399
 
305
400
  // src/components/LinkPicker/resolveLink.ts
306
401
  function detectEmbedded() {
@@ -378,5 +473,5 @@ function qs(params) {
378
473
  assertStylesLoaded();
379
474
 
380
475
  export { LinkPicker, resolveLink, useLinkTargets };
381
- //# sourceMappingURL=chunk-WCUKTVWC.js.map
382
- //# sourceMappingURL=chunk-WCUKTVWC.js.map
476
+ //# sourceMappingURL=chunk-H3X6KFEN.js.map
477
+ //# sourceMappingURL=chunk-H3X6KFEN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/LinkPicker/useLinkTargets.ts","../src/components/LinkPicker/LinkPicker.tsx","../src/components/LinkPicker/resolveLink.ts","../src/components/LinkPicker/index.ts"],"names":["qs","useState","useEffect","useMemo"],"mappings":"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","file":"chunk-H3X6KFEN.js","sourcesContent":["// =============================================================================\r\n// useLinkTargets — discover apps + linkable entries for a collection\r\n// =============================================================================\r\n// Hook used by <LinkPicker /> (and available standalone) to enumerate every\r\n// navigable target visible to the current collection. Combines:\r\n// - The list of installed apps (from SL.collection.getAppsConfig).\r\n// - Each app's static manifest.linkable (best-effort, fetched per app).\r\n// - Each app's appConfig.linkable (dynamic content entries).\r\n//\r\n// Results are cached per collection so the picker can be opened repeatedly\r\n// without re-fetching.\r\n\r\nimport { useEffect, useMemo, useState } from 'react';\r\nimport * as SL from '@proveanything/smartlinks';\r\nimport type { LinkableEntry } from './types';\r\n\r\nexport interface DiscoveredApp {\r\n id: string;\r\n name: string;\r\n faIcon?: string;\r\n hidden?: boolean;\r\n /** True when the app declared itself deep-linkable in collection apps config. */\r\n supportsDeepLinks?: boolean;\r\n manifestUrl?: string;\r\n}\r\n\r\ninterface CacheEntry {\r\n apps?: DiscoveredApp[];\r\n linkables?: Map<string, LinkableEntry[]>; // appId -> entries\r\n promise?: Promise<void>;\r\n}\r\n\r\nconst cache = new Map<string, CacheEntry>();\r\n\r\nfunction entryId(e: { path?: string; title: string; params?: Record<string, string> }): string {\r\n // Stable, content-addressed id: path + sorted params, falling back to title.\r\n const base = e.path || e.title.toLowerCase().replace(/\\s+/g, '-');\r\n if (!e.params || Object.keys(e.params).length === 0) return base;\r\n const qs = Object.keys(e.params)\r\n .sort()\r\n .map((k) => `${k}=${e.params![k]}`)\r\n .join('&');\r\n return `${base}?${qs}`;\r\n}\r\n\r\nasync function fetchManifest(url: string): Promise<any | null> {\r\n try {\r\n const res = await fetch(url, { credentials: 'omit' });\r\n if (!res.ok) return null;\r\n return await res.json();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nasync function loadCollection(collectionId: string): Promise<CacheEntry> {\r\n const existing = cache.get(collectionId);\r\n if (existing?.apps) return existing;\r\n if (existing?.promise) {\r\n await existing.promise;\r\n return cache.get(collectionId)!;\r\n }\r\n\r\n const entry: CacheEntry = {};\r\n const promise = (async () => {\r\n const result: any = await (SL as any).collection.getAppsConfig(collectionId);\r\n const apps: any[] = Array.isArray(result?.apps) ? result.apps : [];\r\n const discovered: DiscoveredApp[] = apps.map((a) => ({\r\n id: a.id,\r\n name: a.name || a.id,\r\n faIcon: a.faIcon,\r\n hidden: a.hidden,\r\n supportsDeepLinks: a.supportsDeepLinks,\r\n manifestUrl: a.manifestUrl,\r\n }));\r\n entry.apps = discovered;\r\n entry.linkables = new Map();\r\n\r\n // Fan out: per-app linkable discovery. Failures are silent (the app simply\r\n // shows zero deep links, which the UI handles gracefully).\r\n await Promise.all(\r\n discovered.map(async (app) => {\r\n const out: LinkableEntry[] = [];\r\n\r\n // Static — manifest.linkable\r\n if (app.manifestUrl) {\r\n const manifest = await fetchManifest(app.manifestUrl);\r\n const list: any[] = Array.isArray(manifest?.linkable) ? manifest.linkable : [];\r\n for (const l of list) {\r\n if (!l?.title) continue;\r\n out.push({\r\n appId: app.id,\r\n id: entryId(l),\r\n title: String(l.title),\r\n path: l.path ? String(l.path) : undefined,\r\n params: l.params && typeof l.params === 'object' ? { ...l.params } : undefined,\r\n source: 'manifest',\r\n });\r\n }\r\n }\r\n\r\n // Dynamic — appConfig.linkable\r\n try {\r\n const cfg: any = await (SL as any).appConfiguration.getConfig({\r\n collectionId,\r\n appId: app.id,\r\n });\r\n const list: any[] = Array.isArray(cfg?.linkable) ? cfg.linkable : [];\r\n for (const l of list) {\r\n if (!l?.title) continue;\r\n out.push({\r\n appId: app.id,\r\n id: entryId(l),\r\n title: String(l.title),\r\n path: l.path ? String(l.path) : undefined,\r\n params: l.params && typeof l.params === 'object' ? { ...l.params } : undefined,\r\n source: 'config',\r\n });\r\n }\r\n } catch {\r\n // No config or no read access — fine.\r\n }\r\n\r\n entry.linkables!.set(app.id, out);\r\n })\r\n );\r\n\r\n cache.set(collectionId, entry);\r\n })();\r\n\r\n entry.promise = promise;\r\n cache.set(collectionId, entry);\r\n await promise;\r\n return cache.get(collectionId)!;\r\n}\r\n\r\nexport interface UseLinkTargetsOptions {\r\n collectionId?: string;\r\n includeCurrentApp?: boolean;\r\n currentAppId?: string;\r\n}\r\n\r\nexport interface UseLinkTargetsReturn {\r\n loading: boolean;\r\n apps: DiscoveredApp[];\r\n /** Map of appId -> linkable entries (after current-app filtering). */\r\n linkables: Map<string, LinkableEntry[]>;\r\n /** Flat list across all visible apps, useful for search. */\r\n allLinkables: LinkableEntry[];\r\n}\r\n\r\nexport function useLinkTargets(opts: UseLinkTargetsOptions): UseLinkTargetsReturn {\r\n const { collectionId, includeCurrentApp = true, currentAppId } = opts;\r\n const [tick, setTick] = useState(0);\r\n\r\n useEffect(() => {\r\n if (!collectionId) return;\r\n let cancelled = false;\r\n loadCollection(collectionId).then(() => {\r\n if (!cancelled) setTick((t) => t + 1);\r\n });\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [collectionId]);\r\n\r\n return useMemo(() => {\r\n if (!collectionId) {\r\n return { loading: false, apps: [], linkables: new Map(), allLinkables: [] };\r\n }\r\n const entry = cache.get(collectionId);\r\n if (!entry?.apps) return { loading: true, apps: [], linkables: new Map(), allLinkables: [] };\r\n\r\n const apps = entry.apps.filter((a) => {\r\n if (a.hidden) return false;\r\n if (!includeCurrentApp && currentAppId && a.id === currentAppId) return false;\r\n return true;\r\n });\r\n\r\n const linkables = new Map<string, LinkableEntry[]>();\r\n const all: LinkableEntry[] = [];\r\n for (const a of apps) {\r\n const list = entry.linkables?.get(a.id) ?? [];\r\n linkables.set(a.id, list);\r\n for (const l of list) all.push(l);\r\n }\r\n\r\n return { loading: false, apps, linkables, allLinkables: all };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [collectionId, includeCurrentApp, currentAppId, tick]);\r\n}","// =============================================================================\r\n// LinkPicker — Component\r\n// =============================================================================\r\n// Universal link/app/deep-link picker. Produces a `LinkTarget` discriminated\r\n// union — never a resolved URL — because real navigation happens at runtime in\r\n// container/widget context where additional params (proof, product, variant,\r\n// batch) are injected by the platform.\r\n\r\nimport React, { useMemo, useState, useEffect } from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport { ExternalLink, AppWindow, Link2, Loader2, Plus, X } from 'lucide-react';\r\nimport type {\r\n LinkPickerProps,\r\n LinkTarget,\r\n LinkKind,\r\n LinkOpenTarget,\r\n} from './types';\r\nimport { useLinkTargets } from './useLinkTargets';\r\n\r\nconst KIND_META: Record<LinkKind, { label: string; icon: React.ComponentType<{ className?: string }> }> = {\r\n external: { label: 'External URL', icon: ExternalLink },\r\n app: { label: 'App', icon: AppWindow },\r\n deep: { label: 'Page in app', icon: Link2 },\r\n};\r\n\r\nexport const LinkPicker: React.FC<LinkPickerProps> = ({\r\n value,\r\n onChange,\r\n allow = ['external', 'app', 'deep'],\r\n includeCurrentApp = true,\r\n collectionId,\r\n currentAppId,\r\n className,\r\n}) => {\r\n const initialKind: LinkKind = value?.kind ?? allow[0];\r\n const [kind, setKind] = useState<LinkKind>(initialKind);\r\n\r\n // Keep tab in sync if value is replaced externally\r\n useEffect(() => {\r\n if (value?.kind && value.kind !== kind) setKind(value.kind);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [value?.kind]);\r\n\r\n const { loading, apps, linkables } = useLinkTargets({\r\n collectionId,\r\n includeCurrentApp,\r\n currentAppId,\r\n });\r\n\r\n function emit(next: LinkTarget | null) {\r\n onChange?.(next);\r\n }\r\n\r\n function setKindAndReset(next: LinkKind) {\r\n setKind(next);\r\n if (!value || value.kind !== next) emit(null);\r\n }\r\n\r\n return (\r\n <div className={cn('space-y-3', className)}>\r\n {allow.length > 1 && (\r\n <div className=\"flex gap-1 border-b border-border pb-2\">\r\n {allow.map((k) => {\r\n const Meta = KIND_META[k];\r\n const Icon = Meta.icon;\r\n const active = k === kind;\r\n return (\r\n <button\r\n key={k}\r\n type=\"button\"\r\n onClick={() => setKindAndReset(k)}\r\n className={cn(\r\n 'inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-md transition-colors',\r\n active\r\n ? 'bg-primary text-primary-foreground'\r\n : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'\r\n )}\r\n >\r\n <Icon className=\"w-3.5 h-3.5\" />\r\n {Meta.label}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n )}\r\n\r\n {kind === 'external' && (\r\n <ExternalForm value={value?.kind === 'external' ? value : null} onChange={emit} />\r\n )}\r\n\r\n {(kind === 'app' || kind === 'deep') && (\r\n loading ? (\r\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground py-6 justify-center\">\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n Loading apps…\r\n </div>\r\n ) : (\r\n <AppDeepForm\r\n kind={kind}\r\n value={value && (value.kind === 'app' || value.kind === 'deep') ? value : null}\r\n apps={apps}\r\n linkables={linkables}\r\n onChange={emit}\r\n />\r\n )\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// External URL form\r\n// ---------------------------------------------------------------------------\r\nconst ExternalForm: React.FC<{\r\n value: LinkTarget | null;\r\n onChange: (v: LinkTarget | null) => void;\r\n}> = ({ value, onChange }) => {\r\n const url = value?.kind === 'external' ? value.url : '';\r\n const target: LinkOpenTarget = value?.kind === 'external' ? value.target : '_blank';\r\n\r\n function update(patch: { url?: string; target?: LinkOpenTarget }) {\r\n const next: LinkTarget = {\r\n kind: 'external',\r\n url: patch.url ?? url,\r\n target: patch.target ?? target,\r\n };\r\n if (!next.url) {\r\n onChange(null);\r\n return;\r\n }\r\n if (next.target === '_blank') next.rel = 'noopener noreferrer';\r\n onChange(next);\r\n }\r\n\r\n return (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-xs font-medium text-muted-foreground\">URL</label>\r\n <input\r\n type=\"url\"\r\n inputMode=\"url\"\r\n placeholder=\"https://example.com\"\r\n value={url}\r\n onChange={(e) => update({ url: e.target.value })}\r\n className=\"w-full px-3 py-2 text-sm rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring\"\r\n />\r\n <div className=\"flex gap-1\">\r\n {(['_self', '_blank'] as LinkOpenTarget[]).map((t) => (\r\n <button\r\n key={t}\r\n type=\"button\"\r\n onClick={() => update({ target: t })}\r\n className={cn(\r\n 'px-2.5 py-1 text-xs font-medium rounded-full transition-colors',\r\n target === t\r\n ? 'bg-foreground text-background'\r\n : 'bg-muted text-muted-foreground hover:bg-accent'\r\n )}\r\n >\r\n {t === '_self' ? 'Same window' : 'New window'}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// App + Deep Link form\r\n// ---------------------------------------------------------------------------\r\nconst AppDeepForm: React.FC<{\r\n kind: 'app' | 'deep';\r\n value: LinkTarget | null;\r\n apps: ReturnType<typeof useLinkTargets>['apps'];\r\n linkables: ReturnType<typeof useLinkTargets>['linkables'];\r\n onChange: (v: LinkTarget | null) => void;\r\n}> = ({ kind, value, apps, linkables, onChange }) => {\r\n const selectedAppId =\r\n value && (value.kind === 'app' || value.kind === 'deep') ? value.appId : '';\r\n const selectedDeepId = value?.kind === 'deep' ? value.deepLinkId : '';\r\n const target: LinkOpenTarget =\r\n (value?.kind === 'app' || value?.kind === 'deep' ? value.target : undefined) ?? '_self';\r\n\r\n const entries = useMemo(\r\n () => (selectedAppId ? linkables.get(selectedAppId) ?? [] : []),\r\n [linkables, selectedAppId]\r\n );\r\n\r\n function selectApp(appId: string) {\r\n if (!appId) return onChange(null);\r\n if (kind === 'app') {\r\n onChange({ kind: 'app', appId, target });\r\n } else {\r\n // Switching app under 'deep' — clear deep selection\r\n onChange({ kind: 'deep', appId, deepLinkId: '', params: undefined, target });\r\n }\r\n }\r\n\r\n function selectDeep(deepLinkId: string) {\r\n if (!selectedAppId) return;\r\n const entry = entries.find((e) => e.id === deepLinkId);\r\n onChange({\r\n kind: 'deep',\r\n appId: selectedAppId,\r\n deepLinkId,\r\n params: entry?.params,\r\n target,\r\n });\r\n }\r\n\r\n function updateParams(nextParams: Record<string, string> | undefined) {\r\n if (!selectedAppId || value?.kind !== 'deep') return;\r\n onChange({\r\n ...value,\r\n params: nextParams && Object.keys(nextParams).length > 0 ? nextParams : undefined,\r\n });\r\n }\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div className=\"space-y-1\">\r\n <label className=\"text-xs font-medium text-muted-foreground\">App</label>\r\n {apps.length === 0 ? (\r\n <p className=\"text-xs text-muted-foreground italic\">No apps available in this collection.</p>\r\n ) : (\r\n <select\r\n value={selectedAppId}\r\n onChange={(e) => selectApp(e.target.value)}\r\n className=\"w-full px-3 py-2 text-sm rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring\"\r\n >\r\n <option value=\"\">— Choose app —</option>\r\n {apps.map((a) => (\r\n <option key={a.id} value={a.id}>{a.name}</option>\r\n ))}\r\n </select>\r\n )}\r\n </div>\r\n\r\n {kind === 'deep' && selectedAppId && (\r\n <div className=\"space-y-1\">\r\n <label className=\"text-xs font-medium text-muted-foreground\">Page</label>\r\n {entries.length === 0 ? (\r\n <p className=\"text-xs text-muted-foreground italic\">\r\n This app has no deep-linkable pages. Switch to <em>App</em> to link to its default route.\r\n </p>\r\n ) : (\r\n <select\r\n value={selectedDeepId}\r\n onChange={(e) => selectDeep(e.target.value)}\r\n className=\"w-full px-3 py-2 text-sm rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring\"\r\n >\r\n <option value=\"\">— Choose page —</option>\r\n {entries.map((e) => (\r\n <option key={`${e.source}:${e.id}`} value={e.id}>\r\n {e.title}\r\n </option>\r\n ))}\r\n </select>\r\n )}\r\n </div>\r\n )}\r\n\r\n {kind === 'deep' && value?.kind === 'deep' && selectedDeepId && (\r\n <ParamsEditor\r\n params={value.params}\r\n onChange={updateParams}\r\n />\r\n )}\r\n\r\n {selectedAppId && (\r\n <div className=\"text-[11px] text-muted-foreground\">\r\n Resolved at runtime within the surrounding container — context params are added automatically.\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Custom params editor (deep links only)\r\n// ---------------------------------------------------------------------------\r\nconst ParamsEditor: React.FC<{\r\n params?: Record<string, string>;\r\n onChange: (next: Record<string, string> | undefined) => void;\r\n}> = ({ params, onChange }) => {\r\n // Local row state preserves order and supports blank keys while typing.\r\n const [rows, setRows] = useState<Array<{ key: string; value: string }>>(\r\n () => Object.entries(params ?? {}).map(([key, value]) => ({ key, value }))\r\n );\r\n\r\n // Sync from outside when the deep-link selection changes (params prop replaced).\r\n const paramsKey = JSON.stringify(params ?? {});\r\n useEffect(() => {\r\n const incoming = Object.entries(params ?? {}).map(([key, value]) => ({ key, value }));\r\n const currentKey = JSON.stringify(\r\n Object.fromEntries(rows.filter((r) => r.key).map((r) => [r.key, r.value]))\r\n );\r\n if (currentKey !== paramsKey) setRows(incoming);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [paramsKey]);\r\n\r\n function commit(next: Array<{ key: string; value: string }>) {\r\n setRows(next);\r\n const obj: Record<string, string> = {};\r\n for (const r of next) {\r\n const k = r.key.trim();\r\n if (k) obj[k] = r.value;\r\n }\r\n onChange(Object.keys(obj).length > 0 ? obj : undefined);\r\n }\r\n\r\n function updateRow(i: number, patch: Partial<{ key: string; value: string }>) {\r\n commit(rows.map((r, idx) => (idx === i ? { ...r, ...patch } : r)));\r\n }\r\n\r\n function removeRow(i: number) {\r\n commit(rows.filter((_, idx) => idx !== i));\r\n }\r\n\r\n function addRow() {\r\n setRows([...rows, { key: '', value: '' }]);\r\n }\r\n\r\n return (\r\n <div className=\"space-y-1.5\">\r\n <div className=\"flex items-center justify-between\">\r\n <label className=\"text-xs font-medium text-muted-foreground\">Custom parameters</label>\r\n <button\r\n type=\"button\"\r\n onClick={addRow}\r\n className=\"inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground\"\r\n >\r\n <Plus className=\"w-3 h-3\" />\r\n Add\r\n </button>\r\n </div>\r\n {rows.length === 0 ? (\r\n <p className=\"text-[11px] text-muted-foreground italic\">\r\n No custom parameters. The page's defaults will be used.\r\n </p>\r\n ) : (\r\n <div className=\"space-y-1.5\">\r\n {rows.map((row, i) => (\r\n <div key={i} className=\"flex gap-1.5 items-center\">\r\n <input\r\n type=\"text\"\r\n placeholder=\"key\"\r\n value={row.key}\r\n onChange={(e) => updateRow(i, { key: e.target.value })}\r\n className=\"flex-1 min-w-0 px-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring\"\r\n />\r\n <input\r\n type=\"text\"\r\n placeholder=\"value\"\r\n value={row.value}\r\n onChange={(e) => updateRow(i, { value: e.target.value })}\r\n className=\"flex-1 min-w-0 px-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => removeRow(i)}\r\n aria-label=\"Remove parameter\"\r\n className=\"p-1 text-muted-foreground hover:text-foreground rounded\"\r\n >\r\n <X className=\"w-3.5 h-3.5\" />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n <p className=\"text-[11px] text-muted-foreground\">\r\n Platform context (proof, product, collection…) is added automatically — don't repeat it here.\r\n </p>\r\n </div>\r\n );\r\n};","// =============================================================================\r\n// resolveLink — runtime navigation helper\r\n// =============================================================================\r\n// As of `@proveanything/smartlinks` **1.11.13**, the canonical resolver lives\r\n// at `SL.navigation.resolveLink`. Public consumers (widgets, executors)\r\n// should call it directly — it ships with the SDK, has no React/DOM coupling\r\n// beyond `window`, and emits `click_link` analytics when `track` is supplied.\r\n//\r\n// This module remains as a **fallback shim** for two cases:\r\n// 1. Tests / sandboxes that aren't running inside the SmartLinks SDK.\r\n// 2. Older host apps still pinned to SDK < 1.11.13.\r\n// At runtime we delegate to `window.SL.navigation.resolveLink` when present,\r\n// so call sites get the real implementation (analytics, embedded detection,\r\n// future improvements) for free. The local copy mirrors the same API.\r\n//\r\n// @deprecated Prefer `SL.navigation.resolveLink` from `@proveanything/smartlinks`.\r\n\r\nimport type { LinkTarget } from './types';\r\n\r\n/** Subset of `SL.analytics.browser.trackLinkClick` context fields. */\r\nexport interface LinkTrackingContext {\r\n collectionId: string;\r\n productId?: string;\r\n proofId?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface ResolveLinkContext {\r\n /** True when running inside a SmartLinks container/widget/iframe. */\r\n embedded?: boolean;\r\n /**\r\n * Override for the postMessage target (defaults to `window.parent`). Useful\r\n * for tests and for hosts that proxy messages.\r\n */\r\n postTarget?: Window | null;\r\n /** Window for standalone navigation (defaults to `window`). */\r\n win?: Window;\r\n /**\r\n * Forwarded to `SL.navigation.resolveLink` when delegating. Causes a\r\n * `click_link` analytics event to fire immediately before navigation.\r\n * Ignored by the local fallback shim (no SDK = no analytics pipeline).\r\n *\r\n * @example { track: { collectionId, productId } }\r\n */\r\n track?: LinkTrackingContext;\r\n}\r\n\r\nexport interface ResolvedLink {\r\n /** Imperatively perform the navigation. */\r\n navigate(): void;\r\n /** Human-readable summary, suitable for tooltips / aria-labels. */\r\n describe(): string;\r\n}\r\n\r\nfunction detectEmbedded(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n try {\r\n return window.parent && window.parent !== window;\r\n } catch {\r\n return true;\r\n }\r\n}\r\n\r\n/** Look up `window.SL.navigation.resolveLink` if the SDK is loaded. */\r\nfunction getSdkResolver(): ((link: LinkTarget, ctx?: ResolveLinkContext) => ResolvedLink) | null {\r\n if (typeof window === 'undefined') return null;\r\n const sl = (window as unknown as { SL?: { navigation?: { resolveLink?: unknown } } }).SL;\r\n const fn = sl?.navigation?.resolveLink;\r\n return typeof fn === 'function' ? (fn as (link: LinkTarget, ctx?: ResolveLinkContext) => ResolvedLink) : null;\r\n}\r\n\r\nexport function resolveLink(link: LinkTarget, ctx: ResolveLinkContext = {}): ResolvedLink {\r\n // Prefer the SDK resolver — it carries analytics and stays in lock-step\r\n // with the platform's navigation contract.\r\n const sdk = getSdkResolver();\r\n if (sdk) return sdk(link, ctx);\r\n\r\n const win = ctx.win ?? (typeof window !== 'undefined' ? window : (undefined as any));\r\n const embedded = ctx.embedded ?? detectEmbedded();\r\n\r\n return {\r\n navigate() {\r\n if (!win) return;\r\n\r\n if (link.kind === 'external') {\r\n if (link.target === '_blank') {\r\n win.open(link.url, '_blank', link.rel ? `noopener,noreferrer` : 'noopener,noreferrer');\r\n } else {\r\n win.location.assign(link.url);\r\n }\r\n return;\r\n }\r\n\r\n if (embedded) {\r\n const target = ctx.postTarget ?? win.parent;\r\n if (!target) return;\r\n // Standard navigation message — mirrors the smartlinks-route-change\r\n // shape the parent platform already understands. The parent fills in\r\n // collectionId / productId / etc. before broadcasting.\r\n target.postMessage(\r\n {\r\n type: 'smartlinks-navigate',\r\n appId: link.appId,\r\n path: link.kind === 'deep' ? deepPath(link.deepLinkId) : '/',\r\n params: link.kind === 'deep' ? link.params ?? {} : {},\r\n target: link.target ?? '_self',\r\n },\r\n '*'\r\n );\r\n return;\r\n }\r\n\r\n // Standalone fallback — best-effort hash route. The SDK ships a\r\n // canonical version of this once `SL.navigation.resolveLink` lands.\r\n const hash = link.kind === 'deep'\r\n ? `#${deepPath(link.deepLinkId)}${qs(link.params)}`\r\n : `#/`;\r\n const url = `${win.location.pathname}?appId=${encodeURIComponent(link.appId)}${hash}`;\r\n if (link.target === '_blank') win.open(url, '_blank', 'noopener,noreferrer');\r\n else win.location.assign(url);\r\n },\r\n describe() {\r\n if (link.kind === 'external') return `Open ${link.url}`;\r\n if (link.kind === 'app') return `Open app ${link.appId}`;\r\n return `Open ${link.appId} → ${link.deepLinkId}`;\r\n },\r\n };\r\n}\r\n\r\nfunction deepPath(deepLinkId: string): string {\r\n // deepLinkId is `path` (or `path?params`) when minted from manifest entries,\r\n // and a slug otherwise. Normalise to a hash-route path.\r\n const [path] = deepLinkId.split('?');\r\n if (!path) return '/';\r\n return path.startsWith('/') ? path : `/${path}`;\r\n}\r\n\r\nfunction qs(params?: Record<string, string>): string {\r\n if (!params) return '';\r\n const keys = Object.keys(params);\r\n if (!keys.length) return '';\r\n const usp = new URLSearchParams();\r\n for (const k of keys) usp.set(k, params[k]);\r\n return `?${usp.toString()}`;\r\n}","import '../../styles.css';\r\nimport { assertStylesLoaded } from '../../utils/assertStylesLoaded';\r\nassertStylesLoaded();\r\n\r\nexport { LinkPicker } from './LinkPicker';\r\nexport { useLinkTargets } from './useLinkTargets';\r\nexport type { DiscoveredApp, UseLinkTargetsOptions, UseLinkTargetsReturn } from './useLinkTargets';\r\nexport { resolveLink } from './resolveLink';\r\nexport type { ResolveLinkContext, ResolvedLink, LinkTrackingContext } from './resolveLink';\r\nexport type {\r\n LinkPickerProps,\r\n LinkTarget,\r\n LinkKind,\r\n LinkOpenTarget,\r\n ExternalLinkTarget,\r\n AppLinkTarget,\r\n DeepLinkTarget,\r\n LinkableEntry,\r\n} from './types';"]}
@@ -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 ID", description: "Match specific items", icon: "package", color: "#d97706", helpText: "Limit by specific product IDs." },
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
- summary += ` ${verb} ${cond.productIds.length} item(s)`;
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.products?.length ? /* @__PURE__ */ jsx(
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-JNCRSL2H.js.map
1318
- //# sourceMappingURL=chunk-JNCRSL2H.js.map
1577
+ //# sourceMappingURL=chunk-WJTD5HT7.js.map
1578
+ //# sourceMappingURL=chunk-WJTD5HT7.js.map