@picked/svelte 0.0.1-dev.1773807602703 → 0.0.1-dev.1773878362211

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.
@@ -0,0 +1 @@
1
+ import*as o from"svelte/internal/client";import{createForm as f}from"@picked/client/form";import{getExperience as n,getPicked as s}from"../hooks/client.js";function a(t,c,m){const e=f({client:s(),experienceInstance:n()},t,c,m);return{...e,form:{...e.form,onSubmit:r=>{o.user_effect(()=>e.form.onSubmit(r))},onSuccess:r=>{o.user_effect(()=>e.form.onSuccess(r))},onError:r=>{o.user_effect(()=>e.form.onError(r))}}}}export{a as createForm};
@@ -0,0 +1,24 @@
1
+ import { Store } from 'effector';
2
+ import { FormInstance as CoreFormInstance, ErrorCallback, SubmitCallback, SuccessCallback } from '@picked/client/form';
3
+ export type { FormField } from '@picked/client/form';
4
+ /**
5
+ * Svelte FormInstance — identical to core but callback registration returns void
6
+ * (cleanup is handled automatically via $effect, not by the consumer).
7
+ */
8
+ export interface FormInstance<TFieldIds extends string = string> extends Omit<CoreFormInstance<TFieldIds>, 'form'> {
9
+ form: Omit<CoreFormInstance<TFieldIds>['form'], 'onSubmit' | 'onSuccess' | 'onError'> & {
10
+ onSubmit: (callback: SubmitCallback<TFieldIds>) => void;
11
+ onSuccess: (callback: SuccessCallback<TFieldIds>) => void;
12
+ onError: (callback: ErrorCallback) => void;
13
+ };
14
+ }
15
+ /**
16
+ * Creates a form instance with Svelte lifecycle management.
17
+ *
18
+ * Wraps the framework-agnostic createForm from @picked/client/form:
19
+ * - Injects client and experienceInstance from Svelte context
20
+ * - Auto-wires callback cleanup via $effect so consumers don't need to manage lifecycle
21
+ *
22
+ * Used internally by setStepContext — access via getStep() in components.
23
+ */
24
+ export declare function createForm(formId: string, title: Store<string>, fieldIds: Store<string[]>): FormInstance;
@@ -0,0 +1 @@
1
+ export * from './create-form.js';
@@ -0,0 +1,16 @@
1
+ import { ValidationError } from '@picked/client';
2
+ interface GetFormOptions {
3
+ id: string;
4
+ title: string;
5
+ onSuccess?: () => void | Promise<void>;
6
+ onError?: (errors: ValidationError[]) => void | Promise<void>;
7
+ }
8
+ type SubmitEventWithCurrentTarget = SubmitEvent & {
9
+ currentTarget: EventTarget & HTMLFormElement;
10
+ };
11
+ export declare function getForm({ id: formId, title, onError, onSuccess }: GetFormOptions): {
12
+ form: {
13
+ onsubmit: import('effector').EventCallable<SubmitEventWithCurrentTarget>;
14
+ };
15
+ };
16
+ export {};
@@ -0,0 +1 @@
1
+ import{buildResponsesFromFormData as g}from"@picked/client/form";import{createEvent as E,createEffect as c,attach as f,sample as u,split as F}from"effector";import{getPicked as S,getExperience as b}from"../hooks/client.js";import"@picked/client";import{getStep as h}from"../hooks/step.js";import"svelte";import"svelte/store";import"@picked/analytics";function T({id:i,title:n,onError:d,onSuccess:l}){const r=S(),v=h(),o=b(),{currentStepStore:s}=o,p=E(),a=c(e=>r.responses.commit(e)),x=f({source:{step:s},effect:c(({step:e})=>{r.eventBus({type:"form_submit_success",form:{id:i,title:n},experience:o,step:e??void 0}),l?.()})}),_=f({source:{step:s},mapParams:(e,t)=>({step:t.step,errors:e.errors}),effect:c(({step:e,errors:t})=>{r.eventBus({type:"form_submit_error",form:{id:i,title:n},exception:{reason:t},experience:o,step:e??void 0}),t.forEach(m=>{r.eventBus({type:"field_validation_error",exception:{reason:[m]},experience:o,step:e??void 0})}),d?.(t)})});return u({clock:p,source:{step:s},fn:({step:e})=>({formId:i,title:n,step:e}),target:c(({formId:e,title:t,step:m})=>{r.eventBus({type:"form_submit",form:{id:e,title:t},experience:o,step:m??void 0})})}),u({clock:p,source:{fields:r.fields.listStore,stepFields:v.fields,step:s},fn:({stepFields:e},t)=>(t.preventDefault(),g(e,new FormData(t.currentTarget))),target:a}),F({source:a.doneData,match:{hasErrors:({errors:e})=>e.length>0},cases:{hasErrors:_,__:x}}),{form:{onsubmit:p}}}export{T as getForm};
@@ -1,25 +1,2 @@
1
- import { ValidationError } from '@picked/client';
2
- interface GetFormOptions {
3
- id: string;
4
- title: string;
5
- onSuccess?: () => void | Promise<void>;
6
- onError?: (errors: ValidationError[]) => void | Promise<void>;
7
- }
8
- type SubmitEventWithCurrentTarget = SubmitEvent & {
9
- currentTarget: EventTarget & HTMLFormElement;
10
- };
11
- /**
12
- *
13
- * @param root0
14
- * @param root0.id
15
- * @param root0.title
16
- * @param root0.onError
17
- * @param root0.onSuccess
18
- * @example
19
- */
20
- export declare function getForm({ id: formId, title, onError, onSuccess }: GetFormOptions): {
21
- form: {
22
- onsubmit: import('effector').EventCallable<SubmitEventWithCurrentTarget>;
23
- };
24
- };
25
- export {};
1
+ export type { FormField } from '@picked/client/form';
2
+ export { getForm } from './get-form';
@@ -1 +1 @@
1
- import{createEvent as _,createEffect as m,attach as y,sample as v,split as k}from"effector";import{getPicked as D,getExperience as F}from"../hooks/client.js";import"@picked/client";import{getStep as w}from"../hooks/step.js";import"svelte";import"svelte/store";import"@picked/analytics";function z({id:f,title:l,onError:b,onSuccess:g}){const o=D(),x=w(),i=F(),{currentStepStore:u}=i,d=_(),h=m(r=>o.responses.commit(r)),E=y({source:{step:u},effect:m(async({step:r})=>{o.eventBus({type:"form_submit_success",form:{id:f,title:l},experience:i,step:r??void 0}),await g?.()})}),S=y({source:{step:u},mapParams:(r,a)=>({step:a.step,errors:r.errors}),effect:m(async({step:r,errors:a})=>{o.eventBus({type:"form_submit_error",form:{id:f,title:l},exception:{reason:a},experience:i,step:r??void 0}),a.forEach(c=>{o.eventBus({type:"field_validation_error",exception:{reason:[c]},experience:i,step:r??void 0})}),await b?.(a)})});return v({clock:d,source:{step:u},fn:({step:r})=>({formId:f,title:l,step:r}),target:m(({formId:r,title:a,step:c})=>{o.eventBus({type:"form_submit",form:{id:r,title:a},experience:i,step:c??void 0})})}),v({clock:d,source:{fields:o.fields.listStore,stepFields:x.fields,step:u},fn:({stepFields:r},a)=>{a.preventDefault();const c=new FormData(a.currentTarget),A=Array.from(c.entries()),p={data:{},push(t){const s=t.questionId,e=this.data[s];e?Array.isArray(e)&&Array.isArray(t.value)?Array.isArray(e)&&Array.isArray(t.value)&&(typeof e[0]=="string"?this.data[s]=[...e,...t.value].map(String):typeof e[0]=="number"?this.data[s]=[...e,...t.value].map(Number):typeof e[0]=="boolean"?this.data[s]=[...e,...t.value].map(n=>!!n):this.data[s]=t.value):this.data[s]=t.value:this.data[s]=t.value}};return r.forEach(t=>{let s=A.filter(([e])=>e===t.key||e===t.id);s.length===0&&(s=[[t.id,""]]),s.forEach(([,e])=>{const n=t.id;if(e===""){p.push({questionId:n,value:null});return}switch(t.type){case"text":p.push({questionId:n,value:t.multiple?[String(e)]:String(e)});break;case"number":p.push({questionId:n,value:t.multiple?[Number(e)]:Number(e)});break;case"boolean":p.push({questionId:n,value:t.multiple?[e==="true"]:e==="true"});break}})}),p.data},target:h}),k({source:h.doneData,match:{hasErrors:({errors:r})=>r.length>0},cases:{hasErrors:S,__:E}}),{form:{onsubmit:d}}}export{z as getForm};
1
+ import{getForm as e}from"./get-form.js";export{e as getForm};
@@ -1,8 +1,7 @@
1
1
  import { Field, FieldValue } from '@picked/client';
