@picked/svelte 0.0.1-dev.1780464669265 → 0.0.1-dev.1780552550363

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.
@@ -28,7 +28,13 @@
28
28
  const client = getPicked()
29
29
  const selector = $derived(`.picked-slot-${name}`)
30
30
 
31
- const PLACEMENT_ORDER: ExperienceTarget['placement'][] = ['before', 'prepend', 'append', 'after']
31
+ const PLACEMENT_ORDER: ExperienceTarget['placement'][] = [
32
+ 'replace',
33
+ 'before',
34
+ 'prepend',
35
+ 'append',
36
+ 'after',
37
+ ]
32
38
 
33
39
  interface Candidate {
34
40
  experience: ExperienceStore
@@ -54,8 +60,8 @@
54
60
  }
55
61
 
56
62
  /**
57
- * Maps an experience to a slot candidate, or null when it does not target this slot, uses the
58
- * deferred `replace` placement, or carries an action-referencing condition.
63
+ * Maps an experience to a slot candidate, or null when it does not target this slot or carries
64
+ * an action-referencing condition.
59
65
  *
60
66
  * @param {ExperienceStore} experience - The experience to inspect.
61
67
  * @returns {Candidate | null} The candidate, or null when the experience is not an eligible slot match.
@@ -71,12 +77,6 @@
71
77
  return null
72
78
  }
73
79
 
74
- // `replace` is deferred (first-wins semantics are not implemented yet), so skip it rather than
75
- // letting it fall through and render appended-last.
76
- if (target.placement === 'replace') {
77
- return null
78
- }
79
-
80
80
  // Action-referencing conditions are never cached (their side effect must re-run), so they can
81
81
  // never resolve through the synchronous `peek` the slot path relies on. Slots do not support
82
82
  // action-gated conditions in v1; excluding them also stops the selection effect from re-firing
@@ -102,13 +102,16 @@
102
102
 
103
103
  // Referencing `$conditionResults` keeps this recompute reactive to late condition writes
104
104
  // (the standalone cache-miss path), so a `peek` that returned `undefined` re-renders once
105
- // the async evaluation resolves and writes the store.
106
- const active = $derived(
107
- candidates.filter((candidate) => {
108
- void $conditionResults
109
- return client.conditionResults.peek(candidate.hash) === true
110
- }),
111
- )
105
+ // the async evaluation resolves and writes the store. An active `replace` experience wins:
106
+ // the first one (it sorts first) renders alone, replacing any other slot matches.
107
+ const active = $derived.by(() => {
108
+ void $conditionResults
109
+ const activeCandidates = candidates.filter(
110
+ (candidate) => client.conditionResults.peek(candidate.hash) === true,
111
+ )
112
+ const firstReplace = activeCandidates.find((candidate) => candidate.placement === 'replace')
113
+ return firstReplace ? [firstReplace] : activeCandidates
114
+ })
112
115
 
113
116
  /**
114
117
  * Builds a plain, JSON-serialisable subset of the current URL for the evaluation context.
@@ -2,6 +2,7 @@ import { CreateClientOptions, Picked } from '@picked/client';
2
2
  import { PickedSnapshot } from '@picked/client/server';
3
3
  type SetPickedContextParams = {
4
4
  client: Picked;
5
+ snapshot?: PickedSnapshot;
5
6
  } | {
6
7
  options: CreateClientOptions;
7
8
  snapshot?: PickedSnapshot;
@@ -12,16 +13,17 @@ type SetPickedContextParams = {
12
13
  * Call this once at the top of a component's `<script>` so `setContext` and `onMount` run during
13
14
  * component initialisation. Pass `options` to create the client and synchronously hydrate it from an
14
15
  * optional SSR snapshot (a `versionId` mismatch is tolerated; the client reconciles via `start()`),
15
- * or pass an existing `client` (such as the app's already-running global client) to render
16
- * experiences against it. In the browser the client is started from `onMount`; `start()` is
16
+ * or pass an existing `client` (such as the app's single global client) to render experiences
17
+ * against it — supply `snapshot` alongside `client` to SSR-seed that shared client rather than
18
+ * creating a second one. In the browser the client is started from `onMount`; `start()` is
17
19
  * idempotent, so a client that was already started is left untouched.
18
20
  *
19
- * @param {SetPickedContextParams} params - Either `{ client }` or `{ options, snapshot? }`.
21
+ * @param {SetPickedContextParams} params - `{ client, snapshot? }` or `{ options, snapshot? }`.
20
22
  * @returns {Picked} The client placed into context.
21
23
  * @example
22
24
  * setPickedContext({ options })
23
25
  * @example
24
- * setPickedContext({ client: globalClient })
26
+ * setPickedContext({ client: globalClient, snapshot })
25
27
  */
