@tailorkit/react 0.1.0-beta.24 → 0.1.0-beta.25

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.
@@ -1,8 +1,8 @@
1
1
  import type { TailorKitStore } from "@tailorkit/client-core";
2
2
  import type { TailorKitClientConfig } from "../tailorkit";
3
- export interface TailorRootContextValue {
3
+ export interface TailorkitContextValue {
4
4
  store: TailorKitStore;
5
5
  client: TailorKitClientConfig;
6
6
  }
7
- export declare const TailorRootContext: import("react").Context<TailorRootContextValue | null>;
8
- export declare function useTailorRootContext(component: string, expectedClient?: TailorKitClientConfig): TailorRootContextValue;
7
+ export declare const TailorkitContext: import("react").Context<TailorkitContextValue | null>;
8
+ export declare function useTailorkitContext(component: string, expectedClient?: TailorKitClientConfig): TailorkitContextValue;
@@ -1,2 +1 @@
1
- export { Root } from "./root";
2
- export { Slot } from "./slot";
1
+ export { RenderSlot } from "./render-slot";
@@ -0,0 +1,9 @@
1
+ import type { ControlledRenderSlotProps, RenderSlotProps } from "@tailorkit/client-core";
2
+ import type { SlotDefinitions, ViewDefinition } from "@tailorkit/core/schema";
3
+ import type { ReactNode } from "react";
4
+ export type { ControlledRenderSlotProps, RenderSlotProps, RenderSlotContext, } from "@tailorkit/client-core";
5
+ type DefaultViews = Record<`/${string}`, ViewDefinition>;
6
+ export type RenderSlotComponent<TViews extends Record<string, ViewDefinition> = DefaultViews, TSlots extends SlotDefinitions = SlotDefinitions> = ((props: RenderSlotProps<TSlots>) => ReactNode) & {
7
+ Controlled: (props: ControlledRenderSlotProps<TViews, TSlots>) => ReactNode;
8
+ };
9
+ export declare const RenderSlot: RenderSlotComponent;
@@ -1,5 +1,6 @@
1
- import type { AppsQueryOptions, QueryResult, TailorKitApp, TailorKitStore } from "@tailorkit/client-core";
1
+ import type { AppsQueryOptions, TailorKitApp, TailorKitStore } from "@tailorkit/client-core";
2
+ import type { UseQueryResult } from "./use-query-result";
2
3
  export type UseAppsOptions<TScopeNames extends string = string> = AppsQueryOptions<TScopeNames>;
3
- export type UseAppsResult = QueryResult<TailorKitApp[]>;
4
+ export type UseAppsResult = UseQueryResult<TailorKitApp[]>;
4
5
  export declare function useApps(options?: UseAppsOptions): UseAppsResult;
5
6
  export declare function useAppsStore(store: TailorKitStore, options?: UseAppsOptions): UseAppsResult;
@@ -0,0 +1,9 @@
1
+ import type { QueryResult } from "@tailorkit/client-core";
2
+ import type { ReadableAtom } from "nanostores";
3
+ export type UseQueryResult<T> = Pick<QueryResult<T>, "data" | "isPending" | "error"> & {
4
+ /** Whether a background fetch is running after the initial pending state. */
5
+ isRefetching: boolean;
6
+ /** Fetch fresh data, bypassing the cache's freshness window. */
7
+ fetch: () => Promise<void>;
8
+ };
9
+ export declare function useQueryResult<T>(state: ReadableAtom<QueryResult<T>>): UseQueryResult<T>;
@@ -1,6 +1,7 @@
1
- import type { ViewsQueryOptions, ViewsQueryResult } from "@tailorkit/client-core";
1
+ import type { SlotItem, ViewsQueryOptions } from "@tailorkit/client-core";
2
+ import type { UseQueryResult } from "./use-query-result";
2
3
  export type { SlotItem } from "@tailorkit/client-core";
3
4
  export type UseViewsOptions<TScopeNames extends string = string, TSlot extends string = string> = ViewsQueryOptions<TScopeNames, TSlot>;
4
- export type UseViewsResult<TMultiple extends boolean = boolean> = ViewsQueryResult<TMultiple>;
5
+ export type UseViewsResult<TMultiple extends boolean = boolean> = UseQueryResult<SlotItem<TMultiple>[]>;
5
6
  /** Subscribe to the shared views query using React's lifecycle. */
6
7
  export declare function useViews(options: UseViewsOptions): UseViewsResult;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- export { Slot } from "./components/slot";
2
- export type { ControlledSlotProps, SlotComponent, SlotContext, SlotProps } from "./components/slot";
1
+ export { RenderSlot } from "./components/render-slot";
2
+ export type { ControlledRenderSlotProps, RenderSlotComponent, RenderSlotContext, RenderSlotProps, } from "./components/render-slot";
3
3
  export { components, createTailorKitClient } from "./tailorkit";
4
- export type { TailorKitApp, TailorKitClientConfig, TailorKitInstance } from "./tailorkit";
5
- export { Root } from "./components/root";
4
+ export type { TailorKitApp, TailorKitClientConfig, TailorKitInstance, TailorKitProviderProps, } from "./tailorkit";
6
5
  export type { UseAppsOptions, UseAppsResult } from "./hooks/use-apps";
7
6
  export type { SlotItem, UseViewsOptions, UseViewsResult } from "./hooks/use-views";
8
7
  export type { UseViewContext, ViewOptions, ViewState } from "./hooks/use-view-context";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/components/slot.tsx
1
+ // src/components/render-slot.tsx
2
2
  import { useStore as useStore2 } from "@nanostores/react";
3
3
  import { createSlotRuntime, buildThemeCss } from "@tailorkit/client-core";
4
4
  import { useEffect as useEffect2, useId as useId2, useMemo as useMemo3 } from "react";
@@ -134,32 +134,34 @@ var RemoteView = memo(RemoteViewComponent);
134
134
 
135
135
  // src/components/context.ts
136
136
  import { createContext as createContext3, useContext as useContext3 } from "react";
137
- var TailorRootContext = createContext3(null);
138
- function useTailorRootContext(component, expectedClient) {
139
- const context = useContext3(TailorRootContext);
137
+ var TailorkitContext = createContext3(null);
138
+ function useTailorkitContext(component, expectedClient) {
139
+ const context = useContext3(TailorkitContext);
140
140
  if (!context) {
141
- throw new Error(`${component} must be rendered inside Root.`);
141
+ throw new Error(`${component} must be rendered inside a TailorKit Provider.`);
142
142
  }
143
143
  if (expectedClient && context.client !== expectedClient) {
144
144
  throw new Error(
145
- `${component} was created for a different TailorKit client than the one passed to Root.`
145
+ `${component} was created for a different TailorKit client than the surrounding Provider.`
146
146
  );
147
147
  }
148
148
  return context;
149
149
  }
150
150
 
151
- // src/components/slot.tsx
151
+ // src/components/render-slot.tsx
152
152
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
153
- function ManagedSlot(props) {
153
+ function ManagedRenderSlot(props) {
154
154
  return /* @__PURE__ */ jsx3(SlotRenderer, { mode: "managed", ...props });
155
155
  }
156
- function ControlledSlot(props) {
156
+ function ControlledRenderSlot(props) {
157
157
  return /* @__PURE__ */ jsx3(SlotRenderer, { mode: "controlled", ...props });
158
158
  }
159
- var Slot = Object.assign(ManagedSlot, { Controlled: ControlledSlot });
159
+ var RenderSlot = Object.assign(ManagedRenderSlot, {
160
+ Controlled: ControlledRenderSlot
161
+ });
160
162
  function SlotRenderer(options) {
161
- const { store, client } = useTailorRootContext(
162
- options.mode === "managed" ? "Slot" : "Slot.Controlled"
163
+ const { store, client } = useTailorkitContext(
164
+ options.mode === "managed" ? "RenderSlot" : "RenderSlot.Controlled"
163
165
  );
164
166
  const reactId = useId2();
165
167
  const runtime = useMemo3(() => createSlotRuntime(store, options), [store]);
@@ -186,13 +188,17 @@ function SlotRenderer(options) {
186
188
  }
187
189
 
188
190
  // src/tailorkit.tsx
189
- import { createTailorKitClientConfig, createComponentRegistry } from "@tailorkit/client-core";
190
- import { createElement as createElement2 } from "react";
191
+ import {
192
+ createTailorKitClientConfig,
193
+ createComponentRegistry,
194
+ createTailorKitStore
195
+ } from "@tailorkit/client-core";
196
+ import { createElement as createElement2, useEffect as useEffect4, useMemo as useMemo8, useState } from "react";
191
197
 
192
198
  // src/hooks/use-view-context.ts
193
199
  import { useEffect as useEffect3, useMemo as useMemo4 } from "react";
194
200
  function useViewContext(view, options) {
195
- const { store } = useTailorRootContext("useViewContext");
201
+ const { store } = useTailorkitContext("useViewContext");
196
202
  const id = useMemo4(() => /* @__PURE__ */ Symbol("tailorkit-current-view"), []);
197
203
  const { context, loading, error } = options;
198
204
  useEffect3(
@@ -207,27 +213,44 @@ function useViewContext(view, options) {
207
213
  }
208
214
 
209
215
  // src/hooks/use-apps.ts
216
+ import { useMemo as useMemo6 } from "react";
217
+ import { appsQueryKey, createAppsQuery } from "@tailorkit/client-core";
218
+
219
+ // src/hooks/use-query-result.ts
210
220
  import { useStore as useStore3 } from "@nanostores/react";
211
221
  import { useMemo as useMemo5 } from "react";
212
- import { appsQueryKey, createAppsQuery } from "@tailorkit/client-core";
222
+ function useQueryResult(state) {
223
+ const result = useStore3(state);
224
+ return useMemo5(
225
+ () => ({
226
+ data: result.data,
227
+ isPending: result.isPending,
228
+ error: result.error,
229
+ isRefetching: result.isFetching && !result.isPending,
230
+ fetch: result.refetch
231
+ }),
232
+ [result]
233
+ );
234
+ }
235
+
236
+ // src/hooks/use-apps.ts
213
237
  function useApps(options = {}) {
214
- return useAppsStore(useTailorRootContext("useApps").store, options);
238
+ return useAppsStore(useTailorkitContext("useApps").store, options);
215
239
  }
216
240
  function useAppsStore(store, options = {}) {
217
241
  const key = appsQueryKey(options);
218
- const query = useMemo5(() => createAppsQuery(store, options), [store, key]);
219
- return useStore3(query.state);
242
+ const query = useMemo6(() => createAppsQuery(store, options), [store, key]);
243
+ return useQueryResult(query.state);
220
244
  }
221
245
 
222
246
  // src/hooks/use-views.ts
223
- import { useStore as useStore4 } from "@nanostores/react";
224
- import { useMemo as useMemo6 } from "react";
247
+ import { useMemo as useMemo7 } from "react";
225
248
  import { appsQueryKey as appsQueryKey2, createViewsQuery } from "@tailorkit/client-core";
226
249
  function useViews(options) {
227
- const { store } = useTailorRootContext("useViews");
250
+ const { store } = useTailorkitContext("useViews");
228
251
  const key = appsQueryKey2(options);
229
- const query = useMemo6(() => createViewsQuery(store, options), [store, key, options.slot]);
230
- return useStore4(query.state);
252
+ const query = useMemo7(() => createViewsQuery(store, options), [store, key, options.slot]);
253
+ return useQueryResult(query.state);
231
254
  }
232
255
 
233
256
  // src/tailorkit.tsx
@@ -252,146 +275,49 @@ function createReactTailorKitClient(options) {
252
275
  const clientConfig = createTailorKitClientConfig({ ...options, components: wrappedComponents });
253
276
  const client = {
254
277
  ...clientConfig,
255
- Slot: Object.assign(
256
- function ClientSlot(props) {
257
- useTailorRootContext("Slot", client);
258
- return createElement2(Slot, props);
278
+ Provider: function TailorKitProvider({ children, apps }) {
279
+ const [store] = useState(
280
+ () => createTailorKitStore(client.baseUrl, apps, client.fetchClient)
281
+ );
282
+ useEffect4(() => {
283
+ store.setProvidedApps(apps);
284
+ }, [store, apps]);
285
+ useEffect4(() => () => store.previews.dispose(), [store]);
286
+ const context = useMemo8(() => ({ store, client }), [store]);
287
+ return createElement2(TailorkitContext.Provider, { value: context }, children);
288
+ },
289
+ RenderSlot: Object.assign(
290
+ function ClientRenderSlot(props) {
291
+ useTailorkitContext("RenderSlot", client);
292
+ return createElement2(RenderSlot, props);
259
293
  },
260
294
  {
261
- Controlled: function ClientControlledSlot(props) {
262
- useTailorRootContext("Slot.Controlled", client);
263
- return createElement2(Slot.Controlled, props);
295
+ Controlled: function ClientControlledRenderSlot(props) {
296
+ useTailorkitContext("RenderSlot.Controlled", client);
297
+ return createElement2(
298
+ RenderSlot.Controlled,
299
+ props
300
+ );
264
301
  }
265
302
  }
266
303
  ),
267
304
  useApps: function useClientApps(options2) {
268
- useTailorRootContext("useApps", client);
305
+ useTailorkitContext("useApps", client);
269
306
  return useApps(options2);
270
307
  },
271
308
  useViews: function useClientViews(options2) {
272
- useTailorRootContext("useViews", client);
309
+ useTailorkitContext("useViews", client);
273
310
  return useViews(options2);
274
311
  },
275
312
  useViewContext: function useClientViewContext(view, options2) {
276
- useTailorRootContext("useViewContext", client);
313
+ useTailorkitContext("useViewContext", client);
277
314
  useViewContext(view, options2);
278
315
  }
279
316
  };
280
317
  return client;
281
318
  }
282
-
283
- // src/components/root.tsx
284
- import { useEffect as useEffect4, useMemo as useMemo8, useState } from "react";
285
- import { createTailorKitStore, toBaseUrl } from "@tailorkit/client-core";
286
-
287
- // src/components/render.tsx
288
- import { cloneElement, createElement as createElement3, isValidElement, useMemo as useMemo7 } from "react";
289
- function useRender({
290
- defaultTagName,
291
- props,
292
- render
293
- }) {
294
- return useMemo7(() => {
295
- if (render) {
296
- if (!isValidElement(render)) {
297
- throw new Error("The render prop must be a valid React element.");
298
- }
299
- return cloneElement(render, mergeProps(render.props, props));
300
- }
301
- return createElement3(defaultTagName, props);
302
- }, [defaultTagName, props, render]);
303
- }
304
- function mergeProps(...propSets) {
305
- const merged = {};
306
- for (const props of propSets) {
307
- if (!props) {
308
- continue;
309
- }
310
- for (const [key, value] of Object.entries(props)) {
311
- if (value === void 0) {
312
- continue;
313
- }
314
- const existing = merged[key];
315
- if (key === "className" && existing && value) {
316
- merged[key] = `${existing} ${value}`;
317
- continue;
318
- }
319
- if (key === "style" && existing && value) {
320
- merged[key] = {
321
- ...existing,
322
- ...value
323
- };
324
- continue;
325
- }
326
- if (key === "ref" && existing && value) {
327
- merged[key] = composeRefs(existing, value);
328
- continue;
329
- }
330
- if (isEventHandler(key) && typeof existing === "function" && typeof value === "function") {
331
- merged[key] = (...args) => {
332
- existing(...args);
333
- const event = args[0];
334
- if (!event?.defaultPrevented) {
335
- value(...args);
336
- }
337
- };
338
- continue;
339
- }
340
- merged[key] = value;
341
- }
342
- }
343
- return merged;
344
- }
345
- function composeRefs(...refs) {
346
- return (node) => {
347
- for (const ref of refs) {
348
- if (typeof ref === "function") {
349
- ref(node);
350
- } else if (ref) {
351
- ref.current = node;
352
- }
353
- }
354
- };
355
- }
356
- function isEventHandler(key) {
357
- return /^on[A-Z]/u.test(key);
358
- }
359
-
360
- // src/components/root.tsx
361
- import { jsx as jsx4 } from "react/jsx-runtime";
362
- function Root({ apps: appsProp, children, render, client, ...props }) {
363
- const baseUrl = toBaseUrl(client.baseUrl).toString();
364
- const [previous, setStore] = useState(() => ({
365
- store: createTailorKitStore(baseUrl, appsProp, client.fetchClient),
366
- fetchClient: client.fetchClient
367
- }));
368
- const previousStore = previous.store;
369
- let store = previousStore;
370
- if (previousStore.baseUrl.toString() !== baseUrl || previous.fetchClient !== client.fetchClient) {
371
- store = createTailorKitStore(baseUrl, appsProp, client.fetchClient);
372
- setStore({ store, fetchClient: client.fetchClient });
373
- }
374
- useEffect4(() => {
375
- store.setProvidedApps(appsProp);
376
- }, [store, appsProp]);
377
- useEffect4(() => () => store.previews.dispose(), [store]);
378
- const context = useMemo8(
379
- () => ({
380
- store,
381
- client
382
- }),
383
- [store, client]
384
- );
385
- const element = render ? useRender({
386
- defaultTagName: "div",
387
- props: mergeProps({ children }, props),
388
- render
389
- }) : children;
390
- return /* @__PURE__ */ jsx4(TailorRootContext.Provider, { value: context, children: element });
391
- }
392
319
  export {
393
- Root,
394
- Slot,
320
+ RenderSlot,
395
321
  components,
396
322
  createTailorKitClient,
397
323
  primitives
@@ -1,4 +1,4 @@
1
- import type { AnyComponentDefinition, ComponentRenderer, ComponentRenderers, CompleteComponentRenderers, TailorKitClientConfig, TailorKitServerShape, ServerComponents, ServerViews, ServerSlots, ServerScopeNames, SlotMultiple } from "@tailorkit/client-core";
1
+ import type { AnyComponentDefinition, ComponentRenderer, ComponentRenderers, CompleteComponentRenderers, TailorKitClientConfig, TailorKitApp, TailorKitServerShape, ServerComponents, ServerViews, ServerSlots, ServerScopeNames, SlotMultiple } from "@tailorkit/client-core";
2
2
  export type { TailorKitClientConfig } from "@tailorkit/client-core";
3
3
  import type { TailorKitCacheOptions } from "@tailorkit/client-core";
4
4
  import type { ReactNode } from "react";
@@ -7,12 +7,17 @@ import type { primitives } from "./primitives";
7
7
  import type { UseViewContext } from "./hooks/use-view-context";
8
8
  import type { UseAppsOptions, UseAppsResult } from "./hooks/use-apps";
9
9
  import type { UseViewsOptions, UseViewsResult } from "./hooks/use-views";
10
- import type { SlotComponent } from "./components/slot";
10
+ import type { RenderSlotComponent } from "./components/render-slot";
11
11
  export type { TailorKitApp } from "@tailorkit/client-core";
12
+ export interface TailorKitProviderProps {
13
+ apps?: TailorKitApp[];
14
+ children?: ReactNode;
15
+ }
12
16
  export interface TailorKitInstance<TViews extends Record<string, ViewDefinition> = Record<string, ViewDefinition>, TSlots extends SlotDefinitions = SlotDefinitions, TScopeNames extends string = string> extends TailorKitClientConfig {
13
17
  readonly $slots?: TSlots;
14
18
  readonly $views?: TViews;
15
- readonly Slot: SlotComponent<TViews, TSlots>;
19
+ readonly Provider: (props: TailorKitProviderProps) => ReactNode;
20
+ readonly RenderSlot: RenderSlotComponent<TViews, TSlots>;
16
21
  readonly useApps: (options?: UseAppsOptions<TScopeNames>) => UseAppsResult;
17
22
  readonly useViews: <TSlot extends keyof TSlots & string>(options: UseViewsOptions<TScopeNames, TSlot>) => UseViewsResult<SlotMultiple<TSlots[TSlot]>>;
18
23
  readonly useViewContext: UseViewContext<TViews>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailorkit/react",
3
- "version": "0.1.0-beta.24",
3
+ "version": "0.1.0-beta.25",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,11 +24,11 @@
24
24
  "@floating-ui/react-dom": "^2.1.9",
25
25
  "@nanostores/react": "2.0.1",
26
26
  "@standard-schema/spec": "^1.1.0",
27
- "@tailorkit/app": "0.1.0-beta.24",
28
- "@tailorkit/client-core": "0.1.0-beta.24",
29
- "@tailorkit/client-platform": "0.1.0-beta.24",
30
- "@tailorkit/core": "0.1.0-beta.24",
31
- "@tailorkit/sandbox": "0.1.0-beta.24",
27
+ "@tailorkit/app": "0.1.0-beta.25",
28
+ "@tailorkit/client-core": "0.1.0-beta.25",
29
+ "@tailorkit/client-platform": "0.1.0-beta.25",
30
+ "@tailorkit/core": "0.1.0-beta.25",
31
+ "@tailorkit/sandbox": "0.1.0-beta.25",
32
32
  "nanostores": "1.5.4"
33
33
  },
34
34
  "devDependencies": {
@@ -1,19 +0,0 @@
1
- import type { ComponentPropsWithoutRef, ElementType, HTMLAttributes, ReactElement, ReactNode, Ref } from "react";
2
- type ElementProps<TTagName extends ElementType> = ComponentPropsWithoutRef<TTagName> & {
3
- ref?: Ref<unknown>;
4
- };
5
- export interface RenderProps {
6
- render?: ReactElement<Record<string, unknown>>;
7
- }
8
- export type ComponentProps<TTagName extends ElementType> = ElementProps<TTagName> & RenderProps;
9
- export declare function useRender<TTagName extends ElementType>({ defaultTagName, props, render, }: {
10
- defaultTagName: TTagName;
11
- props: ElementProps<TTagName>;
12
- render?: ReactElement<Record<string, unknown>>;
13
- }): ReactNode;
14
- export declare function mergeProps<TProps extends Record<string, unknown>>(...propSets: (TProps | Record<string, unknown> | undefined)[]): TProps;
15
- export declare function composeRefs<T>(...refs: (Ref<T> | undefined)[]): Ref<T>;
16
- export type HtmlProps<TElement extends HTMLElement> = HTMLAttributes<TElement> & {
17
- ref?: Ref<TElement>;
18
- };
19
- export {};
@@ -1,9 +0,0 @@
1
- import type { ReactNode } from "react";
2
- import type { TailorKitApp, TailorKitClientConfig } from "../tailorkit";
3
- import type { ComponentProps } from "./render";
4
- export interface RootProps extends ComponentProps<"div"> {
5
- apps?: TailorKitApp[];
6
- children?: ReactNode;
7
- client: TailorKitClientConfig;
8
- }
9
- export declare function Root({ apps: appsProp, children, render, client, ...props }: RootProps): ReactNode;
@@ -1,9 +0,0 @@
1
- import type { ControlledSlotProps, SlotProps } from "@tailorkit/client-core";
2
- import type { SlotDefinitions, ViewDefinition } from "@tailorkit/core/schema";
3
- import type { ReactNode } from "react";
4
- export type { ControlledSlotProps, SlotProps, SlotContext } from "@tailorkit/client-core";
5
- type DefaultViews = Record<`/${string}`, ViewDefinition>;
6
- export type SlotComponent<TViews extends Record<string, ViewDefinition> = DefaultViews, TSlots extends SlotDefinitions = SlotDefinitions> = ((props: SlotProps<TSlots>) => ReactNode) & {
7
- Controlled: (props: ControlledSlotProps<TViews, TSlots>) => ReactNode;
8
- };
9
- export declare const Slot: SlotComponent;