@preprio/toolkit 0.5.0-rc.2 → 0.5.0-rc.3

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.
Files changed (50) hide show
  1. package/README.md +207 -10
  2. package/dist/astro/index.cjs +1174 -1
  3. package/dist/astro/index.d.cts +47 -1
  4. package/dist/astro/index.d.ts +47 -1
  5. package/dist/astro/index.js +1177 -1
  6. package/dist/chunk-42Z2VW7G.js +1161 -0
  7. package/dist/chunk-6WY3MWCX.js +246 -0
  8. package/dist/chunk-MDAV2FLM.js +26 -0
  9. package/dist/{chunk-FLPNN3CV.js → chunk-PP3O7RB4.js} +1370 -623
  10. package/dist/chunk-S3VT4UWM.js +75 -0
  11. package/dist/chunk-SXUDBGLZ.js +184 -0
  12. package/dist/chunk-URXSDJOU.js +356 -0
  13. package/dist/index.cjs +3108 -392
  14. package/dist/index.d.cts +238 -4
  15. package/dist/index.d.ts +238 -4
  16. package/dist/index.js +189 -149
  17. package/dist/live-preview-EADA3ZL4.js +18 -0
  18. package/dist/nextjs/components.cjs +1522 -359
  19. package/dist/nextjs/components.d.cts +1 -1
  20. package/dist/nextjs/components.d.ts +1 -1
  21. package/dist/nextjs/components.js +4 -1
  22. package/dist/nextjs/index.cjs +1065 -6
  23. package/dist/nextjs/index.d.cts +73 -1
  24. package/dist/nextjs/index.d.ts +73 -1
  25. package/dist/nextjs/index.js +1059 -7
  26. package/dist/nextjs/live-action.cjs +285 -0
  27. package/dist/nextjs/live-action.d.cts +12 -0
  28. package/dist/nextjs/live-action.d.ts +12 -0
  29. package/dist/nextjs/live-action.js +68 -0
  30. package/dist/nextjs/live.cjs +1838 -0
  31. package/dist/nextjs/live.d.cts +52 -0
  32. package/dist/nextjs/live.d.ts +52 -0
  33. package/dist/nextjs/live.js +265 -0
  34. package/dist/nuxt/index.cjs +1 -1
  35. package/dist/nuxt/index.js +1 -1
  36. package/dist/nuxt/live-preview-PTEC3GPC.js +1462 -0
  37. package/dist/nuxt/live.cjs +1662 -0
  38. package/dist/nuxt/live.d.cts +43 -0
  39. package/dist/nuxt/live.d.ts +43 -0
  40. package/dist/nuxt/live.js +94 -0
  41. package/dist/{pixel-B3oQNbZ3.d.cts → pixel-CX422dCO.d.cts} +10 -1
  42. package/dist/{pixel-B3oQNbZ3.d.ts → pixel-CX422dCO.d.ts} +10 -1
  43. package/dist/react/components.cjs +1522 -359
  44. package/dist/react/components.d.cts +9 -0
  45. package/dist/react/components.d.ts +9 -0
  46. package/dist/react/components.js +1522 -359
  47. package/dist/sveltekit/index.cjs +1 -1
  48. package/dist/sveltekit/index.js +1 -1
  49. package/package.json +12 -1
  50. package/src/astro/PreprToolbar.astro +7 -1
