@tailorkit/react 0.1.0-beta.4 → 0.1.0-beta.40

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.
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 { Fragment, 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,113 @@ 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
  };
36
+ var isStringValue = (value) => typeof value === "string";
37
+ var isPressCallback = (value) => typeof value === "function";
38
+ var Pressable = ({
39
+ props,
40
+ children
41
+ }) => {
42
+ const context = useContext(PrimitiveThemeContext);
43
+ const nodeId = usePrimitiveNodeId();
44
+ const displays = {
45
+ box: "block",
46
+ flex: "flex",
47
+ grid: "grid",
48
+ inline: "inline-flex"
49
+ };
50
+ const { ariaLabel, layout, onPress } = props;
51
+ const display = layout === "box" || layout === "flex" || layout === "grid" ? displays[layout] : displays.inline;
52
+ const disabled = props.disabled === true;
53
+ const css = context ? buildPrimitiveCss({
54
+ display,
55
+ nodeId,
56
+ pressable: true,
57
+ props,
58
+ theme: context.theme,
59
+ viewId: context.viewId
60
+ }) : "";
61
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
62
+ css === "" ? null : /* @__PURE__ */ jsx("style", { "data-tailorkit-node-style": nodeId, children: css }),
63
+ /* @__PURE__ */ jsx(
64
+ "button",
65
+ {
66
+ "aria-label": isStringValue(ariaLabel) ? ariaLabel : void 0,
67
+ "data-tailorkit-node": nodeId,
68
+ disabled,
69
+ onClick: () => {
70
+ if (!disabled && isPressCallback(onPress)) {
71
+ onPress();
72
+ }
73
+ },
74
+ type: "button",
75
+ children
76
+ }
77
+ )
78
+ ] });
79
+ };
362
80
  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 })
81
+ Box: ({
82
+ props,
83
+ children
84
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "block", element: "div", props, children }),
85
+ Flex: ({
86
+ props,
87
+ children
88
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "flex", element: "div", props, children }),
89
+ Grid: ({
90
+ props,
91
+ children
92
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "grid", element: "div", props, children }),
93
+ Inline: ({
94
+ props,
95
+ children
96
+ }) => /* @__PURE__ */ jsx(Primitive, { display: "inline", element: "span", props, children }),
97
+ Pressable: ({
98
+ props,
99
+ children
100
+ }) => /* @__PURE__ */ jsx(Pressable, { props, children })
367
101
  };
368
102
 
369
103
  // src/remote-view.tsx
104
+ import { useStore } from "@nanostores/react";
105
+ import {
106
+ createRemoteViewStore,
107
+ createRemoteElementProps
108
+ } from "@tailorkit/client-core";
370
109
  import {
371
110
  Component,
372
- Fragment,
373
- createElement as createElement2,
111
+ Fragment as Fragment2,
112
+ createElement,
113
+ createContext as createContext2,
374
114
  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
115
+ useContext as useContext2,
116
+ useEffect,
117
+ useMemo as useMemo2,
118
+ useState
382
119
  } 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";
120
+ import { jsx as jsx2 } from "react/jsx-runtime";
121
+ var RemoteUIContext = createContext2(null);
498
122
  var formatError = (error) => error.message;
499
123
  var RemoteErrorBoundary = class extends Component {
500
- state = { error: null };
124
+ constructor(props) {
125
+ super(props);
126
+ this.state = { error: null };
127
+ }
501
128
  static getDerivedStateFromError(error) {
502
129
  return { error };
503
130
  }
@@ -506,415 +133,359 @@ var RemoteErrorBoundary = class extends Component {
506
133
  }
507
134
  render() {
508
135
  if (this.state.error) {
509
- return createElement2("div", null, formatError(this.state.error));
136
+ return createElement("div", null, formatError(this.state.error));
510
137
  }
511
138
  return this.props.children;
512
139
  }
513
140
  };
