@picked/svelte 0.0.62-next.11 → 0.0.62-next.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.
@@ -88,7 +88,7 @@
88
88
  if (isConvincelyDomain(url)) {
89
89
  const encodedUrl = encodeURIComponent(url.toString())
90
90
  const optimizedSize = findClosestSize(targetWidth)
91
- return `https://img.picked-content.com/_next/image?url=${encodedUrl}&w=${optimizedSize}&q=75`
91
+ return `https://img.convincely.io/_next/image?url=${encodedUrl}&w=${optimizedSize}&q=75`
92
92
  }
93
93
 
94
94
  // For other domains, return the original URL
@@ -1 +1 @@
1
- import{getExperience as e,getPicked as t}from"./client.js";import{attach as n}from"effector";import{trackRecommendationPresentEvent as r}from"@picked/analytics";var i=()=>{let{session:i,projectId:a}=t(),o=e();return n({source:{config:o.configStore,step:o.currentStepStore,sessionSnapshot:i.store},async effect({config:e,step:t,sessionSnapshot:n},i){if(!t)throw Error(`Cannot track recommendation present event: missing experience step.`);return r({projectId:a,experience:{id:o.experienceId,title:e.name},sessionId:n.id,identifiers:n.identifiers,isUser:n.isUser,step:t,productList:i})}})};export{i as getTrackRecommendationPresentEvent};
1
+ import{getExperience as e,getPicked as t}from"./client.js";import{attach as n}from"effector";import{trackRecommendationPresentEvent as r}from"@picked/analytics";var i=()=>{let{session:i,projectId:a}=t(),o=e();return n({source:{config:o.configStore,step:o.currentStepStore},async effect({config:e,step:t},n){if(!i||!t)throw Error(`Cannot track recommendation present event: missing session or experience data.`);return r({projectId:a,experience:{id:o.experienceId,title:e.name},sessionId:i.id,identifiers:i.identifiers,isUser:i.isUser,step:t,productList:n})}})};export{i as getTrackRecommendationPresentEvent};
@@ -3,8 +3,7 @@ export { getPicked, getExperience } from './client';
3
3
  export { getPredicate, getPredicateResult } from './predicate';
4
4
  export { getFeature, getFeatureResult } from './feature';
5
5
  export { getAction, getActionResult } from './action';
6
- export { getStep, setStepContext, getStepContent } from './step';
7
- export { getContent } from './content';
6
+ export { getStep, setStepContext } from './step';
8
7
  export { useUnit, getContextScope, setContextScope } from './stores';
9
8
  export { createSessionStorageStore, createLocalStorageStore } from './storage.js';
10
9
  export { getTrackRecommendationPresentEvent } from './events';
@@ -1 +1 @@
1
- import{getExperience as e,getPicked as t}from"./client.js";import{getPredicate as n,getPredicateResult as r}from"./predicate.js";import{getFeature as i,getFeatureResult as a}from"./feature.js";import{getAction as o,getActionResult as s}from"./action.js";import{getStep as c,getStepContent as l,setStepContext as u}from"./step.js";import{getContent as d}from"./content.js";import{getContextScope as f,setContextScope as p,useUnit as m}from"./stores.js";import{createLocalStorageStore as h,createSessionStorageStore as g}from"./storage.js";import{getTrackRecommendationPresentEvent as _}from"./events.js";import{createQuery as v,queryCache as y,queryPresets as b}from"./create-query/index.js";export{h as createLocalStorageStore,v as createQuery,g as createSessionStorageStore,o as getAction,s as getActionResult,d as getContent,f as getContextScope,e as getExperience,i as getFeature,a as getFeatureResult,t as getPicked,n as getPredicate,r as getPredicateResult,c as getStep,l as getStepContent,_ as getTrackRecommendationPresentEvent,y as queryCache,b as queryPresets,p as setContextScope,u as setStepContext,m as useUnit};
1
+ import{getExperience as e,getPicked as t}from"./client.js";import{getPredicate as n,getPredicateResult as r}from"./predicate.js";import{getFeature as i,getFeatureResult as a}from"./feature.js";import{getAction as o,getActionResult as s}from"./action.js";import{getStep as c,setStepContext as l}from"./step.js";import{getContextScope as u,setContextScope as d,useUnit as f}from"./stores.js";import{createLocalStorageStore as p,createSessionStorageStore as m}from"./storage.js";import{getTrackRecommendationPresentEvent as h}from"./events.js";import{createQuery as g,queryCache as _,queryPresets as v}from"./create-query/index.js";export{p as createLocalStorageStore,g as createQuery,m as createSessionStorageStore,o as getAction,s as getActionResult,u as getContextScope,e as getExperience,i as getFeature,a as getFeatureResult,t as getPicked,n as getPredicate,r as getPredicateResult,c as getStep,h as getTrackRecommendationPresentEvent,_ as queryCache,v as queryPresets,d as setContextScope,l as setStepContext,f as useUnit};
@@ -1,15 +1,10 @@
1
1
  import { Store } from 'effector';