@@ -0,0 +1,246 @@
1
+ import {
2
+ isAllowedEditorOrigin
3
+ } from "./chunk-URXSDJOU.js";
4
+ import {
5
+ indexSnapshot,
6
+ isLiveFieldChange,
7
+ parseEditTarget,
8
+ parseListEntries,
9
+ patchSnapshot,
10
+ syncListSnapshot
11
+ } from "./chunk-42Z2VW7G.js";
12
+ import {
13
+ createScopedLogger,
14
+ getTrustedParentOrigin,
15
+ sendPreprEvent
16
+ } from "./chunk-S3VT4UWM.js";
17
+
18
+ // src/core/live-preview/bridge-events.ts
19
+ var debug = createScopedLogger("live-preview:bridge");
20
+ function createLiveBridge(store, options = {}) {
21
+ let parentOrigin = null;
22
+ const onMessage = (evt) => {
23
+ const data = evt?.data;
24
+ if (data?.event === "prepr:initVE" && !parentOrigin) {
25
+ if (isAllowedEditorOrigin(evt.origin, options.allowedEditorOrigins?.())) {
26
+ parentOrigin = evt.origin;
27
+ } else {
28
+ debug.warn("ignored live preview handshake from origin", evt.origin);
29
+ }
30
+ return;
31
+ }
32
+ const trusted = parentOrigin ?? getTrustedParentOrigin();
33
+ if (!trusted || evt.origin !== trusted) return;
34
+ if (data?.event === "prepr:fieldChange") {
35
+ if (typeof data.itemId === "string" && typeof data.field === "string" && data.field && isLiveFieldChange(data.field, data.value)) {
36
+ const edit = parseEditTarget(data.edit);
37
+ if (edit) store.pushPatch(data.itemId, data.field, data.value, edit);
38
+ else store.pushPatch(data.itemId, data.field, data.value);
39
+ } else {
40
+ debug.log("dropped malformed fieldChange", data);
41
+ }
42
+ return;
43
+ }
44
+ if (data?.event === "prepr:listChange") {
45
+ const list = parseListEntries(data.entries);
46
+ if (typeof data.itemId === "string" && typeof data.field === "string" && data.field && list) {
47
+ store.pushList(data.itemId, data.field, list);
48
+ } else {
49
+ debug.log("dropped malformed listChange", data);
50
+ }
51
+ return;
52
+ }
53
+ if (data?.event === "prepr:itemChanged") {
54
+ if (typeof data.itemId === "string") {
55
+ store.invalidate(data.itemId);
56
+ } else {
57
+ debug.log("dropped malformed itemChanged", data);
58
+ }
59
+ }
60
+ };
61
+ return {
62
+ start() {
63
+ window.addEventListener("message", onMessage);
64
+ sendPreprEvent(
65
+ "live_ready",
66
+ options.strictMode?.() ? { strictMode: true } : void 0,
67
+ { allowUntrustedTarget: true }
68
+ );
69
+ },
70
+ stop() {
71
+ window.removeEventListener("message", onMessage);
72
+ }
73
+ };
74
+ }
75
+
76
+ // src/core/live-preview/live-store.ts
77
+ var debug2 = createScopedLogger("live-preview");
78
+ var INVALIDATE_DEBOUNCE_MS = 150;
79
+ var MAX_LOG_ENTRIES = 500;
80
+ function withPatch(log, patch) {
81
+ let previous = -1;
82
+ for (let i = log.length - 1; i >= 0; i--) {
83
+ const p = log[i];
84
+ if (p.type === patch.type && p.itemId === patch.itemId && p.field === patch.field) {
85
+ previous = i;
86
+ break;
87
+ }
88
+ }
89
+ if (previous === -1) return [...log, patch];
90
+ const since = log.slice(previous + 1);
91
+ const listPrefix = `${patch.field}.`;
92
+ const dependsOnPosition = since.some(
93
+ (p) => p.type === "list" || patch.type === "list" && p.itemId === patch.itemId && p.field.startsWith(listPrefix)
94
+ );
95
+ if (dependsOnPosition) return [...log, patch];
96
+ return [...log.slice(0, previous), ...since, patch];
97
+ }
98
+ function createLiveStore(options = {}) {
99
+ const accepts = (patch) => options.accept ? options.accept(patch) : true;
100
+ const entries = /* @__PURE__ */ new Set();
101
+ const invalidateListeners = /* @__PURE__ */ new Set();
102
+ const pendingInvalidates = /* @__PURE__ */ new Map();
103
+ let defaultFetcher = null;
104
+ let log = [];
105
+ const logListeners = /* @__PURE__ */ new Set();
106
+ function record(patch) {
107
+ log = withPatch(log, patch).slice(-MAX_LOG_ENTRIES);
108
+ logListeners.forEach((fn) => fn(log));
109
+ }
110
+ function notify(entry) {
111
+ entry.listeners.forEach((fn) => fn());
112
+ }
113
+ async function refetch(entry) {
114
+ const fetcher = entry.opts.fetcher ?? defaultFetcher;
115
+ if (!fetcher || entry.opts.query == null) return;
116
+ const token = ++entry.fetchToken;
117
+ try {
118
+ const result = await fetcher(entry.opts.query, entry.opts.variables);
119
+ if (token !== entry.fetchToken || !entries.has(entry)) return;
120
+ entry.snapshot = result;
121
+ entry.index = indexSnapshot(result);
122
+ notify(entry);
123
+ } catch (error) {
124
+ debug2.log("refetch failed, keeping previous snapshot", error);
125
+ }
126
+ }
127
+ function runInvalidate(itemId) {
128
+ pendingInvalidates.delete(itemId);
129
+ invalidateListeners.forEach((fn) => fn(itemId));
130
+ for (const entry of entries) {
131
+ if (entry.index.has(itemId)) void refetch(entry);
132
+ }
133
+ }
134
+ return {
135
+ register(data, opts = {}) {
136
+ const entry = {
137
+ snapshot: data,
138
+ index: indexSnapshot(data),
139
+ opts,
140
+ listeners: /* @__PURE__ */ new Set(),
141
+ fetchToken: 0
142
+ };
143
+ for (const patch of log) {
144
+ if (patch.type === "field") {
145
+ entry.snapshot = patchSnapshot(
146
+ entry.snapshot,
147
+ entry.index,
148
+ patch.itemId,
149
+ patch.field,
150
+ patch.value
151
+ );
152
+ } else {
153
+ const next = syncListSnapshot(
154
+ entry.snapshot,
155
+ entry.index,
156
+ patch.itemId,
157
+ patch.field,
158
+ patch.entries
159
+ );
160
+ if (next !== entry.snapshot) {
161
+ entry.snapshot = next;
162
+ entry.index = indexSnapshot(next);
163
+ }
164
+ }
165
+ }
166
+ entries.add(entry);
167
+ return {
168
+ getSnapshot: () => entry.snapshot,
169
+ subscribe(fn) {
170
+ entry.listeners.add(fn);
171
+ return () => entry.listeners.delete(fn);
172
+ },
173
+ unregister() {
174
+ entry.listeners.clear();
175
+ entries.delete(entry);
176
+ }
177
+ };
178
+ },
179
+ pushPatch(itemId, field, value, edit) {
180
+ const patch = edit ? { type: "field", itemId, field, value, edit } : { type: "field", itemId, field, value };
181
+ if (!accepts(patch)) return;
182
+ record(patch);
183
+ for (const entry of entries) {
184
+ const next = patchSnapshot(
185
+ entry.snapshot,
186
+ entry.index,
187
+ itemId,
188
+ field,
189
+ value
190
+ );
191
+ if (next !== entry.snapshot) {
192
+ entry.snapshot = next;
193
+ notify(entry);
194
+ }
195
+ }
196
+ },
197
+ pushList(itemId, field, list) {
198
+ const patch = { type: "list", itemId, field, entries: list };
199
+ if (!accepts(patch)) return;
200
+ record(patch);
201
+ for (const entry of entries) {
202
+ const next = syncListSnapshot(
203
+ entry.snapshot,
204
+ entry.index,
205
+ itemId,
206
+ field,
207
+ list
208
+ );
209
+ if (next !== entry.snapshot) {
210
+ entry.snapshot = next;
211
+ entry.index = indexSnapshot(next);
212
+ notify(entry);
213
+ }
214
+ }
215
+ },
216
+ invalidate(itemId) {
217
+ if (log.length) {
218
+ log = [];
219
+ logListeners.forEach((fn) => fn(log));
220
+ }
221
+ const pending = pendingInvalidates.get(itemId);
222
+ if (pending) clearTimeout(pending);
223
+ pendingInvalidates.set(
224
+ itemId,
225
+ setTimeout(() => runInvalidate(itemId), INVALIDATE_DEBOUNCE_MS)
226
+ );
227
+ },
228
+ setFetcher(fetcher) {
229
+ defaultFetcher = fetcher;
230
+ },
231
+ onInvalidate(fn) {
232
+ invalidateListeners.add(fn);
233
+ return () => invalidateListeners.delete(fn);
234
+ },
235
+ getLog: () => log,
236
+ onLogChange(fn) {
237
+ logListeners.add(fn);
238
+ return () => logListeners.delete(fn);
239
+ }
240
+ };
241
+ }
242
+
243
+ export {
244
+ createLiveBridge,
245
+ createLiveStore
246
+ };
@@ -0,0 +1,26 @@
1
+ // src/version.ts
2
+ var VERSION = "0.5.0-rc.3";
3
+
4
+ // src/core/features.ts
5
+ function isEnabled(config) {
6
+ if (typeof config === "boolean") return config;
7
+ return config?.enabled ?? true;
8
+ }
9
+ function resolveFeatures(features) {
10
+ return {
11
+ segments: isEnabled(features?.segments),
12
+ abTesting: isEnabled(features?.abTesting),
13
+ editMode: isEnabled(features?.editMode)
14
+ };
15
+ }
16
+ var ALL_FEATURES_ENABLED = Object.freeze({
17
+ segments: true,
18
+ abTesting: true,
19
+ editMode: true
20
+ });
21
+
22
+ export {
23
+ VERSION,
24
+ resolveFeatures,
25
+ ALL_FEATURES_ENABLED
26
+ };