2
2
  import { Store } from 'effector';
3
- interface GetFieldResponse {
3
+ export interface GetFieldResponse {
4
4
  value: Store<FieldValue>;
5
5
  field: Store<Field | null>;
6
6
  }
7
- export declare function getField(key: string): GetFieldResponse;
8
- export {};
7
+ export declare function getField(id: string): GetFieldResponse;
@@ -1 +1 @@
1
- import{getPicked as s}from"./client.js";function r(e){const t=s(),n=t.fields.getByKey(e),o=t.responses.getByFieldKey(e);return{field:n,value:o}}export{r as getField};
1
+ import{getPicked as s}from"./client.js";function r(e){const t=s(),n=t.fields.getById(e),o=t.responses.getByFieldId(e);return{field:n,value:o}}export{r as getField};
@@ -1,13 +1,13 @@
1
1
  import { Store } from 'effector';
2
- import { ExperienceStep, Field, Response } from '@picked/client';
3
- type FieldWithValue = Field & {
4
- value: Response | undefined;
5
- };
6
- export interface StepContext {
2
+ import { ExperienceStep } from '@picked/client';
3
+ import { FormInstance, FormField } from '../form/create-form.svelte';
4
+ export interface StepContext extends FormInstance {
7
5
  step: Store<ExperienceStep>;
8
- fields: Store<FieldWithValue[]>;
6
+ /** Directly accessible fields with current response values — usable without a form */
7
+ fields: Store<FormField[]>;
8
+ isActive: Store<boolean>;
9
+ /** @deprecated Use `isActive` instead */
9
10
  isActiveStep: Store<boolean>;
10
11
  }
11
- export declare function getStep(): StepContext;
12
12
  export declare function setStepContext(stepId: string): StepContext;
13
- export {};
13
+ export declare function getStep(): StepContext;
@@ -1 +1 @@
1
- import{getContext as g,setContext as y}from"svelte";import{createStore as v,combine as a,attach as h,createEffect as k,sample as l}from"effector";import{getStepFields as x}from"../utils/get-step-fields.js";import{STEP_CONTEXT_KEY as u}from"../context.js";import{getStepRouter as E}from"../router/context.js";import{getPicked as K}from"./client.js";function _(){return g(u)}function b(o){const r=K(),{activeStep:S}=E(),n=S.map(e=>e?.id===o),f=r.steps.listStore.map(e=>{const i=e.find(t=>(t.key??t.id)===o);if(!i)throw new Error(`Step with id "${o}" not found in the step registry.`);return i}),d=v([]),m=a({fields:d,responses:r.responses.listStore},({fields:e,responses:i})=>e.map(t=>{const s=i.find(p=>p.fieldKey===t.key||p.fieldId===t.id)?.value;return{...t,value:s}})),c=h({source:a({step:f,fields:r.fields.listStore}),effect:k(async({step:e,fields:i})=>{const t=e.fieldKeys&&e.fieldKeys.length>0?i.filter(s=>(e.fieldKeys??[]).includes(s.key)):i.filter(s=>(e.fieldIds??[]).includes(s.id));return await x(r,t)})});return l({source:{isActiveStep:n},filter:({isActiveStep:e})=>e,target:c}),l({clock:r.responses.listStore,source:{isActiveStep:n},filter:({isActiveStep:e})=>e,target:c}),l({source:c.doneData,target:d}),y(u,{step:f,fields:m,isActiveStep:n})}export{_ as getStep,b as setStepContext};
1
+ import{getContext as f,setContext as S}from"svelte";import{STEP_CONTEXT_KEY as s}from"../context.js";import{createForm as a}from"../form/create-form.svelte";import{getStepRouter as u}from"../router/context.js";import{getExperience as x}from"./client.js";function d(e){const t=x().treeStore.map(o=>{const c=o.steps.find(m=>m.id===e);if(!c)throw new Error(`Step with id "${e}" not found in the experience tree.`);return c}),r=t.map(o=>o.label),n=t.map(o=>o.fieldIds),i=a(e,r,n);return{stepStore:t,form:i}}function h(e){const{activeStep:p}=u(),t=p.map(i=>i?.id===e),{stepStore:r,form:n}=d(e);return S(s,{step:r,isActive:t,isActiveStep:t,...n})}function v(){return f(s)}export{v as getStep,h as setStepContext};
@@ -1,13 +1,9 @@
1
1
  <script lang="ts">
2
2
  import type { ExperienceInstance } from '@picked/client'
3
3
  import { Button } from '../ui'
4
- import { getPicked } from '../../../hooks'
5
4
 
6
5
  export let experienceInstance: ExperienceInstance
7
6
 
8
- const client = getPicked()
9
- const experienceLookup = client.experiences.get(experienceInstance.experienceId)
10
-
11
7
  const currentNode = experienceInstance.currentNodeStore
12
8
  const currentStep = experienceInstance.currentStepStore
13
9
  const nextStepNodes = experienceInstance.nextReachableStepNodesStore
@@ -16,24 +12,15 @@
16
12
  const isOpen = experienceInstance.isOpenStore
17
13
 
18
14
  $: totalNextStepNodes = $nextStepNodes.length
19
- $: experienceName = $experienceLookup?.name ?? $experienceLookup?.key ?? experienceInstance.experienceId
20
- $: currentNodeDisplay = $currentNode
21
- ? (('name' in $currentNode && $currentNode.name) ||
22
- ('stepKey' in $currentNode && $currentNode.stepKey) ||
23
- $currentNode.id)
24
- : ''
25
- $: currentStepDisplay = $currentStep
26
- ? ($currentStep.name ?? $currentStep.key ?? $currentStep.id)
27
- : ''
28
15
  </script>
29
16
 
30
17
  <tr>
31
- <td>{experienceName}</td>
18
+ <td>{experienceInstance.experienceId}</td>
32
19
  <td><Button variant="ghost" size="small" onclick={() => experienceInstance.toggleOpen()}>{$isOpen}</Button></td>
33
- <td>{currentNodeDisplay}</td>
20
+ <td>{$currentNode?.id || ''}</td>
34
21
  <td>{$currentNode?.type || ''}</td>
35
- <td>{currentStepDisplay}</td>
36
- <td>{$currentStep?.title || ''}</td>
22
+ <td>{$currentStep?.id || ''}</td>
23
+ <td>{$currentStep?.label || ''}</td>
37
24
  <td>{totalNextStepNodes}</td>
38
25
  <td>{$stepsToOrigin[0]} - {$stepsToOrigin[1]}</td>
39
26
  <td>{$stepsToLeaf[0]} - {$stepsToLeaf[1]}</td>
@@ -6,7 +6,7 @@
6
6
  export let experienceInstances: ExperienceInstance[]
7
7
 
8
8
  const columns = [
9
- { key: 'experience', header: 'Name' },
9
+ { key: 'experience', header: 'Experience' },
10
10
  { key: 'isOpen', header: 'Is Open' },
11
11
  { key: 'currentNodeId', header: 'Current node ID' },
12
12
  { key: 'currentNodeType', header: 'Current node Type' },
@@ -1,23 +1,11 @@
1
1
  <script lang="ts">
2
2
  import type { EventBusPayload, EventHistoryEntry } from '@picked/client'
3
3
  import { Badge, Card, CodeBlock, Stack, Text } from '../../ui'
4
- import { getPicked } from '../../../../hooks'
5
4
 
6
5
  export let event: EventHistoryEntry
7
6
  export let isExpanded: boolean
8
7
  export let onToggle: () => void
9
8
 
10
- const client = getPicked()
11
-
12
- const eventExpId =
13
- 'experience' in event.payload && event.payload.experience
14
- ? event.payload.experience.experienceId
15
- : undefined
16
- const eventExpLookup = client.experiences.get(eventExpId ?? '')
17
- $: eventExpName = eventExpId
18
- ? ($eventExpLookup?.name ?? $eventExpLookup?.key ?? eventExpId)
19
- : '-'
20
-
21
9
  function formatTime(date: Date): string {
22
10
  return date.toLocaleTimeString('en-US', {
23
11
  hour12: false,
@@ -33,49 +21,59 @@
33
21
  value: unknown
34
22
  }
35
23
 
36
- function getExperienceFields(exp: unknown): PayloadField[] {
37
- if (!exp || typeof exp !== 'object') return []
24
+ function getPayloadFields(payload: EventBusPayload): PayloadField[] {
38
25
  const fields: PayloadField[] = []
39
- if ('id' in exp && exp.id) fields.push({ label: 'Experience ID', value: exp.id })
40
- if ('experienceId' in exp && exp.experienceId)
41
- fields.push({ label: 'Experience Type', value: exp.experienceId })
42
- return fields
43
- }
44
26
 
45
- function getStepFields(step: unknown): PayloadField[] {
46
- if (!step || typeof step !== 'object') return []
47
- const fields: PayloadField[] = []
48
- if ('id' in step && step.id) fields.push({ label: 'Step ID', value: step.id })
49
- // eslint-disable-next-line sonarjs/deprecation -- backwards-compat fallback for label
50
- const stepName = ('name' in step && step.name) || ('label' in step && step.label)
51
- if (stepName) fields.push({ label: 'Step Name', value: stepName })
52
- return fields
53
- }
27
+ fields.push({ label: 'Type', value: payload.type })
54
28
 
55
- function getScalarFields(payload: EventBusPayload): PayloadField[] {
56
- const fields: PayloadField[] = []
57
- if ('value' in payload && payload.value !== undefined)
29
+ if ('value' in payload && payload.value !== undefined) {
58
30
  fields.push({ label: 'Value', value: payload.value })
59
- if ('form' in payload && payload.form)
31
+ }
32
+
33
+ if ('experience' in payload && payload.experience) {
34
+ const exp = payload.experience
35
+ if (exp && typeof exp === 'object') {
36
+ if ('id' in exp && exp.id) {
37
+ fields.push({ label: 'Experience ID', value: exp.id })
38
+ }
39
+ if ('experienceId' in exp && exp.experienceId) {
40
+ fields.push({ label: 'Experience Type', value: exp.experienceId })
41
+ }
42
+ }
43
+ }
44
+
45
+ if ('step' in payload && payload.step) {
46
+ const step = payload.step
47
+ if (step && typeof step === 'object') {
48
+ if ('id' in step && step.id) {
49
+ fields.push({ label: 'Step ID', value: step.id })
50
+ }
51
+ if ('label' in step && step.label) {
52
+ fields.push({ label: 'Step Label', value: step.label })
53
+ }
54
+ }
55
+ }
56
+
57
+ if ('form' in payload && payload.form) {
60
58
  fields.push({ label: 'Form', value: JSON.stringify(payload.form) })
61
- if ('feature' in payload && payload.feature)
59
+ }
60
+
61
+ if ('feature' in payload && payload.feature) {
62
62
  fields.push({ label: 'Feature', value: JSON.stringify(payload.feature) })
63
- if ('exception' in payload && payload.exception)
63
+ }
64
+
65
+ if ('exception' in payload && payload.exception) {
64
66
  fields.push({ label: 'Exception', value: JSON.stringify(payload.exception) })
65
- if ('version' in payload && payload.version)
67
+ }
68
+
69
+ if ('version' in payload && payload.version) {
66
70
  fields.push({ label: 'Version', value: payload.version })
67
- return fields
68
- }
71
+ }
69
72
 
70
- function getPayloadFields(payload: EventBusPayload): PayloadField[] {
71
- const fields: PayloadField[] = [{ label: 'Type', value: payload.type }]
72
- fields.push(...getScalarFields(payload))
73
- if ('experience' in payload && payload.experience)
74
- fields.push(...getExperienceFields(payload.experience))
75
- if ('step' in payload && payload.step)
76
- fields.push(...getStepFields(payload.step))
77
- if ('id' in payload && payload.id && payload.type === 'session')
73
+ if ('id' in payload && payload.id && payload.type === 'session') {
78
74
  fields.push({ label: 'Session ID', value: payload.id })
75
+ }
76
+
79
77
  return fields
80
78
  }
81
79
 
@@ -99,7 +97,9 @@
99
97
  <Badge status="info">{event.payload.type}</Badge>
100
98
  </td>
101
99
  <td>
102
- <Text size="small">{eventExpName}</Text>
100
+ <Text size="small">
101
+ {'experience' in event.payload && event.payload.experience ? event.payload.experience.experienceId : '-'}
102
+ </Text>
103
103
  </td>
104
104
  <td>
105
105
  <Text size="caption" color="subdued">
@@ -114,7 +114,7 @@
114
114
  <Text size="small" weight="semibold">Event Payload</Text>
115
115
  <Card>
116
116
  <Stack direction="vertical" gap="small">
117
- {#each getPayloadFields(event.payload) as field (field.label)}
117
+ {#each getPayloadFields(event.payload) as field}
118
118
  <Text size="caption" inline>
119
119
  <Text size="caption" weight="semibold" color="subdued" inline>{field.label}:</Text>
120
120
  <CodeBlock code={formatValue(field.value)} inline />
@@ -11,7 +11,7 @@
11
11
 
12
12
  <Stack direction="vertical" gap="medium" padding="medium">
13
13
  <Stack direction="horizontal" gap="small">
14
- <Button variant="primary" size="small" onclick={() => client.experiences.open({ id: experience.id, options: { bypassCondition: true } })}>
14
+ <Button variant="primary" size="small" onclick={() => client.launchExperienceById(experience.id)}>
15
15
  Launch experience
16
16
  </Button>
17
17
  </Stack>
@@ -9,16 +9,17 @@
9
9
  let zoom = 1
10
10
  let selectedNode = null
11
11
  let highlightedPath: string[][] = []
12
- let error = null
12
+ let error: string | null = null
13
13
  const loading = false
14
14
 
15
15
  let treeRenderingDone = false
16
16
 
17
17
  const tree = experience.treeStore
18
18
 
19
+ $: steps = $tree.steps
19
20
  $: nodes = $tree.nodes
20
21
  $: edges = $tree.edges
21
- $: conditions = $tree.conditions
22
+ $: conditionals = $tree.conditionals
22
23
 
23
24
  let zoomBehavior: d3.ZoomBehavior<SVGSVGElement, unknown>
24
25
 
@@ -88,7 +89,8 @@
88
89
  function renderGraph() {
89
90
  d3.select(svgEl).selectAll('*').remove()
90
91
 
91
- const conditionsMap = new Map(conditions.map((c) => [c.id, c]))
92
+ const stepsMap = new Map(steps.map((s) => [s.id, s]))
93
+ const conditionalsMap = new Map(conditionals.map((c) => [c.id, c]))
92
94
  const outgoingEdges = new Map<string, ExperienceEdge[]>()
93
95
  edges.forEach((e) => {
94
96
  if (!outgoingEdges.has(e.sourceNodeId)) outgoingEdges.set(e.sourceNodeId, [])
@@ -97,13 +99,12 @@
97
99
 
98
100
  const getNodeLabel = (node: ExperienceNode): string => {
99
101
  if (node.type === 'origin') return 'Start'
100
- if (node.type === 'step')
101
- return node.name ?? node.stepKey ?? node.stepId ?? 'Unknown Step'
102
- if (node.type === 'conditional') {
103
- const conditionId = node.conditionId ?? node.conditionalId
104
- const conditionItem = conditionId ? conditionsMap.get(conditionId) : undefined
105
- if (conditionItem?.label) return conditionItem.label
106
- if (conditionItem?.condition) return formatLogicRule(conditionItem.condition)
102
+ if (node.type === 'step' && node.stepId)
103
+ return stepsMap.get(node.stepId)?.label ?? 'Unknown Step'
104
+ if (node.type === 'conditional' && node.conditionalId) {
105
+ const conditional = conditionalsMap.get(node.conditionalId)
106
+ if (conditional?.label) return conditional.label
107
+ if (conditional?.condition) return formatLogicRule(conditional.condition)
107
108
  return 'Condition'
108
109
  }
109
110
  return 'Unknown Node'
@@ -9,7 +9,7 @@
9
9
  $: tabs = $experiences.map((experience) => {
10
10
  return {
11
11
  id: experience.id,
12
- label: experience.name ?? experience.key ?? experience.id,
12
+ label: experience.id,
13
13
  component: ExperienceScreen,
14
14
  props: {
15
15
  experience,
@@ -1,17 +1,12 @@
1
1
  <script lang="ts">
2
2
  import type { HistoryEntry } from '@picked/client'
3
- import { getPicked } from '../../../../hooks'
4
3
 
5
4
  export let historyEntry: HistoryEntry
6
-
7
- const client = getPicked()
8
- const experienceLookup = client.experiences.get(historyEntry.experienceId)
9
- $: experienceName = $experienceLookup?.name ?? $experienceLookup?.key ?? historyEntry.experienceId
10
5
  </script>
11
6
 
12
7
  <tr>
13
8
  <td>{historyEntry.id}</td>
14
- <td>{experienceName}</td>
9
+ <td>{historyEntry.experienceId}</td>
15
10
  <td>{historyEntry.node.id}</td>
16
11
  <td>{historyEntry.node.type}</td>
17
12
  <td>{historyEntry.at}</td>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { ResponseListItem, PrimitiveFieldValue, Field } from '@picked/client'
2
+ import type { ResponseListItem, PrimitiveFieldValue, Field, FieldValue } from '@picked/client'
3
3
  import { getPicked } from '../../../../hooks'
4
4
  import { Button, Text, CodeBlock, Banner, Stack } from '../../ui'
5
5
 
@@ -11,9 +11,10 @@
11
11
  let isEditing = false
12
12
  let editValue = ''
13
13
  let editError = ''
14
- let selectedOptions: Set<PrimitiveFieldValue> = new Set()
14
+ let selectedOptions: Set<FieldValue> = new Set()
15
15
 
16
- $: hasOptions = field?.options && field.options.length > 0
16
+ $: hasOptions = Array.isArray(field?.options) && field.options.length > 0
17
+ $: staticOptions = Array.isArray(field?.options) ? field.options : null
17
18
  $: currentValue = response?.value ?? null
18
19
 
19
20
  function formatValue(value: unknown): string {
@@ -52,7 +53,7 @@
52
53
  selectedOptions = new Set()
53
54
  }
54
55
 
55
- function toggleOption(optionValue: PrimitiveFieldValue) {
56
+ function toggleOption(optionValue: FieldValue) {
56
57
  if (field?.multiple) {
57
58
  if (selectedOptions.has(optionValue)) {
58
59
  selectedOptions.delete(optionValue)
@@ -65,7 +66,7 @@
65
66
  }
66
67
  }
67
68
 
68
- function parseValue(input: string): unknown {
69
+ function parseValue(input: string): FieldValue {
69
70
  input = input.trim()
70
71
 
71
72
  if (input === '' || input === '-') {
@@ -99,14 +100,14 @@
99
100
 
100
101
  async function saveEdit() {
101
102
  try {
102
- let newValue: unknown
103
+ let newValue: FieldValue
103
104
 
104
105
  if (hasOptions) {
105
106
  const values = Array.from(selectedOptions)
106
107
  if (field?.multiple) {
107
108
  newValue = values
108
109
  } else {
109
- newValue = values[0] ?? null
110
+ newValue = values.at(0) ?? null
110
111
  }
111
112
  } else {
112
113
  newValue = parseValue(editValue)
@@ -134,7 +135,7 @@
134
135
 
135
136
  <tr>
136
137
  <td>
137
- <CodeBlock code={field.key ?? field.id} inline />
138
+ <CodeBlock code={field.name} inline />
138
139
  </td>
139
140
  <td>
140
141
  <Text size="small" weight="semibold">{field.label}</Text>
@@ -142,9 +143,9 @@
142
143
  <td>
143
144
  {#if isEditing}
144
145
  <Stack direction="vertical" gap="small">
145
- {#if hasOptions && field?.options}
146
+ {#if hasOptions && staticOptions}
146
147
  <Stack direction="vertical" gap="small">
147
- {#each field.options as option (option.id)}
148
+ {#each staticOptions as option (option.id)}
148
149
  <label class="option-label">
149
150
  {#if field.multiple}
150
151
  <input
@@ -34,7 +34,7 @@
34
34
  }
35
35
 
36
36
  const columns = [
37
- { key: 'id', header: 'Key' },
37
+ { key: 'id', header: 'ID' },
38
38
  { key: 'field', header: 'Field' },
39
39
  { key: 'value', header: 'Value' },
40
40
  { key: 'type', header: 'Type' },
@@ -13,7 +13,6 @@
13
13
 
14
14
  const step = {
15
15
  id,
16
- key: id
17
16
  }
18
17
 
19
18
  const { registerStep, unregisterStep } = getStepRouter()
@@ -51,7 +51,7 @@
51
51
 
52
52
  sample({
53
53
  source: { steps: stepsStore, currentStep: currentStepStore },
54
- fn: ({ steps, currentStep }) => steps.find((s) => s.id === (currentStep?.key ?? currentStep?.id)) || null,
54
+ fn: ({ steps, currentStep }) => steps.find((s) => s.id === currentStep?.id) || null,
55
55
  target: setActiveStepEvent,
56
56
  })
57
57
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picked/svelte",
3
- "version": "0.0.1-dev.1773807602703",
3
+ "version": "0.0.1-dev.1773878362211",
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.1-dev.1773807602703",
91
+ "@picked/client": "0.0.1-dev.1773878362211",
92
92
  "effector": "^23.3.0",
93
93
  "svelte": "^5.34.3"
94
94
  },
@@ -1,2 +0,0 @@
1
- import { Field, Picked } from '@picked/client';
2
- export declare function getStepFields(client: Picked, fields: Field[]): Promise<Field[]>;
@@ -1 +0,0 @@
1
- import{evaluateRuleLogic as s}from"@picked/client";function u(o){return o.options?.some(n=>"condition"in n)??!1}function l(o){return o.some(n=>n.condition||n.conditionKey||u(n))}async function a(o,n){return n.conditionKey?o.conditions.getByKey(n.conditionKey).getState()?.condition??null:n.condition??null}async function g(o,n){return n.length===0||!l(n)?n:(await Promise.all(n.map(async t=>{const r=await a(o,t);if(!(r?await s(o,r):!0))return null;if(!t.options||!u(t))return t;const e=(await Promise.all(t.options.map(async i=>i.condition?await s(o,i.condition)?i:null:i))).filter(i=>i!==null);return e.length===t.options.length?t:e.length===0?null:{...t,options:e}}))).filter(t=>t!==null)}export{g as getStepFields};