26
28
  export declare function setPickedContext(params: SetPickedContextParams): Picked;
27
29
  export {};
@@ -1 +1 @@
1
- import{CLIENT_CONTEXT_KEY as e}from"../context.js";import{onMount as t,setContext as n}from"svelte";import{createClient as r,supportsWindow as i}from"@picked/client";import{registerProjectConfig as a}from"@picked/client/server";function o(e,t){let n=r(e);if(t){let e=n.session.store.getState().id;a(n,t.projectConfig,{isPreview:!1,sessionId:e}),t.content.forEach(e=>n.registerContent(e)),n.conditionResults.seed(t.conditionResults)}return n}function s(r){let a=`client`in r?r.client:o(r.options,r.snapshot);return n(e,a),t(()=>{i()&&a.start()}),a}export{s as setPickedContext};
1
+ import{CLIENT_CONTEXT_KEY as e}from"../context.js";import{onMount as t,setContext as n}from"svelte";import{createClient as r,supportsWindow as i}from"@picked/client";import{registerProjectConfig as a}from"@picked/client/server";function o(e,t){let n=e.session.store.getState().id;a(e,t.projectConfig,{isPreview:!1,sessionId:n}),t.content.forEach(t=>e.registerContent(t)),e.conditionResults.seed(t.conditionResults)}function s(e,t){let n=r(e);return t&&o(n,t),n}function c(r){let a;return`client`in r?(r.snapshot&&o(r.client,r.snapshot),a=r.client):a=s(r.options,r.snapshot),n(e,a),t(()=>{i()&&a.start()}),a}export{c as setPickedContext};
package/dist/index.d.ts CHANGED
@@ -5,4 +5,4 @@ export { adaptSvelteComponent, isValidAdaptedComponent } from './component';
5
5
  export type { ComponentWithProps } from './component';
6
6
  export { LazyImage } from './components';
7
7
  export { setPickedContext } from './experience/set-picked-context';
8
- export { default as Experience } from './experience/Experience.svelte';
8
+ export { default as ExperienceSlot } from './experience/ExperienceSlot.svelte';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{adaptSvelteComponent as e,isValidAdaptedComponent as t}from"./component.js";import{LazyImage as n}from"./components/index.js";import{setPickedContext as r}from"./experience/set-picked-context.js";import i from"./experience/Experience.svelte";export{i as Experience,n as LazyImage,e as adaptSvelteComponent,t as isValidAdaptedComponent,r as setPickedContext};
1
+ import{adaptSvelteComponent as e,isValidAdaptedComponent as t}from"./component.js";import{LazyImage as n}from"./components/index.js";import{setPickedContext as r}from"./experience/set-picked-context.js";import i from"./experience/ExperienceSlot.svelte";export{i as ExperienceSlot,n as LazyImage,e as adaptSvelteComponent,t as isValidAdaptedComponent,r as setPickedContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picked/svelte",
3
- "version": "0.0.1-dev.1780464669265",
3
+ "version": "0.0.1-dev.1780552550363",
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.1780464669265",
109
+ "@picked/client": "0.0.1-dev.1780552550363",
110
110
  "effector": "^23.3.0",
111
111
  "svelte": "^5.46.4"
112
112
  },