514
- function RemoteViewHost({
141
+ var RemoteRoot = ({ store }) => {
142
+ const rootId = useStore(store.nodes.root);
143
+ return rootId === null ? null : /* @__PURE__ */ jsx2(RemoteView, { nodeId: rootId });
144
+ };
145
+ var RemoteViewHost = ({
515
146
  appUrl,
147
+ sourceText,
148
+ toolBridge,
149
+ getBackendSession,
516
150
  components: components2,
517
151
  createIframe,
518
- props,
519
- runtimeUrl
520
- }) {
152
+ props
153
+ }) => {
521
154
  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, {
155
+ const [state, setState] = useState(() => ({
156
+ appKey,
157
+ store: createRemoteViewStore({ components: components2, props })
158
+ }));
159
+ if (state.appKey !== appKey) {
160
+ setState({ appKey, store: createRemoteViewStore({ components: components2, props }) });
161
+ }
162
+ const { store } = state;
163
+ const snapshot = useStore(store.state);
164
+ useEffect(() => {
165
+ store.setComponents(components2);
166
+ }, [components2, store]);
167
+ useEffect(() => {
168
+ store.setProps(props);
169
+ }, [props, store]);
170
+ useEffect(
171
+ () => store.mount({
172
+ appUrl,
557
173
  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;
174
+ getBackendSession,
175
+ sourceText,
176
+ toolBridge
177
+ }),
178
+ [appUrl, sourceText, toolBridge, getBackendSession, createIframe, store]
179
+ );
180
+ if (snapshot.status === "error" && snapshot.error) {
181
+ return createElement("div", null, formatError(snapshot.error));
594
182
  }
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];
183
+ return /* @__PURE__ */ jsx2(RemoteUIContext.Provider, { value: store, children: /* @__PURE__ */ jsx2(RemoteErrorBoundary, { children: /* @__PURE__ */ jsx2(RemoteRoot, { store }) }, `${appKey}:${snapshot.generation}`) });
184
+ };
185
+ var RemoteElementViewComponent = ({
186
+ ctx,
187
+ node
188
+ }) => {
189
+ const componentStore = useMemo2(
190
+ () => ctx.selectComponent(node.type),
191
+ [ctx, node.type]
192
+ );
193
+ const component = useStore(componentStore);
194
+ const children = node.children.map((child) => (
195
+ // oxlint-disable-next-line no-use-before-define -- This deferred callback runs after initialization; the definitions are mutually dependent.
196
+ /* @__PURE__ */ jsx2(RemoteView, { nodeId: child.id }, child.id)
197
+ ));
601
198
  if (component === void 0) {
602
199
  throw new Error(`TailorKit component "${node.type}" is not registered.`);
603
200
  }
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]
201
+ const props = createRemoteElementProps(node, ctx.dispatch.bind(ctx));
202
+ return createElement(
203
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- The renderer was supplied through the typed component registry; React's createElement overload erases its heterogeneous props. */
204
+ component,
205
+ /* oxlint-enable typescript/no-unsafe-type-assertion */
206
+ props,
207
+ ...children
628
208
  );
629
- const getSnapshot = useCallback2(() => store.getNode(nodeId), [store, nodeId]);
630
- const node = useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
209
+ };
210
+ var RemoteElementView = memo(RemoteElementViewComponent);
211
+ var RemoteNodeView = ({
212
+ ctx,
213
+ nodeId
214
+ }) => {
215
+ const nodeStore = useMemo2(() => ctx.nodes.selectNode(nodeId), [ctx, nodeId]);
216
+ const node = useStore(nodeStore);
631
217
  if (node === null) {
632
218
  return null;
633
219
  }
634
220
  if (node.kind === "text") {
635
221
  return node.text;
636
222
  }
637
- const childElements = node.children.map((child) => /* @__PURE__ */ jsx3(RemoteView2, { nodeId: child.id }, child.id));
223
+ const childElements = node.children.map((child) => (
224
+ // oxlint-disable-next-line no-use-before-define -- This deferred callback runs after initialization; the definitions are mutually dependent.
225
+ /* @__PURE__ */ jsx2(RemoteView, { nodeId: child.id }, child.id)
226
+ ));
638
227
  if (node.kind === "fragment") {
639
- return createElement2(Fragment, { key: node.id }, ...childElements);
228
+ return createElement(Fragment2, { key: node.id }, ...childElements);
229
+ }
230
+ return /* @__PURE__ */ jsx2(RemoteElementView, { node, ctx });
231
+ };
232
+ var RemoteViewComponent = ({ nodeId }) => {
233
+ const ctx = useContext2(RemoteUIContext);
234
+ return ctx === null ? null : /* @__PURE__ */ jsx2(RemoteNodeView, { ctx, nodeId });
235
+ };
236
+ var RemoteView = memo(RemoteViewComponent);
237
+
238
+ // src/components/context.ts
239
+ import { createContext as createContext3, useContext as useContext3 } from "react";
240
+ var TailorkitContext = createContext3(
241
+ null
242
+ );
243
+ var useTailorkitContext = (component, expectedClient) => {
244
+ const context = useContext3(TailorkitContext);
245
+ if (!context) {
246
+ throw new Error(
247
+ `${component} must be rendered inside a TailorKit Provider.`
248
+ );
249
+ }
250
+ if (expectedClient && context.client !== expectedClient) {
251
+ throw new Error(
252
+ `${component} was created for a different TailorKit client than the surrounding Provider.`
253
+ );
254
+ }
255
+ return context;
256
+ };
257
+
258
+ // src/components/render-slot.tsx
259
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
260
+ var SlotRenderer = (options) => {
261
+ const { store, client } = useTailorkitContext(
262
+ options.mode === "managed" ? "RenderSlot" : "RenderSlot.Controlled"
263
+ );
264
+ const reactId = useId2();
265
+ const [state, setState] = useState2(() => ({
266
+ runtime: createSlotRuntime(store, options),
267
+ store
268
+ }));
269
+ if (state.store !== store) {
270
+ setState({ runtime: createSlotRuntime(store, options), store });
271
+ }
272
+ const { runtime } = state;
273
+ useEffect2(() => {
274
+ runtime.setInput(options);
275
+ }, [runtime, options]);
276
+ const snapshot = useStore2(runtime.state);
277
+ const viewId = `tailorkit-view-${reactId.replaceAll(":", "")}`;
278
+ const themeContext = useMemo3(
279
+ () => ({ theme: client.theme, viewId }),
280
+ [client.theme, viewId]
281
+ );
282
+ if (snapshot.status === "hidden") {
283
+ return null;
640
284
  }
641
- return /* @__PURE__ */ jsx3(RemoteElementView, { node, ctx });
642
- });
285
+ if (snapshot.status === "loading") {
286
+ return /* @__PURE__ */ jsx3("output", { children: snapshot.message });
287
+ }
288
+ if (snapshot.status === "error") {
289
+ return /* @__PURE__ */ jsx3("div", { role: "alert", children: snapshot.error.message });
290
+ }
291
+ return /* @__PURE__ */ jsx3(PrimitiveThemeContext.Provider, { value: themeContext, children: /* @__PURE__ */ jsxs2("div", { "data-tailorkit-view": viewId, children: [
292
+ /* @__PURE__ */ jsx3("style", { "data-tailorkit-theme-style": viewId, children: buildThemeCss(viewId, client.theme) }),
293
+ /* @__PURE__ */ jsx3(
294
+ RemoteViewHost,
295
+ {
296
+ appUrl: snapshot.appUrl,
297
+ sourceText: snapshot.sourceText,
298
+ toolBridge: snapshot.toolBridge,
299
+ getBackendSession: snapshot.getBackendSession,
300
+ components: client.components,
301
+ props: snapshot.props
302
+ },
303
+ snapshot.hostKey
304
+ )
305
+ ] }) });
306
+ };
307
+ var ManagedRenderSlot = (props) => /* @__PURE__ */ jsx3(SlotRenderer, { mode: "managed", ...props });
308
+ var ControlledRenderSlot = (props) => /* @__PURE__ */ jsx3(SlotRenderer, { mode: "controlled", ...props });
309
+ var RenderSlot = Object.assign(
310
+ ManagedRenderSlot,
311
+ {
312
+ Controlled: ControlledRenderSlot
313
+ }
314
+ );
315
+
316
+ // src/tailorkit.tsx
317
+ import {
318
+ createTailorKitClientConfig,
319
+ createComponentRegistry,
320
+ createTailorKitStore
321
+ } from "@tailorkit/client-core";
322
+ import { createElement as createElement2, useEffect as useEffect4, useMemo as useMemo8, useState as useState3 } from "react";
643
323
 
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({
324
+ // src/hooks/use-apps.ts
325
+ import { createValueMemo, createAppsQuery } from "@tailorkit/client-core";
326
+ import { useMemo as useMemo5 } from "react";
327
+
328
+ // src/hooks/use-query-result.ts
329
+ import { useStore as useStore3 } from "@nanostores/react";
330
+ import { useMemo as useMemo4 } from "react";
331
+ var useQueryResult = (state) => {
332
+ const result = useStore3(state);
333
+ return useMemo4(
334
+ () => ({
335
+ data: result.data,
336
+ error: result.error,
337
+ fetch: result.refetch,
338
+ isPending: result.isPending,
339
+ isRefetching: result.isFetching && !result.isPending
340
+ }),
341
+ [result]
342
+ );
343
+ };
344
+
345
+ // src/hooks/use-apps.ts
346
+ var useAppsStore = (store, options = {}) => {
347
+ const memoOptions = useMemo5(() => createValueMemo(), []);
348
+ const stableOptions = memoOptions({
349
+ appIds: options.appIds === void 0 ? void 0 : [...new Set(options.appIds)].toSorted(),
350
+ scopes: options.scopes === void 0 ? void 0 : [...new Set(options.scopes)].toSorted()
351
+ });
352
+ const query = useMemo5(
353
+ () => createAppsQuery(store, stableOptions),
354
+ [store, stableOptions]
355
+ );
356
+ return useQueryResult(query.state);
357
+ };
358
+ var useApps = (options = {}) => useAppsStore(useTailorkitContext("useApps").store, options);
359
+
360
+ // src/hooks/use-view-context.ts
361
+ import { useEffect as useEffect3, useMemo as useMemo6 } from "react";
362
+ var useViewContext = (view, options) => {
363
+ const { store } = useTailorkitContext("useViewContext");
364
+ const id = useMemo6(() => /* @__PURE__ */ Symbol("tailorkit-current-view"), []);
365
+ const { context, loading, error } = options;
366
+ useEffect3(
367
+ () => () => {
368
+ store.views.unregister(id);
369
+ },
370
+ [id, store]
371
+ );
372
+ useEffect3(() => {
373
+ store.views.register({ context, error, id, loading, view });
374
+ }, [id, view, context, loading, error, store]);
375
+ };
376
+
377
+ // src/hooks/use-views.ts
378
+ import { createValueMemo as createValueMemo2, createViewsQuery } from "@tailorkit/client-core";
379
+ import { useMemo as useMemo7 } from "react";
380
+ var useViews = (options) => {
381
+ const { store } = useTailorkitContext("useViews");
382
+ const memoOptions = useMemo7(() => createValueMemo2(), []);
383
+ const stableOptions = memoOptions({
384
+ appIds: options.appIds === void 0 ? void 0 : [...new Set(options.appIds)].toSorted(),
385
+ scopes: options.scopes === void 0 ? void 0 : [...new Set(options.scopes)].toSorted(),
386
+ slot: options.slot
387
+ });
388
+ const query = useMemo7(
389
+ () => createViewsQuery(store, stableOptions),
390
+ [store, stableOptions]
391
+ );
392
+ return useQueryResult(query.state);
393
+ };
394
+
395
+ // src/tailorkit.tsx
396
+ var components = (_contract, customComponents) => (
397
+ /* 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. */
398
+ customComponents
399
+ );
400
+ var createReactTailorKitClient = (options) => {
401
+ const wrappedComponents = createComponentRegistry(
402
+ options.components ?? {},
403
+ (renderer) => (
404
+ // oxlint-disable-next-line typescript/promise-function-async -- Client components must render synchronously; ReactNode also permits Promise results for server components.
405
+ function TailorKitComponent({
661
406
  children,
662
407
  ...props
663
408
  }) {
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
706
- }
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
409
+ const rendererArgs = { props };
410
+ if (children !== void 0) {
411
+ rendererArgs.children = children;
736
412
  }
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;
784
- }
785
- if (selected !== null && depth === selectedDepth && screen.order > selected.order) {
786
- selected = screen;
413
+ return renderer(
414
+ rendererArgs
415
+ );
787
416
  }
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;
417
+ )
418
+ );
419
+ const clientConfig = createTailorKitClientConfig({
420
+ ...options,
421
+ components: wrappedComponents
422
+ });
423
+ const ClientRenderSlot = (props) => {
424
+ useTailorkitContext("RenderSlot", client);
425
+ return createElement2(RenderSlot, props);
799
426
  };
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 = {
427
+ const client = {
428
+ ...clientConfig,
429
+ Provider: function Provider({ children, apps }) {
430
+ const [store] = useState3(
431
+ () => createTailorKitStore({
818
432
  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;
433
+ assetsBaseUrl: client.assetsBaseUrl,
434
+ baseUrl: client.baseUrl,
435
+ client: clientConfig.fetchClient,
436
+ contract: client.contract,
437
+ tools: client.tools
438
+ })
439
+ );
440
+ useEffect4(() => {
441
+ store.setProvidedApps(apps);
442
+ }, [store, apps]);
443
+ useEffect4(
444
+ () => () => {
445
+ store.previews.dispose();
446
+ },
447
+ [store]
448
+ );
449
+ const context = useMemo8(() => ({ client, store }), [store]);
450
+ return createElement2(
451
+ TailorkitContext.Provider,
452
+ { value: context },
453
+ children
454
+ );
863
455
  },
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;
456
+ RenderSlot: Object.assign(ClientRenderSlot, {
457
+ Controlled: function Controlled(props) {
458
+ useTailorkitContext("RenderSlot.Controlled", client);
459
+ return createElement2(
460
+ RenderSlot.Controlled,
461
+ /* 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. */
462
+ props
463
+ /* oxlint-enable typescript/no-unsafe-type-assertion */
464
+ );
877
465
  }
878
- selectCurrentScreen();
879
- emit();
466
+ }),
467
+ useApps: function useApps2(optionsValue) {
468
+ useTailorkitContext("useApps", client);
469
+ return useApps(optionsValue);
880
470
  },
881
- subscribe: (listener) => {
882
- listeners.add(listener);
883
- return () => {
884
- listeners.delete(listener);
885
- };
471
+ useViewContext: function useViewContext2(view, optionsValue2) {
472
+ useTailorkitContext("useViewContext", client);
473
+ useViewContext(view, optionsValue2);
886
474
  },
887
- unregisterScreen: (id) => {
888
- screens.delete(id);
889
- selectCurrentScreen();
890
- emit();
475
+ useViews: function useViews2(optionsValue3) {
476
+ useTailorkitContext("useViews", client);
477
+ return (
478
+ /* 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. */
479
+ useViews(optionsValue3)
480
+ );
891
481
  }
892
482
  };
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
- }
483
+ return client;
484
+ };
485
+ var createClient = (options) => createReactTailorKitClient(options);
916
486
  export {
487
+ RenderSlot,
917
488
  components,
918
- createTailorKitClient,
489
+ createClient,
919
490
  primitives
920
491
  };