@picked/svelte 0.0.1-dev.1784511339717 → 0.0.1-dev.1785287094311

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,30 @@
1
+ <script lang="ts">
2
+ // Test-only harness. `createForm` registers option callbacks with `$effect`,
3
+ // which requires a real component instance — mounting this is how the callback
4
+ // lifecycle (registration on mount, teardown on unmount) gets exercised.
5
+ import { untrack } from 'svelte'
6
+ import type { Store } from 'effector'
7
+ import { createForm, type FormCallbackOptions } from '../create-form.svelte'
8
+
9
+ interface HarnessProps {
10
+ formId: string
11
+ title: Store<string>
12
+ fieldKeys: Store<string[]>
13
+ options?: FormCallbackOptions
14
+ imperativeCallback?: () => void
15
+ }
16
+
17
+ const { formId, title, fieldKeys, options, imperativeCallback }: HarnessProps = $props()
18
+
19
+ // Props are read once, at init, on purpose: the harness is mounted with fixed
20
+ // props to exercise registration and teardown, and `createForm` itself is an
21
+ // init-time call. `untrack` states that intent rather than suppressing the
22
+ // state_referenced_locally warning.
23
+ untrack(() => {
24
+ const instance = createForm(formId, title, fieldKeys, options)
25
+
26
+ if (imperativeCallback) {
27
+ instance.form.onSuccess(imperativeCallback)
28
+ }
29
+ })
30
+ </script>
@@ -1 +1 @@
1
- import{getExperience as e,getPicked as t}from"../hooks/client.js";import{createForm as n}from"@picked/client/form";import*as r from"svelte/internal/client";function i(i,a,o){let s=n({client:t(),experienceInstance:e()},i,a,o);return{...s,form:{...s.form,props:{...s.form.props,onsubmit:e=>s.form.props.onsubmit(e)},onBeforeSubmit:e=>{r.user_effect(()=>s.form.onBeforeSubmit(e))},onSuccess:e=>{r.user_effect(()=>s.form.onSuccess(e))},onError:e=>{r.user_effect(()=>s.form.onError(e))}}}}export{i as createForm};
1
+ import{getExperience as e,getPicked as t}from"../hooks/client.js";import{createForm as n}from"@picked/client/form";import*as r from"svelte/internal/client";function i(i,a,o,s){let c=n({client:t(),experienceInstance:e()},i,a,o);if(s?.onBeforeSubmit){let e=s.onBeforeSubmit;r.user_effect(()=>c.form.onBeforeSubmit(e))}if(s?.onSuccess){let e=s.onSuccess;r.user_effect(()=>c.form.onSuccess(e))}if(s?.onError){let e=s.onError;r.user_effect(()=>c.form.onError(e))}return{...c,form:{...c.form,props:{...c.form.props,onsubmit:e=>c.form.props.onsubmit(e)},onBeforeSubmit:e=>{r.user_effect(()=>c.form.onBeforeSubmit(e))},onSuccess:e=>{r.user_effect(()=>c.form.onSuccess(e))},onError:e=>{r.user_effect(()=>c.form.onError(e))}}}}export{i as createForm};
@@ -1,6 +1,6 @@
1
1
  import { Store } from 'effector';
2
- import { FormInstance as CoreFormInstance, ErrorCallback, SubmitCallback, SubmitEventWithCurrentTarget, SuccessCallback } from '@picked/client/form';
3
- export type { FormField } from '@picked/client/form';
2
+ import { FormInstance as CoreFormInstance, ErrorCallback, FormCallbackOptions, SubmitCallback, SubmitEventWithCurrentTarget, SuccessCallback } from '@picked/client/form';
3
+ export type { FormField, FormCallbackOptions } from '@picked/client/form';
4
4
  /**
5
5
  * Svelte FormInstance — identical to core but callback registration returns void
6
6
  * (cleanup is handled automatically via $effect, not by the consumer).
@@ -28,10 +28,12 @@ export interface FormInstance<TFieldKeys extends string = string> extends Omit<C
28
28
  * @param {string} formId - Unique identifier for this form instance.
29
29
  * @param {Store<string>} title - Reactive store holding the form/step title.
30
30
  * @param {Store<string[]>} fieldKeys - Reactive store of field keys that belong to this form.
31
+ * @param {FormCallbackOptions} [options] - Submit callback slots, registered once for the component's lifetime.
31
32
  * @returns {FormInstance} A form instance with reactive field stores, submission handlers, and callback registration.
32
33
  * @example
33
34
  * ```ts
34
- * const { form, fields } = createForm('lead-capture', $title, $fieldKeys)
35
+ * const { form, fields } = createForm('lead-capture', $title, $fieldKeys, { onSuccess })
35
36
  * ```
37
+ * @design-parity Mirrors `useForm`'s options argument in `@picked/react`.
36
38
  */
