@tailorkit/react 0.1.0-beta.3 → 0.1.0-beta.32

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/LICENSE.md +74 -0
  2. package/README.md +3 -0
  3. package/dist/components/context.d.ts +7 -10
  4. package/dist/components/index.d.ts +1 -2
  5. package/dist/components/render-slot.d.ts +9 -0
  6. package/dist/hooks/use-apps.d.ts +6 -13
  7. package/dist/hooks/use-query-result.d.ts +9 -0
  8. package/dist/hooks/use-view-context.d.ts +6 -0
  9. package/dist/hooks/use-views.d.ts +7 -0
  10. package/dist/index.d.ts +7 -3
  11. package/dist/index.js +362 -839
  12. package/dist/primitives.d.ts +11 -21
  13. package/dist/remote-view.d.ts +12 -6
  14. package/dist/tailorkit.d.ts +45 -0
  15. package/package.json +42 -24
  16. package/LICENSE +0 -674
  17. package/dist/components/context.d.ts.map +0 -1
  18. package/dist/components/index.d.ts.map +0 -1
  19. package/dist/components/render.d.ts +0 -20
  20. package/dist/components/render.d.ts.map +0 -1
  21. package/dist/components/root.d.ts +0 -11
  22. package/dist/components/root.d.ts.map +0 -1
  23. package/dist/hooks/use-apps.d.ts.map +0 -1
  24. package/dist/hooks/use-current-screen.d.ts +0 -24
  25. package/dist/hooks/use-current-screen.d.ts.map +0 -1
  26. package/dist/index.d.ts.map +0 -1
  27. package/dist/node-store.d.ts +0 -17
  28. package/dist/node-store.d.ts.map +0 -1
  29. package/dist/primitives.d.ts.map +0 -1
  30. package/dist/remote-context.d.ts +0 -9
  31. package/dist/remote-context.d.ts.map +0 -1
  32. package/dist/remote-view.d.ts.map +0 -1
  33. package/dist/tailor-kit.d.ts +0 -117
  34. package/dist/tailor-kit.d.ts.map +0 -1
  35. package/src/__tests__/node-store.test.ts +0 -206
  36. package/src/__tests__/primitives.test.tsx +0 -85
  37. package/src/__tests__/tailor-kit.test.tsx +0 -424
  38. package/src/__tests__/tailor-kit.types.tsx +0 -151
  39. package/src/components/context.ts +0 -21
  40. package/src/components/index.ts +0 -1
  41. package/src/components/render.tsx +0 -116
  42. package/src/components/root.tsx +0 -37
  43. package/src/hooks/use-apps.ts +0 -47
  44. package/src/hooks/use-current-screen.ts +0 -81
  45. package/src/index.ts +0 -8
  46. package/src/node-store.ts +0 -131
  47. package/src/primitives.tsx +0 -261
  48. package/src/remote-context.ts +0 -11
  49. package/src/remote-view.tsx +0 -232
  50. package/src/tailor-kit.tsx +0 -501