2
- import { Content, ExperienceStep } from '@picked/client';
2
+ import { ExperienceStep } from '@picked/client';
3
3
  import { FormInstance, FormField } from '../form/create-form.svelte';
4
4
  export interface StepContext extends FormInstance {
5
5
  step: Store<ExperienceStep>;
6
6
  /** Directly accessible fields with current response values — usable without a form. */
7
7
  fields: Store<FormField[]>;
8
- /**
9
- * Reactive store of the current step's CMS layout content. Resolves the step's
10
- * `layoutContentId` against `client.contents` and stays reactive.
11
- */
12
- layoutContentStore: Store<Content | null>;
13
8
  isActive: Store<boolean>;
14
9
  /** @deprecated Use `isActive` instead. */
15
10
  isActiveStep: Store<boolean>;
@@ -17,31 +12,13 @@ export interface StepContext extends FormInstance {
17
12
  /**
18
13
  * Creates and sets step context in the Svelte context tree.
19
14
  *
20
- * @param {string} stepKey - The step key.
21
- * @returns {StepContext} The created step context.
15
+ * @param stepKey - The step key.
22
16
  * @example setStepContext('step-1')
23
17
  */
24
18
  export declare function setStepContext(stepKey: string): StepContext;
25
19
  /**
26
20
  * Retrieves the step context from the Svelte context tree.
27
21
  *
28
- * @returns {StepContext} The current step context.
29
22
  * @example getStep()
30
23
  */
31
24
  export declare function getStep(): StepContext;
32
- /**
33
- * Returns a Svelte/Effector store that yields the current step's resolved CMS content
34
- * data, or `null` when no content is registered for the step's `layoutContentId`.
35
- * Subscribers automatically receive updates when content is registered or replaced.
36
- *
37
- * @returns {Store<Record<string, unknown> | null>} A store of the Content record's `data`.
38
- * @example
39
- * ```svelte
40
- * <script>
41
- * import { getStepContent } from '@picked/svelte'
42
- * const content = getStepContent()
43
- * </script>
44
- * <h1>{$content?.headline ?? ''}</h1>
45
- * ```
46
- */
47
- export declare function getStepContent(): Store<Record<string, unknown> | null>;
@@ -1 +1 @@
1
- import{STEP_CONTEXT_KEY as e}from"../context.js";import{getPicked as t}from"./client.js";import{getStepRouter as n}from"../router/context.js";import{combine as r}from"effector";import{getContext as i,setContext as a}from"svelte";import{createForm as o}from"../form/create-form.svelte";function s(i){let s=t(),{activeStep:c}=n(),l=c.map(e=>e?.key===i),u=s.steps.listStore.map(e=>e.find(e=>e.key===i)??{id:i,key:i,name:``,fieldKeys:[]}),d=o(i,u.map(e=>e.name),u.map(e=>e.fieldKeys));return a(e,{step:u,layoutContentStore:r(u,s.contents.indexStore,(e,t)=>e.layoutContentId?t[e.layoutContentId]??null:null,{skipVoid:!1}),isActive:l,isActiveStep:l,...d})}function c(){return i(e)}function l(){let{layoutContentStore:e}=c();return e.map(e=>e?.data??null,{skipVoid:!1})}export{c as getStep,l as getStepContent,s as setStepContext};
1
+ import{STEP_CONTEXT_KEY as e}from"../context.js";import{getPicked as t}from"./client.js";import{getStepRouter as n}from"../router/context.js";import{getContext as r,setContext as i}from"svelte";import{createForm as a}from"../form/create-form.svelte";function o(r){let o=t(),{activeStep:s}=n(),c=s.map(e=>e?.key===r),l=o.steps.listStore.map(e=>e.find(e=>e.key===r)??{id:r,key:r,name:``,fieldKeys:[]});return i(e,{step:l,isActive:c,isActiveStep:c,...a(r,l.map(e=>e.name),l.map(e=>e.fieldKeys))})}function s(){return r(e)}export{s as getStep,o as setStepContext};
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  /** @file Editable table row for a single field response in the devtools responses screen. */
3
- import type { ResponseListItem, Field, FieldValue, JsonValue } from '@picked/client'
3
+ import type { ResponseListItem, PrimitiveFieldValue, Field } from '@picked/client'
4
4
  import { getPicked } from '../../../../hooks'
5
5
  import { Button, Text, CodeBlock, Banner, Stack } from '../../ui'
6
6
 
@@ -13,7 +13,7 @@
13
13
  let editValue = ''
14
14
  let editError = ''
15
15
  // eslint-disable-next-line svelte/prefer-svelte-reactivity -- Set is reassigned for Svelte reactivity via `selectedOptions = selectedOptions`
16
- let selectedOptions: Set<JsonValue> = new Set()
16
+ let selectedOptions: Set<PrimitiveFieldValue> = new Set()
17
17
 
18
18
  $: hasOptions = Array.isArray(field?.options) && field.options.length > 0
19
19
  $: staticOptions = Array.isArray(field?.options) ? field.options : null
@@ -22,8 +22,7 @@
22
22
  /**
23
23
  * Formats a response value for display, handling arrays, objects, and primitives.
24
24
  *
25
- * @param {unknown} value - The response value to format.
26
- * @returns {string} The display string for the value.
25
+ * @param value - The response value to format.
27
26
  * @example
28
27
  * ```typescript
29
28
  * formatValue(['a', 'b']) // 'a, b'
@@ -88,13 +87,13 @@
88
87
  /**
89
88
  * Toggles selection of a field option, supporting both single and multi-select modes.
90
89
  *
91
- * @param {JsonValue} optionValue - The option value to toggle.
90
+ * @param optionValue - The option value to toggle.
92
91
  * @example
93
92
  * ```typescript
94
93
  * toggleOption('red') // selects or deselects the 'red' option
95
94
  * ```
96
95
  */
97
- function toggleOption(optionValue: JsonValue) {
96
+ function toggleOption(optionValue: PrimitiveFieldValue) {
98
97
  if (field?.multiple) {
99
98
  if (selectedOptions.has(optionValue)) {
100
99
  selectedOptions.delete(optionValue)
@@ -111,15 +110,14 @@
111
110
  /**
112
111
  * Parses a string input into a typed value based on the field's type.
113
112
  *
114
- * @param {string} input - The raw string input to parse.
115
- * @returns {FieldValue} The parsed value (null, number, boolean, JSON, or string).
113
+ * @param input - The raw string input to parse.
116
114
  * @example
117
115
  * ```typescript
118
116
  * parseValue('42') // 42 (when field.type is 'number')
119
117
  * parseValue('true') // true (when field.type is 'boolean')
120
118
  * ```
121
119
  */
122
- function parseValue(input: string): FieldValue {
120
+ function parseValue(input: string): unknown {
123
121
  const trimmed = input.trim()
124
122
 
125
123
  if (trimmed === '' || trimmed === '-') {
@@ -175,7 +173,7 @@
175
173
  newValue = parseValue(editValue)
176
174
  }
177
175
 
178
- const result = await client.responses.commit({ [field.key]: newValue })
176
+ const result = await client.responses.commit({ [field.id]: newValue })
179
177
 
180
178
  if (result.errors.length > 0) {
181
179
  editError = result.errors[0].userMessage
@@ -199,7 +197,7 @@
199
197
  * ```
200
198
  */
201
199
  function handleClear() {
202
- client.responses.clear(field.key)
200
+ client.responses.clear(field.id)
203
201
  }
204
202
  </script>
205
203
 
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  /** @file Root router component that manages step registration and active step detection via Effector. */
3
- import { combine, createEvent, createStore } from 'effector'
3
+ import { createEvent, createStore, sample } from 'effector'
4
+ import { supportsWindow } from '@picked/client'
4
5
  import { getExperience } from '../hooks'
5
6
  import { setStepRouter, type Step } from './context'
6
7
 
@@ -8,24 +9,57 @@
8
9
 
9
10
  const { currentStepStore } = experience
10
11
 
12
+ const activeStepStore = createStore<Step | null>(null)
13
+ let hasActiveStep = false
11
14
  const stepsStore = createStore<Step[]>([])
12
15
 
13
- const registerStep = createEvent<Step>()
14
- const unregisterStep = createEvent<Step>()
16
+ const registerStepEvent = createEvent<Step>()
17
+ const unregisterStepEvent = createEvent<Step>()
18
+ const setActiveStepEvent = createEvent<Step | null>()
15
19
 
16
- stepsStore
17
- .on(registerStep, (state, step) => [...state, step])
18
- .on(unregisterStep, (state, step) => state.filter((s) => s !== step))
20
+ stepsStore.on(registerStepEvent, (state, step) => [...state, step])
21
+ stepsStore.on(unregisterStepEvent, (state, step) => state.filter((s) => s !== step))
19
22
 
20
- const activeStepStore = combine(
21
- { steps: stepsStore, currentStep: currentStepStore },
22
- ({ steps, currentStep }) => steps.find((s) => s.key === currentStep?.key) ?? null,
23
- )
23
+ sample({
24
+ source: setActiveStepEvent,
25
+ filter: (step) => step !== null,
26
+ target: activeStepStore,
27
+ })
28
+
29
+ const registerStep = (step: Step) => {
30
+ // todo: getIsSSR context
31
+
32
+ if (!supportsWindow()) {
33
+ // In SSR we should set the activeStep immediately if it is a match.
34
+ // If there are more Routes being registered after a match is found,
35
+ // we just skip them.
36
+ if (hasActiveStep) return
37
+
38
+ const isMatchingStep = step.key === currentStepStore.getState()?.key
39
+
40
+ if (isMatchingStep) {
41
+ setActiveStepEvent(step)
42
+ hasActiveStep = true
43
+ }
44
+ } else {
45
+ registerStepEvent(step)
46
+ }
47
+ }
48
+
49
+ const unregisterStep = (step: Step) => {
50
+ unregisterStepEvent(step)
51
+ }
52
+
53
+ sample({
54
+ source: { steps: stepsStore, currentStep: currentStepStore },
55
+ fn: ({ steps, currentStep }) => steps.find((s) => s.key === currentStep?.key) || null,
56
+ target: setActiveStepEvent,
57
+ })
24
58
 
25
59
  setStepRouter({
26
60
  registerStep,
27
61
  unregisterStep,
28
- activeStep: activeStepStore,
62
+ activeStep: activeStepStore.map((val) => val),
29
63
  })
30
64
  </script>
31
65
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picked/svelte",
3
- "version": "0.0.62-next.11",
3
+ "version": "0.0.62-next.2",
4
4
  "dependencies": {
5
5
  "d3": "^7.9.0"
6
6
  },
@@ -88,7 +88,7 @@
88
88
  },
89
89
  "module": "./dist/index.js",
90
90
  "peerDependencies": {
91
- "@picked/client": "0.0.62-next.11",
91
+ "@picked/client": "0.0.62-next.2",
92
92
  "effector": "^23.3.0",
93
93
  "svelte": "^5.46.4"
94
94
  },
@@ -1,18 +0,0 @@
1
- import { Store } from 'effector';
2
- import { Content } from '@picked/client';
3
- /**
4
- * Returns the registry store for a content id, mirroring `getField(key)`. Resolves
5
- * the Picked client via `getPicked()` and returns `client.contents.getById(id)`.
6
- *
7
- * @param {string} id - The content record id to look up.
8
- * @returns {Store<Content | null>} The registry store; `null` until content is registered.
9
- * @example
10
- * ```svelte
11
- * <script>
12
- * import { getContent } from '@picked/svelte'
13
- * const banner = getContent('lc_banner')
14
- * </script>
15
- * <h1>{$banner?.data?.headline ?? ''}</h1>
16
- * ```
17
- */
18
- export declare function getContent(id: string): Store<Content | null>;
@@ -1 +0,0 @@
1
- import{getPicked as e}from"./client.js";function t(t){return e().contents.getById(t)}export{t as getContent};