37
- export declare function createForm(formId: string, title: Store<string>, fieldKeys: Store<string[]>): FormInstance;
39
+ export declare function createForm(formId: string, title: Store<string>, fieldKeys: Store<string[]>, options?: FormCallbackOptions): FormInstance;
@@ -1,2 +1,3 @@
1
- export type { FormField } from '@picked/client/form';
1
+ /** @file Public surface of `@picked/svelte/form`. */
2
+ export type { FormField, FormCallbackOptions } from '@picked/client/form';
2
3
  export { getForm } from './get-form';
@@ -1,5 +1,40 @@
1
- export declare function getFeature(featureName: string): import('effector').Store<() => Promise<boolean | string | undefined>>;
2
- export declare function getFeatureResult(featureName: string): import('effector').StoreWritable<{
1
+ import { Store } from 'effector';
2
+ interface FeatureResult {
3
3
  id: string;
4
4
  bucket: string | boolean;
5
- } | undefined>;
5
+ }
6
+ type FeatureBucketValue = boolean | string | undefined;
7
+ /**
8
+ * Returns the reactive store wrapping a feature in an evokable function.
9
+ *
10
+ * @param {string} featureName - The feature id to look up.
11
+ * @returns {Store<() => Promise<FeatureBucketValue>>} The evokable-feature store.
12
+ * @example
13
+ * const $evokable = getFeature('winter-sale')
14
+ */
15
+ export declare function getFeature(featureName: string): Store<() => Promise<FeatureBucketValue>>;
16
+ /**
17
+ * Returns a store that resolves to a feature's evaluated bucket result.
18
+ *
19
+ * @param {string} featureName - The feature id to evaluate.
20
+ * @returns {Store<FeatureResult | undefined>} A store holding the resolved bucket result, or undefined until resolved.
21
+ * @example
22
+ * const $result = getFeatureResult('winter-sale')
23
+ */
24
+ export declare function getFeatureResult(featureName: string): Store<FeatureResult | undefined>;
25
+ /**
26
+ * Returns a store holding a feature's admin `enabled` flag.
27
+ *
28
+ * Unlike {@link getFeatureResult}, this reads the static config flag directly and does not
29
+ * trigger bucket resolution — so a disabled feature (`enabled: false`) can be told apart
30
+ * from an enabled feature whose session simply was not allocated. Resolves to `undefined`
31
+ * when the feature is unregistered or carries no `enabled` metadata (for example,
32
+ * manually-registered features).
33
+ *
34
+ * @param {string} featureName - The feature id to look up.
35
+ * @returns {Store<boolean | undefined>} A store holding the feature's `enabled` flag, or undefined when unknown.
36
+ * @example
37
+ * const $enabled = getFeatureEnabled('winter-sale')
38
+ */
39
+ export declare function getFeatureEnabled(featureName: string): Store<boolean | undefined>;
40
+ export {};
@@ -1 +1 @@
1
- import{getPicked as e}from"./client.js";import{attach as t,createEffect as n,createEvent as r,createStore as i,sample as a}from"effector";function o(t){return e().features.getEvokableFeature(t)}function s(e){let s=o(e),c=i(void 0,{skipVoid:!1}),l=r(),u=t({source:s,mapParams:(e,t)=>t,effect:n(async e=>await e())});return a({clock:l,target:u}),a({clock:u.doneData,fn:t=>{if(t!==void 0)return{id:e,bucket:t}},target:c}),l(),a({clock:s,target:l}),c}export{o as getFeature,s as getFeatureResult};
1
+ import{getPicked as e}from"./client.js";import{attach as t,createEffect as n,createEvent as r,createStore as i,sample as a}from"effector";function o(t){return e().features.getEvokableFeature(t)}function s(e){let s=o(e),c=i(void 0,{skipVoid:!1}),l=r(),u=t({source:s,mapParams:(e,t)=>t,effect:n(async e=>await e())});return a({clock:l,target:u}),a({clock:u.doneData,fn:t=>{if(t!==void 0)return{id:e,bucket:t}},target:c}),l(),a({clock:s,target:l}),c}function c(t){return e().features.getById(t).map(e=>e?.enabled,{skipVoid:!1})}export{o as getFeature,c as getFeatureEnabled,s as getFeatureResult};
@@ -1,7 +1,7 @@
1
1
  /** @file Public re-exports for Svelte hook utilities. */