package/dist/index.js CHANGED
@@ -1,342 +1,16 @@
1
- // src/tailor-kit.tsx
2
- import { useEffect as useEffect4, useId as useId2, useMemo as useMemo6, useSyncExternalStore as useSyncExternalStore3 } from "react";
3
-
4
- // src/components/root.tsx
5
- import { useMemo as useMemo2 } from "react";
6
-
7
- // src/components/render.tsx
8
- import { cloneElement, createElement, isValidElement, useMemo } from "react";
9
- function useRender({
10
- defaultTagName,
11
- props,
12
- render
13
- }) {
14
- return useMemo(() => {
15
- if (render) {
16
- if (!isValidElement(render)) {
17
- throw new Error("The render prop must be a valid React element.");
18
- }
19
- return cloneElement(render, mergeProps(render.props, props));
20
- }
21
- return createElement(defaultTagName, props);
22
- }, [defaultTagName, props, render]);
23
- }
24
- function mergeProps(...propSets) {
25
- const merged = {};
26
- for (const props of propSets) {
27
- if (!props) {
28
- continue;
29
- }
30
- for (const [key, value] of Object.entries(props)) {
31
- if (value === void 0) {
32
- continue;
33
- }
34
- const existing = merged[key];
35
- if (key === "className" && existing && value) {
36
- merged[key] = `${existing} ${value}`;
37
- continue;
38
- }
39
- if (key === "style" && existing && value) {
40
- merged[key] = {
41
- ...existing,
42
- ...value
43
- };
44
- continue;
45
- }
46
- if (key === "ref" && existing && value) {
47
- merged[key] = composeRefs(existing, value);
48
- continue;
49
- }
50
- if (isEventHandler(key) && typeof existing === "function" && typeof value === "function") {
51
- merged[key] = (...args) => {
52
- existing(...args);
53
- const event = args[0];
54
- if (!event?.defaultPrevented) {
55
- value(...args);
56
- }
57
- };
58
- continue;
59
- }
60
- merged[key] = value;
61
- }
62
- }
63
- return merged;
64
- }
65
- function composeRefs(...refs) {
66
- return (node) => {
67
- for (const ref of refs) {
68
- if (typeof ref === "function") {
69
- ref(node);
70
- } else if (ref) {
71
- ref.current = node;
72
- }
73
- }
74
- };
75
- }
76
- function isEventHandler(key) {
77
- return /^on[A-Z]/u.test(key);
78
- }
79
-
80
- // src/components/context.ts
81
- import { createContext, useContext } from "react";
82
- var TailorRootContext = createContext(null);
83
- function useTailorRootContext(component) {
84
- const context = useContext(TailorRootContext);
85
- if (!context) {
86
- throw new Error(`${component} must be rendered inside tailor.Root.`);
87
- }
88
- return context;
89
- }
90
-
91
- // src/components/root.tsx
92
- import { jsx } from "react/jsx-runtime";
93
- var EMPTY_APPS = [];
94
- function Root({ apps: appsProp, children, render, tailor, ...props }) {
95
- const appsResult = tailor.useApps();
96
- const apps = appsProp ?? appsResult.data ?? EMPTY_APPS;
97
- const context = useMemo2(
98
- () => ({
99
- apps
100
- }),
101
- [apps]
102
- );
103
- const element = render ? useRender({
104
- defaultTagName: "div",
105
- props: mergeProps({ children }, props),
106
- render
107
- }) : children;
108
- return /* @__PURE__ */ jsx(TailorRootContext.Provider, { value: context, children: element });
109
- }
110
-
111
- // src/hooks/use-apps.ts
112
- import { useCallback, useEffect, useSyncExternalStore } from "react";
113
- function createUseApps(store) {
114
- return function useApps() {
115
- const snapshot = useSyncExternalStore(
116
- store.subscribe,
117
- store.getAppsSnapshot,
118
- store.getAppsSnapshot
119
- );
120
- useEffect(() => {
121
- void store.fetchApps();
122
- }, []);
123
- const refetch = useCallback(() => store.fetchApps({ force: true }), []);
124
- return toUseAppsResult(snapshot, refetch);
125
- };
126
- }
127
- function toUseAppsResult(snapshot, refetch) {
128
- return {
129
- data: snapshot.status === "ready" ? snapshot.apps : void 0,
130
- error: snapshot.error,
131
- isError: snapshot.status === "error",
132
- isLoading: snapshot.status === "loading",
133
- isPending: snapshot.status === "idle" || snapshot.status === "loading",
134
- isSuccess: snapshot.status === "ready",
135
- refetch,
136
- status: snapshot.status
137
- };
138
- }
139
-
140
- // src/hooks/use-current-screen.ts
141
- import { useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
142
- function createUseCurrentScreen(store) {
143
- return function useCurrentScreen(options) {
144
- useTailorRootContext("tailor.useCurrentScreen");
145
- const id = useMemo3(() => /* @__PURE__ */ Symbol("tailorkit-current-screen"), []);
146
- const status = options.status ?? "ready";
147
- const context = "context" in options ? options.context : void 0;
148
- const contextKey = JSON.stringify(context);
149
- const contextRef = useRef({ key: contextKey, value: context });
150
- if (contextRef.current.key !== contextKey) {
151
- contextRef.current = { key: contextKey, value: context };
152
- }
153
- const contextSnapshot = contextRef.current.value;
154
- useEffect2(
155
- () => () => {
156
- store.unregisterScreen(id);
157
- },
158
- [id]
159
- );
160
- useEffect2(() => {
161
- store.registerScreen({
162
- context: contextSnapshot,
163
- id,
164
- screen: options.screen,
165
- status
166
- });
167
- }, [contextSnapshot, id, options.screen, status]);
168
- };
169
- }
1
+ // src/components/render-slot.tsx
2
+ import { useStore as useStore2 } from "@nanostores/react";
3
+ import { createSlotRuntime, buildThemeCss } from "@tailorkit/client-core";
4
+ import { useEffect as useEffect2, useId as useId2, useMemo as useMemo3, useState as useState2 } from "react";
170
5
 
171
6
  // src/primitives.tsx
172
- import { createContext as createContext2, useContext as useContext2, useId, useMemo as useMemo4 } from "react";
173
- import { resolveTheme } from "@tailorkit/core/primitives/theme";
174
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
175
- var PrimitiveThemeContext = createContext2(null);
176
- var tokenGroups = [
177
- "space",
178
- "radius",
179
- "background",
180
- "border",
181
- "borderColor",
182
- "textColor"
183
- ];
184
- var cssEscape = (value) => {
185
- const css = globalThis.CSS;
186
- if (typeof css?.escape === "function") {
187
- return css.escape(value);
188
- }
189
- return value.replaceAll(/[^A-Za-z0-9_-]/gu, "\\$&");
190
- };
191
- var toCssValue = (group, value) => {
192
- if (typeof value === "number") {
193
- return `${value}px`;
194
- }
195
- if (group === "size" || group === "raw") {
196
- return value;
197
- }
198
- return `var(--tailorkit-${group}-${cssEscape(value)})`;
199
- };
200
- var toResponsiveEntries = (value) => {
201
- if (value === void 0) {
202
- return [];
203
- }
204
- if (!(value && typeof value === "object") || Array.isArray(value)) {
205
- return [["base", value]];
206
- }
207
- return Object.entries(value).filter(
208
- (entry) => entry[1] !== void 0
209
- );
210
- };
211
- var declarationsForProp = (prop, value) => {
212
- if (prop === "columns") {
213
- return [`grid-template-columns: repeat(${String(value)}, minmax(0, 1fr));`];
214
- }
215
- const tokenDeclarations = {
216
- background: ["background", "background"],
217
- border: ["border", "border"],
218
- borderColor: ["borderColor", "border-color"],
219
- textColor: ["textColor", "color"]
220
- };
221
- const tokenDeclaration = tokenDeclarations[prop];
222
- if (tokenDeclaration) {
223
- const [group, property] = tokenDeclaration;
224
- if (prop === "border") {
225
- return [`border-style: ${toCssValue(group, value)};`, "border-width: 1px;"];
226
- }
227
- return [`${property}: ${toCssValue(group, value)};`];
228
- }
229
- if (prop === "gap" || prop === "margin" || prop === "padding") {
230
- return [`${prop}: ${toCssValue("space", value)};`];
231
- }
232
- if (prop === "height" || prop === "width") {
233
- return [`${prop}: ${toCssValue("size", value)};`];
234
- }
235
- if (prop === "radius") {
236
- return [`border-radius: ${toCssValue("radius", value)};`];
237
- }
238
- if (prop === "align") {
239
- return [`align-items: ${toFlexAlignment(value)};`];
240
- }
241
- if (prop === "justify") {
242
- return [`justify-content: ${toFlexJustification(value)};`];
243
- }
244
- if (prop === "direction") {
245
- return [`flex-direction: ${toCssValue("raw", value)};`];
246
- }
247
- if (prop === "overflow") {
248
- return [`overflow: ${toCssValue("raw", value)};`];
249
- }
250
- if (prop === "grow") {
251
- return [`flex-grow: ${String(value)};`];
252
- }
253
- if (prop === "shrink") {
254
- return [`flex-shrink: ${String(value)};`];
255
- }
256
- if (prop === "minHeight") {
257
- return [`min-height: ${toCssValue("size", value)};`];
258
- }
259
- if (prop === "minWidth") {
260
- return [`min-width: ${toCssValue("size", value)};`];
261
- }
262
- if (prop === "basis") {
263
- return [`flex-basis: ${toCssValue("size", value)};`];
264
- }
265
- if (prop === "wrap") {
266
- return [`flex-wrap: ${toCssValue("raw", value)};`];
267
- }
268
- return [];
269
- };
270
- var toFlexAlignment = (value) => {
271
- if (value === "start") {
272
- return "flex-start";
273
- }
274
- if (value === "end") {
275
- return "flex-end";
276
- }
277
- return String(value);
278
- };
279
- var toFlexJustification = (value) => {
280
- if (value === "start") {
281
- return "flex-start";
282
- }
283
- if (value === "end") {
284
- return "flex-end";
285
- }
286
- if (value === "between") {
287
- return "space-between";
288
- }
289
- return String(value);
290
- };
291
- var buildPrimitiveCss = ({
292
- display,
293
- nodeId,
294
- props,
295
- screenId,
296
- theme
297
- }) => {
298
- const selector = `[data-tailorkit-screen="${cssEscape(screenId)}"] [data-tailorkit-node="${cssEscape(
299
- nodeId
300
- )}"]`;
301
- const base = [`display: ${display};`];
302
- const byBreakpoint = /* @__PURE__ */ new Map();
303
- for (const [prop, rawValue] of Object.entries(props)) {
304
- for (const [breakpoint, value] of toResponsiveEntries(rawValue)) {
305
- const declarations = declarationsForProp(prop, value);
306
- if (declarations.length === 0) {
307
- continue;
308
- }
309
- const target = breakpoint === "base" ? base : byBreakpoint.get(breakpoint) ?? [];
310
- target.push(...declarations);
311
- if (breakpoint !== "base") {
312
- byBreakpoint.set(breakpoint, target);
313
- }
314
- }
315
- }
316
- const rules = [`${selector} { ${base.join(" ")} }`];
317
- for (const [breakpoint, declarations] of byBreakpoint) {
318
- const minWidth = theme.breakpoints?.[breakpoint];
319
- if (!minWidth) {
320
- continue;
321
- }
322
- rules.push(`@media (min-width: ${minWidth}) { ${selector} { ${declarations.join(" ")} } }`);
323
- }
324
- return rules.join("\n");
325
- };
326
- var buildThemeCss = (screenId, theme) => {
327
- const selector = `[data-tailorkit-screen="${cssEscape(screenId)}"]`;
328
- const declarations = [];
329
- const resolvedTheme = resolveTheme(theme);
330
- for (const group of tokenGroups) {
331
- for (const [name, value] of Object.entries(resolvedTheme.tokens?.[group] ?? {})) {
332
- declarations.push(`--tailorkit-${group}-${cssEscape(name)}: ${value};`);
333
- }
334
- }
335
- return `${selector} { ${declarations.join(" ")} }`;
336
- };
7
+ import { buildPrimitiveCss } from "@tailorkit/client-core";
8
+ import { createContext, useContext, useId, useMemo } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var PrimitiveThemeContext = createContext(null);
337
11
  var usePrimitiveNodeId = () => {
338
12
  const id = useId();
339
- return useMemo4(() => `tailorkit-${id.replaceAll(":", "")}`, [id]);
13
+ return useMemo(() => `tailorkit-${id.replaceAll(":", "")}`, [id]);
340
14
  };
341
15
  var Primitive = ({
342
16
  children,
@@ -344,160 +18,65 @@ var Primitive = ({
344
18
  element,
345
19
  props
346
20
  }) => {
347
- const context = useContext2(PrimitiveThemeContext);
21
+ const context = useContext(PrimitiveThemeContext);
348
22
  const nodeId = usePrimitiveNodeId();
349
23
  const Element = element;
350
24
  const css = context ? buildPrimitiveCss({
351
25
  display,
352
26
  nodeId,
353
27
  props,
354
- screenId: context.screenId,
355
- theme: context.theme
28
+ theme: context.theme,
29
+ viewId: context.viewId
356
30
  }) : "";
357
31
  return /* @__PURE__ */ jsxs(Element, { "data-tailorkit-node": nodeId, children: [
358
- css === "" ? null : /* @__PURE__ */ jsx2("style", { "data-tailorkit-node-style": nodeId, children: css }),
32
+ css === "" ? null : /* @__PURE__ */ jsx("style", { "data-tailorkit-node-style": nodeId, children: css }),
359
33
  children
360
34
  ] });
361
35
  };
362
36
  var primitives = {
363
- Box: ({ props, slots }) => /* @__PURE__ */ jsx2(Primitive, { display: "block", element: "div", props, children: slots.default }),
364
- Flex: ({ props, slots }) => /* @__PURE__ */ jsx2(Primitive, { display: "flex", element: "div", props, children: slots.default }),
365
- Grid: ({ props, slots }) => /* @__PURE__ */ jsx2(Primitive, { display: "grid", element: "div", props, children: slots.default }),
366
- Inline: ({ props, slots }) => /* @__PURE__ */ jsx2(Primitive, { display: "inline", element: "span", props, children: slots.default })
37
+ Box: ({
38
+ props,
39
+ children
40
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "block", element: "div", props, children }),
41
+ Flex: ({
42
+ props,
43
+ children
44
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "flex", element: "div", props, children }),
45
+ Grid: ({
46
+ props,
47
+ children
48
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "grid", element: "div", props, children }),
49
+ Inline: ({
50
+ props,
51
+ children
52
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "inline", element: "span", props, children })
367
53
  };
368
54
 
369
55
  // src/remote-view.tsx
56
+ import { useStore } from "@nanostores/react";
57
+ import {
58
+ createRemoteViewStore,
59
+ createRemoteElementProps
60
+ } from "@tailorkit/client-core";
370
61
  import {
371
62
  Component,
372
63
  Fragment,
373
- createElement as createElement2,
64
+ createElement,
65
+ createContext as createContext2,
374
66
  memo,
375
- useCallback as useCallback2,
376
- useContext as useContext3,
377
- useEffect as useEffect3,
378
- useMemo as useMemo5,
379
- useRef as useRef2,
380
- useState,
381
- useSyncExternalStore as useSyncExternalStore2
67
+ useContext as useContext2,
68
+ useEffect,
69
+ useMemo as useMemo2,
70
+ useState
382
71
  } from "react";
383
- import { createIframeUiHost } from "@tailorkit/sandbox/host";
384
-
385
- // src/node-store.ts
386
- var childIds = (children) => children.map((c) => c.id).join(",");
387
- var nodeSignature = (node) => {
388
- if (node.kind === "text") {
389
- return `text:${node.text}`;
390
- }
391
- if (node.kind === "fragment") {
392
- return `frag:${childIds(node.children)}`;
393
- }
394
- const propsStr = JSON.stringify(node.props);
395
- const callbacksStr = (node.callbacks ?? []).map((binding) => `${binding.callback}:${binding.event}`).join(",");
396
- return `elem:${node.type}|${childIds(node.children)}|${propsStr}|${callbacksStr}`;
397
- };
398
- var flattenTree = (node, out) => {
399
- out.set(node.id, node);
400
- if (node.kind === "text") {
401
- return;
402
- }
403
- for (const child of node.children) {
404
- flattenTree(child, out);
405
- }
406
- };
407
- var NodeStore = class {
408
- nodes = /* @__PURE__ */ new Map();
409
- signatures = /* @__PURE__ */ new Map();
410
- nodeListeners = /* @__PURE__ */ new Map();
411
- rootListeners = /* @__PURE__ */ new Set();
412
- rootId = null;
413
- clear() {
414
- const nodeIds = [...this.nodeListeners.keys()];
415
- const hadRoot = this.rootId !== null;
416
- this.nodes = /* @__PURE__ */ new Map();
417
- this.signatures = /* @__PURE__ */ new Map();
418
- this.rootId = null;
419
- for (const id of nodeIds) {
420
- const subs = this.nodeListeners.get(id);
421
- if (subs) {
422
- for (const l of subs) {
423
- l();
424
- }
425
- }
426
- }
427
- if (hadRoot) {
428
- for (const l of this.rootListeners) {
429
- l();
430
- }
431
- }
432
- }
433
- setSnapshot(tree) {
434
- const next = /* @__PURE__ */ new Map();
435
- flattenTree(tree, next);
436
- const changed = /* @__PURE__ */ new Set();
437
- for (const [id, node] of next) {
438
- const sig = nodeSignature(node);
439
- if (this.signatures.get(id) !== sig) {
440
- changed.add(id);
441
- this.signatures.set(id, sig);
442
- }
443
- }
444
- for (const id of this.signatures.keys()) {
445
- if (!next.has(id)) {
446
- this.signatures.delete(id);
447
- }
448
- }
449
- this.nodes = next;
450
- const prevRootId = this.rootId;
451
- this.rootId = tree.id;
452
- for (const id of changed) {
453
- const subs = this.nodeListeners.get(id);
454
- if (subs) {
455
- for (const l of subs) {
456
- l();
457
- }
458
- }
459
- }
460
- if (prevRootId !== this.rootId) {
461
- for (const l of this.rootListeners) {
462
- l();
463
- }
464
- }
465
- }
466
- getRootId() {
467
- return this.rootId;
468
- }
469
- getNode(id) {
470
- return this.nodes.get(id) ?? null;
471
- }
472
- subscribe(id, listener) {
473
- let subs = this.nodeListeners.get(id);
474
- if (!subs) {
475
- subs = /* @__PURE__ */ new Set();
476
- this.nodeListeners.set(id, subs);
477
- }
478
- subs.add(listener);
479
- return () => {
480
- subs.delete(listener);
481
- if (subs.size === 0) {
482
- this.nodeListeners.delete(id);
483
- }
484
- };
485
- }
486
- subscribeRoot(listener) {
487
- this.rootListeners.add(listener);
488
- return () => this.rootListeners.delete(listener);
489
- }
490
- };
491
-
492
- // src/remote-context.ts
493
- import { createContext as createContext3 } from "react";
494
- var RemoteUIContext = createContext3(null);
495
-
496
- // src/remote-view.tsx
497
- import { jsx as jsx3 } from "react/jsx-runtime";
72
+ import { jsx as jsx2 } from "react/jsx-runtime";
73
+ var RemoteUIContext = createContext2(null);
498
74
  var formatError = (error) => error.message;
499
75
  var RemoteErrorBoundary = class extends Component {
500
- state = { error: null };
76
+ constructor(props) {
77
+ super(props);
78
+ this.state = { error: null };
79
+ }
501
80
  static getDerivedStateFromError(error) {
502
81
  return { error };
503
82
  }
@@ -506,415 +85,359 @@ var RemoteErrorBoundary = class extends Component {
506
85
  }
507
86
  render() {
508
87
  if (this.state.error) {
509
- return createElement2("div", null, formatError(this.state.error));
88
+ return createElement("div", null, formatError(this.state.error));
510
89
  }
511
90
  return this.props.children;
512
91
  }
513
92
  };
514
- function RemoteViewHost({
93
+ var RemoteRoot = ({ store }) => {
94
+ const rootId = useStore(store.nodes.root);
95
+ return rootId === null ? null : /* @__PURE__ */ jsx2(RemoteView, { nodeId: rootId });
96
+ };
97
+ var RemoteViewHost = ({
515
98
  appUrl,
99
+ sourceText,
100
+ toolBridge,
101
+ getBackendSession,
516
102
  components: components2,
517
103
  createIframe,
518
- props,
519
- runtimeUrl
520
- }) {
104
+ props
105
+ }) => {
521
106
  const appKey = appUrl.toString();
522
- const storeRef = useRef2(null);
523
- if (storeRef.current === null) {
524
- storeRef.current = new NodeStore();
525
- }
526
- const store = storeRef.current;
527
- const appKeyRef = useRef2(appKey);
528
- if (appKeyRef.current !== appKey) {
529
- appKeyRef.current = appKey;
530
- store.clear();
531
- }
532
- const dispatchRef = useRef2(null);
533
- const [error, setError] = useState(null);
534
- const [status, setStatus] = useState("starting");
535
- const ctxRef = useRef2({
536
- components: components2,
537
- dispatch: (payload) => dispatchRef.current?.(payload),
538
- store
539
- });
540
- useEffect3(() => {
541
- ctxRef.current.components = components2;
542
- }, [components2]);
543
- const ui = useMemo5(() => {
544
- const ctx = ctxRef.current;
545
- return createElement2(
546
- RemoteUIContext.Provider,
547
- { value: ctx },
548
- createElement2(
549
- RemoteErrorBoundary,
550
- { key: appKey },
551
- createElement2(RemoteRoot, { store: ctx.store })
552
- )
553
- );
554
- }, [appKey]);
555
- useEffect3(() => {
556
- const host = createIframeUiHost(appUrl, {
107
+ const [state, setState] = useState(() => ({
108
+ appKey,
109
+ store: createRemoteViewStore({ components: components2, props })
110
+ }));
111
+ if (state.appKey !== appKey) {
112
+ setState({ appKey, store: createRemoteViewStore({ components: components2, props }) });
113
+ }
114
+ const { store } = state;
115
+ const snapshot = useStore(store.state);
116
+ useEffect(() => {
117
+ store.setComponents(components2);
118
+ }, [components2, store]);
119
+ useEffect(() => {
120
+ store.setProps(props);
121
+ }, [props, store]);
122
+ useEffect(
123
+ () => store.mount({
124
+ appUrl,
557
125
  createIframe,
558
- onError: (error2) => {
559
- console.error("TailorKit remote app failed", error2);
560
- setError(error2);
561
- setStatus("error");
562
- },
563
- props,
564
- runtimeUrl
565
- });
566
- dispatchRef.current = (payload) => host.dispatch(payload);
567
- const unsubscribe = host.subscribe(() => {
568
- const tree = host.getSnapshot();
569
- if (tree !== null) {
570
- store.setSnapshot(tree);
571
- setStatus("ready");
572
- }
573
- });
574
- setStatus("starting");
575
- setError(null);
576
- host.mount();
577
- return () => {
578
- unsubscribe();
579
- dispatchRef.current = null;
580
- host.destroy();
581
- };
582
- }, [appUrl, createIframe, props, runtimeUrl, store]);
583
- if (status === "error" && error) {
584
- return createElement2("div", null, formatError(error));
585
- }
586
- return ui;
587
- }
588
- function RemoteRoot({ store }) {
589
- const subscribe = useCallback2((listener) => store.subscribeRoot(listener), [store]);
590
- const getSnapshot = useCallback2(() => store.getRootId(), [store]);
591
- const rootId = useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
592
- if (rootId === null) {
593
- return null;
126
+ getBackendSession,
127
+ sourceText,
128
+ toolBridge
129
+ }),
130
+ [appUrl, sourceText, toolBridge, getBackendSession, createIframe, store]
131
+ );
132
+ if (snapshot.status === "error" && snapshot.error) {
133
+ return createElement("div", null, formatError(snapshot.error));
594
134
  }
595
- return /* @__PURE__ */ jsx3(RemoteView, { nodeId: rootId });
596
- }
597
- var RemoteElementView = memo(({ ctx, node }) => {
598
- const { dispatch, components: components2 } = ctx;
599
- const children = node.children.map((child) => /* @__PURE__ */ jsx3(RemoteView, { nodeId: child.id }, child.id));
600
- const component = components2[node.type];
135
+ return /* @__PURE__ */ jsx2(RemoteUIContext.Provider, { value: store, children: /* @__PURE__ */ jsx2(RemoteErrorBoundary, { children: /* @__PURE__ */ jsx2(RemoteRoot, { store }) }, `${appKey}:${snapshot.generation}`) });
136
+ };
137
+ var RemoteElementViewComponent = ({
138
+ ctx,
139
+ node
140
+ }) => {
141
+ const componentStore = useMemo2(
142
+ () => ctx.selectComponent(node.type),
143
+ [ctx, node.type]
144
+ );
145
+ const component = useStore(componentStore);
146
+ const children = node.children.map((child) => (
147
+ // oxlint-disable-next-line no-use-before-define -- This deferred callback runs after initialization; the definitions are mutually dependent.
148
+ /* @__PURE__ */ jsx2(RemoteView, { nodeId: child.id }, child.id)
149
+ ));
601
150
  if (component === void 0) {
602
151
  throw new Error(`TailorKit component "${node.type}" is not registered.`);
603
152
  }
604
- const props = { ...node.props };
605
- for (const binding of node.callbacks ?? []) {
606
- props[binding.callback] = (...args) => {
607
- dispatch({
608
- data: {
609
- args: args.slice(0, binding.inputCount),
610
- event: binding.event,
611
- nodeId: node.id
612
- },
613
- type: "dispatchCallback"
614
- });
615
- };
616
- }
617
- return createElement2(component, props, ...children);
618
- });
619
- var RemoteView = memo(function RemoteView2({ nodeId }) {
620
- const ctx = useContext3(RemoteUIContext);
621
- if (ctx === null) {
622
- return null;
623
- }
624
- const { store } = ctx;
625
- const subscribe = useCallback2(
626
- (listener) => store.subscribe(nodeId, listener),
627
- [store, nodeId]
153
+ const props = createRemoteElementProps(node, ctx.dispatch.bind(ctx));
154
+ return createElement(
155
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- The renderer was supplied through the typed component registry; React's createElement overload erases its heterogeneous props. */
156
+ component,
157
+ /* oxlint-enable typescript/no-unsafe-type-assertion */
158
+ props,
159
+ ...children
628
160
  );
629
- const getSnapshot = useCallback2(() => store.getNode(nodeId), [store, nodeId]);
630
- const node = useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
161
+ };
162
+ var RemoteElementView = memo(RemoteElementViewComponent);
163
+ var RemoteNodeView = ({
164
+ ctx,
165
+ nodeId
166
+ }) => {
167
+ const nodeStore = useMemo2(() => ctx.nodes.selectNode(nodeId), [ctx, nodeId]);
168
+ const node = useStore(nodeStore);
631
169
  if (node === null) {
632
170
  return null;
633
171
  }
634
172
  if (node.kind === "text") {
635
173
  return node.text;
636
174
  }
637
- const childElements = node.children.map((child) => /* @__PURE__ */ jsx3(RemoteView2, { nodeId: child.id }, child.id));
175
+ const childElements = node.children.map((child) => (
176
+ // oxlint-disable-next-line no-use-before-define -- This deferred callback runs after initialization; the definitions are mutually dependent.
177
+ /* @__PURE__ */ jsx2(RemoteView, { nodeId: child.id }, child.id)
178
+ ));
638
179
  if (node.kind === "fragment") {
639
- return createElement2(Fragment, { key: node.id }, ...childElements);
180
+ return createElement(Fragment, { key: node.id }, ...childElements);
640
181
  }
641
- return /* @__PURE__ */ jsx3(RemoteElementView, { node, ctx });
642
- });
182
+ return /* @__PURE__ */ jsx2(RemoteElementView, { node, ctx });
183
+ };
184
+ var RemoteViewComponent = ({ nodeId }) => {
185
+ const ctx = useContext2(RemoteUIContext);
186
+ return ctx === null ? null : /* @__PURE__ */ jsx2(RemoteNodeView, { ctx, nodeId });
187
+ };
188
+ var RemoteView = memo(RemoteViewComponent);
189
+
190
+ // src/components/context.ts
191
+ import { createContext as createContext3, useContext as useContext3 } from "react";
192
+ var TailorkitContext = createContext3(
193
+ null
194
+ );
195
+ var useTailorkitContext = (component, expectedClient) => {
196
+ const context = useContext3(TailorkitContext);
197
+ if (!context) {
198
+ throw new Error(
199
+ `${component} must be rendered inside a TailorKit Provider.`
200
+ );
201
+ }
202
+ if (expectedClient && context.client !== expectedClient) {
203
+ throw new Error(
204
+ `${component} was created for a different TailorKit client than the surrounding Provider.`
205
+ );
206
+ }
207
+ return context;
208
+ };
209
+
210
+ // src/components/render-slot.tsx
211
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
212
+ var SlotRenderer = (options) => {
213
+ const { store, client } = useTailorkitContext(
214
+ options.mode === "managed" ? "RenderSlot" : "RenderSlot.Controlled"
215
+ );
216
+ const reactId = useId2();
217
+ const [state, setState] = useState2(() => ({
218
+ runtime: createSlotRuntime(store, options),
219
+ store
220
+ }));
221
+ if (state.store !== store) {
222
+ setState({ runtime: createSlotRuntime(store, options), store });
223
+ }
224
+ const { runtime } = state;
225
+ useEffect2(() => {
226
+ runtime.setInput(options);
227
+ }, [runtime, options]);
228
+ const snapshot = useStore2(runtime.state);
229
+ const viewId = `tailorkit-view-${reactId.replaceAll(":", "")}`;
230
+ const themeContext = useMemo3(
231
+ () => ({ theme: client.theme, viewId }),
232
+ [client.theme, viewId]
233
+ );
234
+ if (snapshot.status === "hidden") {
235
+ return null;
236
+ }
237
+ if (snapshot.status === "loading") {
238
+ return /* @__PURE__ */ jsx3("output", { children: snapshot.message });
239
+ }
240
+ if (snapshot.status === "error") {
241
+ return /* @__PURE__ */ jsx3("div", { role: "alert", children: snapshot.error.message });
242
+ }
243
+ return /* @__PURE__ */ jsx3(PrimitiveThemeContext.Provider, { value: themeContext, children: /* @__PURE__ */ jsxs2("div", { "data-tailorkit-view": viewId, children: [
244
+ /* @__PURE__ */ jsx3("style", { "data-tailorkit-theme-style": viewId, children: buildThemeCss(viewId, client.theme) }),
245
+ /* @__PURE__ */ jsx3(
246
+ RemoteViewHost,
247
+ {
248
+ appUrl: snapshot.appUrl,
249
+ sourceText: snapshot.sourceText,
250
+ toolBridge: snapshot.toolBridge,
251
+ getBackendSession: snapshot.getBackendSession,
252
+ components: client.components,
253
+ props: snapshot.props
254
+ },
255
+ snapshot.hostKey
256
+ )
257
+ ] }) });
258
+ };
259
+ var ManagedRenderSlot = (props) => /* @__PURE__ */ jsx3(SlotRenderer, { mode: "managed", ...props });
260
+ var ControlledRenderSlot = (props) => /* @__PURE__ */ jsx3(SlotRenderer, { mode: "controlled", ...props });
261
+ var RenderSlot = Object.assign(
262
+ ManagedRenderSlot,
263
+ {
264
+ Controlled: ControlledRenderSlot
265
+ }
266
+ );
267
+
268
+ // src/tailorkit.tsx
269
+ import {
270
+ createTailorKitClientConfig,
271
+ createComponentRegistry,
272
+ createTailorKitStore
273
+ } from "@tailorkit/client-core";
274
+ import { createElement as createElement2, useEffect as useEffect4, useMemo as useMemo8, useState as useState3 } from "react";
275
+
276
+ // src/hooks/use-apps.ts
277
+ import { createValueMemo, createAppsQuery } from "@tailorkit/client-core";
278
+ import { useMemo as useMemo5 } from "react";
279
+
280
+ // src/hooks/use-query-result.ts
281
+ import { useStore as useStore3 } from "@nanostores/react";
282
+ import { useMemo as useMemo4 } from "react";
283
+ var useQueryResult = (state) => {
284
+ const result = useStore3(state);
285
+ return useMemo4(
286
+ () => ({
287
+ data: result.data,
288
+ error: result.error,
289
+ fetch: result.refetch,
290
+ isPending: result.isPending,
291
+ isRefetching: result.isFetching && !result.isPending
292
+ }),
293
+ [result]
294
+ );
295
+ };
296
+
297
+ // src/hooks/use-apps.ts
298
+ var useAppsStore = (store, options = {}) => {
299
+ const memoOptions = useMemo5(() => createValueMemo(), []);
300
+ const stableOptions = memoOptions({
301
+ appIds: options.appIds === void 0 ? void 0 : [...new Set(options.appIds)].toSorted(),
302
+ scopes: options.scopes === void 0 ? void 0 : [...new Set(options.scopes)].toSorted()
303
+ });
304
+ const query = useMemo5(
305
+ () => createAppsQuery(store, stableOptions),
306
+ [store, stableOptions]
307
+ );
308
+ return useQueryResult(query.state);
309
+ };
310
+ var useApps = (options = {}) => useAppsStore(useTailorkitContext("useApps").store, options);
311
+
312
+ // src/hooks/use-view-context.ts
313
+ import { useEffect as useEffect3, useMemo as useMemo6 } from "react";
314
+ var useViewContext = (view, options) => {
315
+ const { store } = useTailorkitContext("useViewContext");
316
+ const id = useMemo6(() => /* @__PURE__ */ Symbol("tailorkit-current-view"), []);
317
+ const { context, loading, error } = options;
318
+ useEffect3(
319
+ () => () => {
320
+ store.views.unregister(id);
321
+ },
322
+ [id, store]
323
+ );
324
+ useEffect3(() => {
325
+ store.views.register({ context, error, id, loading, view });
326
+ }, [id, view, context, loading, error, store]);
327
+ };
328
+
329
+ // src/hooks/use-views.ts
330
+ import { createValueMemo as createValueMemo2, createViewsQuery } from "@tailorkit/client-core";
331
+ import { useMemo as useMemo7 } from "react";
332
+ var useViews = (options) => {
333
+ const { store } = useTailorkitContext("useViews");
334
+ const memoOptions = useMemo7(() => createValueMemo2(), []);
335
+ const stableOptions = memoOptions({
336
+ appIds: options.appIds === void 0 ? void 0 : [...new Set(options.appIds)].toSorted(),
337
+ scopes: options.scopes === void 0 ? void 0 : [...new Set(options.scopes)].toSorted(),
338
+ slot: options.slot
339
+ });
340
+ const query = useMemo7(
341
+ () => createViewsQuery(store, stableOptions),
342
+ [store, stableOptions]
343
+ );
344
+ return useQueryResult(query.state);
345
+ };
643
346
 
644
- // src/tailor-kit.tsx
645
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
646
- var componentTagPrefix = "tailorkit-";
647
- var toComponentTagName = (name) => `${componentTagPrefix}${name.replaceAll(/([a-z0-9])([A-Z])/gu, "$1-$2").replaceAll(/[\s_]+/gu, "-").toLowerCase()}`;
648
- function components(_schema, customComponents) {
649
- return customComponents;
650
- }
651
- function createTailorKitClient(options) {
652
- return createReactTailorKitClient(options);
653
- }
654
- function createReactTailorKitClient(options) {
655
- const wrappedComponents = {};
656
- const store = createTailorKitStore(options.baseUrl);
657
- const theme = options.theme ?? {};
658
- for (const [name, renderer] of Object.entries(options.components ?? {})) {
659
- if (renderer) {
660
- const TailorKitComponent = function TailorKitComponent2({
347
+ // src/tailorkit.tsx
348
+ var components = (_contract, customComponents) => (
349
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- The wrapper preserves the declared component or slot props and changes only the rendering adapter; the generic key-to-props relationship is erased at this boundary. */
350
+ customComponents
351
+ );
352
+ var createReactTailorKitClient = (options) => {
353
+ const wrappedComponents = createComponentRegistry(
354
+ options.components ?? {},
355
+ (renderer) => (
356
+ // oxlint-disable-next-line typescript/promise-function-async -- Client components must render synchronously; ReactNode also permits Promise results for server components.
357
+ function TailorKitComponent({
661
358
  children,
662
359
  ...props
663
360
  }) {
664
- return renderer({
665
- props,
666
- slots: { default: children }
667
- });
668
- };
669
- wrappedComponents[name] = TailorKitComponent;
670
- wrappedComponents[toComponentTagName(name)] = TailorKitComponent;
671
- }
672
- }
673
- const useApps = createUseApps(store);
674
- const useCurrentScreen = createUseCurrentScreen(store);
675
- const AppView = ({
676
- app,
677
- createIframe,
678
- fallback = null,
679
- runtimeUrl,
680
- ...screenProps
681
- }) => {
682
- const reactId = useId2();
683
- const currentScreen = useSyncExternalStore3(
684
- store.subscribe,
685
- store.getCurrentScreen,
686
- store.getCurrentScreen
687
- );
688
- const screen = screenProps.screen;
689
- const context = screenProps.context;
690
- const status = screenProps.status ?? "ready";
691
- const props = useMemo6(() => {
692
- if (screen !== void 0) {
693
- return {
694
- screen: {
695
- context,
696
- path: screen,
697
- status
698
- }
699
- };
700
- }
701
- return currentScreen === null ? void 0 : {
702
- screen: {
703
- context: currentScreen.context,
704
- path: currentScreen.screen,
705
- status: currentScreen.status
361
+ const rendererArgs = { props };
362
+ if (children !== void 0) {
363
+ rendererArgs.children = children;
706
364
  }
707
- };
708
- }, [context, currentScreen, screen, status]);
709
- const meta = useSyncExternalStore3(
710
- store.subscribe,
711
- store.getMetaSnapshot,
712
- store.getMetaSnapshot
713
- );
714
- const assetsBaseUrl = app.clientPath ? null : meta.assetsBaseUrl;
715
- const appUrl = useMemo6(
716
- () => resolveAppUrl(app, store.baseUrl, assetsBaseUrl),
717
- [app, assetsBaseUrl]
718
- );
719
- useEffect4(() => {
720
- void store.fetchMeta();
721
- }, []);
722
- if (props === void 0 || appUrl === null) {
723
- return fallback;
724
- }
725
- const screenId = `tailorkit-screen-${reactId.replaceAll(":", "")}`;
726
- return /* @__PURE__ */ jsx4(PrimitiveThemeContext.Provider, { value: { screenId, theme }, children: /* @__PURE__ */ jsxs2("div", { "data-tailorkit-screen": screenId, children: [
727
- /* @__PURE__ */ jsx4("style", { "data-tailorkit-theme-style": screenId, children: buildThemeCss(screenId, theme) }),
728
- /* @__PURE__ */ jsx4(
729
- RemoteViewHost,
730
- {
731
- appUrl,
732
- components: wrappedComponents,
733
- createIframe,
734
- props,
735
- runtimeUrl
736
- }
737
- )
738
- ] }) });
739
- };
740
- const client = {
741
- AppView,
742
- Root: (props) => /* @__PURE__ */ jsx4(Root, { ...props, tailor: client }),
743
- getApp: store.getApp,
744
- getApps: store.getApps,
745
- useApps,
746
- useCurrentScreen
747
- };
748
- return {
749
- ...client
750
- };
751
- }
752
- function createTailorKitStore(baseUrlInput) {
753
- const baseUrl = toBaseUrl(baseUrlInput);
754
- const listeners = /* @__PURE__ */ new Set();
755
- const screens = /* @__PURE__ */ new Map();
756
- let appsSnapshot = {
757
- apps: [],
758
- error: null,
759
- status: "idle"
760
- };
761
- let metaSnapshot = {
762
- assetsBaseUrl: null,
763
- error: null,
764
- schema: null,
765
- status: "idle"
766
- };
767
- let currentScreen = null;
768
- let fetchAppsPromise = null;
769
- let fetchMetaPromise = null;
770
- let fetchAppsRequestId = 0;
771
- let nextOrder = 0;
772
- const emit = () => {
773
- for (const listener of listeners) {
774
- listener();
775
- }
776
- };
777
- const selectCurrentScreen = () => {
778
- let selected = null;
779
- for (const screen of screens.values()) {
780
- const depth = getScreenDepth(screen.screen);
781
- const selectedDepth = selected === null ? -1 : getScreenDepth(selected.screen);
782
- if (selected === null || depth > selectedDepth) {
783
- selected = screen;
365
+ return renderer(
366
+ rendererArgs
367
+ );
784
368
  }
785
- if (selected !== null && depth === selectedDepth && screen.order > selected.order) {
786
- selected = screen;
787
- }
788
- }
789
- const deepestScreens = selected === null ? [] : [...screens.values()].filter(
790
- (screen) => getScreenDepth(screen.screen) === getScreenDepth(selected.screen)
791
- );
792
- if (typeof console !== "undefined" && selected !== null && deepestScreens.length > 1) {
793
- const screenNames = deepestScreens.map((screen) => `"${screen.screen}"`).join(", ");
794
- console.warn(
795
- `TailorKit found multiple active screens at the same hierarchy depth: ${screenNames}. TailorKit selected "${selected.screen}" by mount order. Only one route at a hierarchy depth should call useCurrentScreen.`
796
- );
797
- }
798
- currentScreen = selected;
369
+ )
370
+ );
371
+ const clientConfig = createTailorKitClientConfig({
372
+ ...options,
373
+ components: wrappedComponents
374
+ });
375
+ const ClientRenderSlot = (props) => {
376
+ useTailorkitContext("RenderSlot", client);
377
+ return createElement2(RenderSlot, props);
799
378
  };
800
- return {
801
- baseUrl,
802
- fetchApps: (options = {}) => {
803
- if (fetchAppsPromise && !options.force) {
804
- return fetchAppsPromise;
805
- }
806
- appsSnapshot = { ...appsSnapshot, status: "loading" };
807
- emit();
808
- const requestId = ++fetchAppsRequestId;
809
- fetchAppsPromise = fetch(new URL("apps", baseUrl)).then(async (response) => {
810
- if (!response.ok) {
811
- throw new Error(`Unable to fetch TailorKit apps from ${baseUrl.toString()}.`);
812
- }
813
- const apps = await response.json();
814
- if (requestId !== fetchAppsRequestId) {
815
- return;
816
- }
817
- appsSnapshot = {
379
+ const client = {
380
+ ...clientConfig,
381
+ Provider: function Provider({ children, apps }) {
382
+ const [store] = useState3(
383
+ () => createTailorKitStore({
818
384
  apps,
819
- error: null,
820
- status: "ready"
821
- };
822
- emit();
823
- }).catch((error) => {
824
- if (requestId !== fetchAppsRequestId) {
825
- return;
826
- }
827
- appsSnapshot = {
828
- ...appsSnapshot,
829
- error: error instanceof Error ? error : new Error(String(error)),
830
- status: "error"
831
- };
832
- emit();
833
- });
834
- return fetchAppsPromise;
835
- },
836
- fetchMeta: () => {
837
- if (fetchMetaPromise) {
838
- return fetchMetaPromise;
839
- }
840
- metaSnapshot = { ...metaSnapshot, status: "loading" };
841
- emit();
842
- fetchMetaPromise = fetch(new URL("meta", baseUrl)).then(async (response) => {
843
- if (!response.ok) {
844
- throw new Error(`Unable to fetch TailorKit metadata from ${baseUrl.toString()}.`);
845
- }
846
- const meta = await response.json();
847
- metaSnapshot = {
848
- assetsBaseUrl: meta.assetsBaseUrl ?? null,
849
- error: null,
850
- schema: meta.schema,
851
- status: "ready"
852
- };
853
- emit();
854
- }).catch((error) => {
855
- metaSnapshot = {
856
- ...metaSnapshot,
857
- error: error instanceof Error ? error : new Error(String(error)),
858
- status: "error"
859
- };
860
- emit();
861
- });
862
- return fetchMetaPromise;
385
+ assetsBaseUrl: client.assetsBaseUrl,
386
+ baseUrl: client.baseUrl,
387
+ client: clientConfig.fetchClient,
388
+ contract: client.contract,
389
+ tools: client.tools
390
+ })
391
+ );
392
+ useEffect4(() => {
393
+ store.setProvidedApps(apps);
394
+ }, [store, apps]);
395
+ useEffect4(
396
+ () => () => {
397
+ store.previews.dispose();
398
+ },
399
+ [store]
400
+ );
401
+ const context = useMemo8(() => ({ client, store }), [store]);
402
+ return createElement2(
403
+ TailorkitContext.Provider,
404
+ { value: context },
405
+ children
406
+ );
863
407
  },
864
- getApp: (id) => appsSnapshot.apps.find((app) => app.id === id),
865
- getApps: () => appsSnapshot.apps,
866
- getAppsSnapshot: () => appsSnapshot,
867
- getCurrentScreen: () => currentScreen,
868
- getMetaSnapshot: () => metaSnapshot,
869
- registerScreen: (entry) => {
870
- const existing = screens.get(entry.id);
871
- screens.set(entry.id, {
872
- ...entry,
873
- order: existing?.order ?? nextOrder
874
- });
875
- if (!existing) {
876
- nextOrder += 1;
408
+ RenderSlot: Object.assign(ClientRenderSlot, {
409
+ Controlled: function Controlled(props) {
410
+ useTailorkitContext("RenderSlot.Controlled", client);
411
+ return createElement2(
412
+ RenderSlot.Controlled,
413
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- The wrapper preserves the declared component or slot props and changes only the rendering adapter; the generic key-to-props relationship is erased at this boundary. */
414
+ props
415
+ /* oxlint-enable typescript/no-unsafe-type-assertion */
416
+ );
877
417
  }
878
- selectCurrentScreen();
879
- emit();
418
+ }),
419
+ useApps: function useApps2(optionsValue) {
420
+ useTailorkitContext("useApps", client);
421
+ return useApps(optionsValue);
880
422
  },
881
- subscribe: (listener) => {
882
- listeners.add(listener);
883
- return () => {
884
- listeners.delete(listener);
885
- };
423
+ useViewContext: function useViewContext2(view, optionsValue2) {
424
+ useTailorkitContext("useViewContext", client);
425
+ useViewContext(view, optionsValue2);
886
426
  },
887
- unregisterScreen: (id) => {
888
- screens.delete(id);
889
- selectCurrentScreen();
890
- emit();
427
+ useViews: function useViews2(optionsValue3) {
428
+ useTailorkitContext("useViews", client);
429
+ return (
430
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- The wrapper preserves the declared component or slot props and changes only the rendering adapter; the generic key-to-props relationship is erased at this boundary. */
431
+ useViews(optionsValue3)
432
+ );
891
433
  }
892
434
  };
893
- }
894
- function getScreenDepth(screen) {
895
- return screen === "/" ? 0 : screen.split("/").filter(Boolean).length;
896
- }
897
- function resolveAppUrl(app, baseUrl, assetsBaseUrl) {
898
- if (app.clientPath) {
899
- return new URL(app.clientPath, baseUrl);
900
- }
901
- if (!assetsBaseUrl || !app.projectId || !app.currentDeployment?.id) {
902
- return null;
903
- }
904
- return new URL(
905
- `projects/${app.projectId}/apps/${app.id}/deployments/${app.currentDeployment.id}/files/client.js`,
906
- toBaseUrl(assetsBaseUrl)
907
- );
908
- }
909
- function toBaseUrl(value) {
910
- const url = value instanceof URL ? new URL(value) : new URL(value);
911
- if (!url.pathname.endsWith("/")) {
912
- url.pathname = `${url.pathname}/`;
913
- }
914
- return url;
915
- }
435
+ return client;
436
+ };
437
+ var createClient = (options) => createReactTailorKitClient(options);
916
438
  export {
439
+ RenderSlot,
917
440
  components,
918
- createTailorKitClient,
441
+ createClient,
919
442
  primitives
920
443
  };