2
2
  export { getPicked, getExperience } from './client';
3
3
  export { getPredicate, getPredicateResult } from './predicate';
4
- export { getFeature, getFeatureResult } from './feature';
4
+ export { getFeature, getFeatureResult, getFeatureEnabled } from './feature';
5
5
  export { getAction, getActionResult } from './action';
6
6
  export { getStep, setStepContext, getStepContent } from './step';
7
7
  export { getContent } from './content';
@@ -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,getFeatureEnabled as a,getFeatureResult as o}from"./feature.js";import{getAction as s,getActionResult as c}from"./action.js";import{getStep as l,getStepContent as u,setStepContext as d}from"./step.js";import{getContent as f}from"./content.js";import{getContextScope as p,setContextScope as m,useUnit as h}from"./stores.js";import{createLocalStorageStore as g,createSessionStorageStore as _}from"./storage.js";import{getTrackRecommendationPresentEvent as v}from"./events.js";import{createQuery as y,queryCache as b,queryPresets as x}from"./create-query/index.js";export{g as createLocalStorageStore,y as createQuery,_ as createSessionStorageStore,s as getAction,c as getActionResult,f as getContent,p as getContextScope,e as getExperience,i as getFeature,a as getFeatureEnabled,o as getFeatureResult,t as getPicked,n as getPredicate,r as getPredicateResult,l as getStep,u as getStepContent,v as getTrackRecommendationPresentEvent,b as queryCache,x as queryPresets,m as setContextScope,d as setStepContext,h as useUnit};
@@ -1,6 +1,6 @@
1
1
  import { Store } from 'effector';
2
2
  import { Content, ExperienceStep } from '@picked/client';
3
- import { FormInstance, FormField } from '../form/create-form.svelte';
3
+ import { FormCallbackOptions, 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. */
@@ -26,17 +26,29 @@ export interface StepContext extends FormInstance {
26
26
  * Creates and sets step context in the Svelte context tree.
27
27
  *
28
28
  * @param {string} stepKey - The step key.
29
+ * @param {FormCallbackOptions} [options] - Submit callback slots for the step's form.
29
30
  * @returns {StepContext} The created step context.
30
- * @example setStepContext('step-1')
31
+ * @example setStepContext('step-1', { onSuccess: ({ data }) => track(data) })
31
32
  */
32
- export declare function setStepContext(stepKey: string): StepContext;
33
+ export declare function setStepContext(stepKey: string, options?: FormCallbackOptions): StepContext;
33
34
  /**
34
35
  * Retrieves the step context from the Svelte context tree.
35
36
  *
37
+ * Passing `options` registers those callbacks for the calling component's
38
+ * lifetime. It is sugar over `form.onSuccess(cb)` and friends, which already
39
+ * manage their own teardown via `$effect` — the value is symmetry with
40
+ * `useStep(options)` in `@picked/react`, where the options form is what makes
41
+ * render-body registration safe.
42
+ *
43
+ * Must be called during component initialisation, like any other rune-backed
44
+ * helper.
45
+ *
46
+ * @param {FormCallbackOptions} [options] - Submit callback slots for this component.
36
47
  * @returns {StepContext} The current step context.
37
- * @example getStep()
48
+ * @example const { form, fields } = getStep({ onSuccess: ({ data }) => track(data) })
49
+ * @design-parity Mirrors `useStep(options)` in `@picked/react`.
38
50
  */
39
- export declare function getStep(): StepContext;
51
+ export declare function getStep(options?: FormCallbackOptions): StepContext;
40
52
  /**
41
53
  * Returns a Svelte/Effector store that yields the current step's resolved CMS content
42
54
  * data, or `null` when no content is registered for the step's `layoutContentId`.
@@ -1 +1 @@
1
- import{STEP_CONTEXT_KEY as e}from"../context.js";import{getExperience as t,getPicked as n}from"./client.js";import{getStepRouter as r}from"../router/context.js";import{getContext as i,setContext as a}from"svelte";import{combine as o}from"effector";import{createForm as s}from"../form/create-form.svelte";function c(t){let i=n(),{activeStep:c}=r(),l=c.map(e=>e?.key===t),u=i.steps.listStore.map(e=>e.find(e=>e.key===t)??{id:t,key:t,name:``,fieldKeys:[]}),d=s(t,u.map(e=>e.name),u.map(e=>e.fieldKeys)),f=o(u,i.contents.indexStore,(e,t)=>e.layoutContentId?t[e.layoutContentId]??null:null,{skipVoid:!1});return a(e,{step:u,layoutContentStore:f,content:f.map(e=>e?.data??null,{skipVoid:!1}),isActive:l,isActiveStep:l,...d})}function l(){return i(e)}function u(){let t=i(e);return t?t.content:d().map(e=>e?.data??null,{skipVoid:!1})}function d(){let e=t(),r=n();return o(e.treeStore,r.contents.indexStore,(e,t)=>{let n=e.steps.find(e=>e.layoutContentId);return n?.layoutContentId?t[n.layoutContentId]??null:null})}export{l as getStep,u as getStepContent,c as setStepContext};
1
+ import{STEP_CONTEXT_KEY as e}from"../context.js";import{getExperience as t,getPicked as n}from"./client.js";import{getStepRouter as r}from"../router/context.js";import{getContext as i,setContext as a}from"svelte";import{combine as o}from"effector";import{createForm as s}from"../form/create-form.svelte";function c(t,i){let c=n(),{activeStep:l}=r(),u=l.map(e=>e?.key===t),d=c.steps.listStore.map(e=>e.find(e=>e.key===t)??{id:t,key:t,name:``,fieldKeys:[]}),f=s(t,d.map(e=>e.name),d.map(e=>e.fieldKeys),i),p=o(d,c.contents.indexStore,(e,t)=>e.layoutContentId?t[e.layoutContentId]??null:null,{skipVoid:!1});return a(e,{step:d,layoutContentStore:p,content:p.map(e=>e?.data??null,{skipVoid:!1}),isActive:u,isActiveStep:u,...f})}function l(t){let n=i(e);return t?.onBeforeSubmit&&n.form.onBeforeSubmit(t.onBeforeSubmit),t?.onSuccess&&n.form.onSuccess(t.onSuccess),t?.onError&&n.form.onError(t.onError),n}function u(){let t=i(e);return t?t.content:d().map(e=>e?.data??null,{skipVoid:!1})}function d(){let e=t(),r=n();return o(e.treeStore,r.contents.indexStore,(e,t)=>{let n=e.steps.find(e=>e.layoutContentId);return n?.layoutContentId?t[n.layoutContentId]??null:null})}export{l as getStep,u as getStepContent,c as setStepContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picked/svelte",
3
- "version": "0.0.1-dev.1784511339717",
3
+ "version": "0.0.1-dev.1785287094311",
4
4
  "dependencies": {
5
5
  "d3": "^7.9.0"
6
6
  },
@@ -106,7 +106,7 @@
106
106
  },
107
107
  "module": "./dist/index.js",
108
108
  "peerDependencies": {
109
- "@picked/client": "0.0.1-dev.1784511339717",
109
+ "@picked/client": "0.0.1-dev.1785287094311",
110
110
  "effector": "^23.3.0",
111
111
  "svelte": "^5.46.4"
112
112
  },