@tailorkit/react 0.1.0-beta.40 → 0.1.0-beta.42
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/README.md +32 -0
- package/dist/index.js +62 -22
- package/dist/remote-view.d.ts +1 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
1
|
# TailorKit React
|
|
2
2
|
|
|
3
3
|
Use the React components and hooks in `@tailorkit/react` to integrate TailorKit into your SaaS product.
|
|
4
|
+
|
|
5
|
+
## Pressable
|
|
6
|
+
|
|
7
|
+
Register the standard `primitives` with the host client and `primitives(theme)` with the contract's Zod, Valibot, or ArkType adapter. Generated extension types expose the same Pressable API for every validator.
|
|
8
|
+
|
|
9
|
+
Pressable owns a `<div role="button">` and its layout. `layout` defaults to `"inline"` (`inline-flex`); `"box"`, `"flex"`, and `"grid"` use `block`, `flex`, and `grid`. It accepts existing primitive theme tokens, responsive styles, and layout props, including `align`, `gap`, `padding`, and `columns`.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<Pressable
|
|
13
|
+
layout="flex"
|
|
14
|
+
align="center"
|
|
15
|
+
gap="sm"
|
|
16
|
+
padding="md"
|
|
17
|
+
onPress={openEmail}
|
|
18
|
+
>
|
|
19
|
+
<Box grow="1">
|
|
20
|
+
<Inline>{email.sender}</Inline>
|
|
21
|
+
<Inline>{email.subject}</Inline>
|
|
22
|
+
</Box>
|
|
23
|
+
<Inline>{email.receivedAt}</Inline>
|
|
24
|
+
</Pressable>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use non-interactive layout children. Nested interactive controls, including buttons, links, inputs, and other Pressables, are unsupported. Pressable does not promote a child or support `asChild`.
|
|
28
|
+
|
|
29
|
+
Enabled controls participate in Tab and Shift+Tab navigation and show a focus outline. Pointer clicks activate once. Enter activates on keydown; Space activates on keyup and prevents scrolling. Holding a key does not repeat activation. Blur or disabling cancels pending Space activation. Focus stays on the control unless the action intentionally moves it. This follows the [ARIA button keyboard pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).
|
|
30
|
+
|
|
31
|
+
Children provide the accessible name. Set `ariaLabel` for an explicit name, including icon-only actions. `disabled` exposes `aria-disabled="true"`, sets `tabIndex={-1}`, and blocks pointer, keyboard, and programmatic click activation. The API also permits omitting `onPress`.
|
|
32
|
+
|
|
33
|
+
Style interactions with `:hover`, `:active`, `:focus-visible`, and `:disabled` conditional token values. `:active` includes held keyboard activation; `:disabled` targets the ARIA disabled state and suppresses other interaction styles. Each style accepts responsive breakpoint values. The focus indicator uses `outline: auto`, letting the browser choose its appearance. Pressable does not specify an outline width, color, or offset, and does not require a host CSS variable or focus-color token.
|
|
34
|
+
|
|
35
|
+
DOM events, keyboard state, focus, and styles stay in the React host. Only the zero-argument `onPress?: () => void` callback is dispatched into the sandbox. The host-provided Button and other primitives retain their existing behavior.
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
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
|
-
import { useEffect as useEffect2, useId as useId2, useMemo as useMemo3, useState as
|
|
4
|
+
import { useEffect as useEffect2, useId as useId2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
5
5
|
|
|
6
6
|
// src/primitives.tsx
|
|
7
7
|
import { buildPrimitiveCss } from "@tailorkit/client-core";
|
|
8
|
-
import { createContext, useContext, useId, useMemo } from "react";
|
|
8
|
+
import { createContext, useContext, useId, useMemo, useState } from "react";
|
|
9
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
var PrimitiveThemeContext = createContext(null);
|
|
11
11
|
var usePrimitiveNodeId = () => {
|
|
@@ -50,6 +50,10 @@ var Pressable = ({
|
|
|
50
50
|
const { ariaLabel, layout, onPress } = props;
|
|
51
51
|
const display = layout === "box" || layout === "flex" || layout === "grid" ? displays[layout] : displays.inline;
|
|
52
52
|
const disabled = props.disabled === true;
|
|
53
|
+
const [pressedKey, setPressedKey] = useState(null);
|
|
54
|
+
if (disabled && pressedKey !== null) {
|
|
55
|
+
setPressedKey(null);
|
|
56
|
+
}
|
|
53
57
|
const css = context ? buildPrimitiveCss({
|
|
54
58
|
display,
|
|
55
59
|
nodeId,
|
|
@@ -61,17 +65,62 @@ var Pressable = ({
|
|
|
61
65
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
62
66
|
css === "" ? null : /* @__PURE__ */ jsx("style", { "data-tailorkit-node-style": nodeId, children: css }),
|
|
63
67
|
/* @__PURE__ */ jsx(
|
|
64
|
-
"
|
|
68
|
+
"div",
|
|
65
69
|
{
|
|
70
|
+
"aria-disabled": disabled || void 0,
|
|
66
71
|
"aria-label": isStringValue(ariaLabel) ? ariaLabel : void 0,
|
|
72
|
+
"data-pressed": !disabled && pressedKey !== null ? "" : void 0,
|
|
67
73
|
"data-tailorkit-node": nodeId,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
onBlur: () => {
|
|
75
|
+
setPressedKey(null);
|
|
76
|
+
},
|
|
77
|
+
onClick: (event) => {
|
|
78
|
+
if (disabled) {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
event.stopPropagation();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (event.button === 0 && isPressCallback(onPress)) {
|
|
84
|
+
onPress();
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
onKeyDown: (event) => {
|
|
88
|
+
const { key } = event;
|
|
89
|
+
if (event.target !== event.currentTarget || key !== "Enter" && key !== " ") {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
if (disabled || event.repeat || pressedKey !== null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
setPressedKey(key);
|
|
97
|
+
if (key === "Enter" && isPressCallback(onPress)) {
|
|
71
98
|
onPress();
|
|
72
99
|
}
|
|
73
100
|
},
|
|
74
|
-
|
|
101
|
+
onKeyUp: (event) => {
|
|
102
|
+
const { key } = event;
|
|
103
|
+
if (event.target !== event.currentTarget || key !== "Enter" && key !== " ") {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
const activate = !disabled && key === " " && pressedKey === " ";
|
|
108
|
+
setPressedKey(null);
|
|
109
|
+
if (activate && isPressCallback(onPress)) {
|
|
110
|
+
onPress();
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
onPointerDown: (event) => {
|
|
114
|
+
if (disabled) {
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (event.button === 0) {
|
|
119
|
+
event.currentTarget.focus();
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
role: "button",
|
|
123
|
+
tabIndex: disabled ? -1 : 0,
|
|
75
124
|
children
|
|
76
125
|
}
|
|
77
126
|
)
|
|
@@ -115,7 +164,7 @@ import {
|
|
|
115
164
|
useContext as useContext2,
|
|
116
165
|
useEffect,
|
|
117
166
|
useMemo as useMemo2,
|
|
118
|
-
useState
|
|
167
|
+
useState as useState2
|
|
119
168
|
} from "react";
|
|
120
169
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
121
170
|
var RemoteUIContext = createContext2(null);
|
|
@@ -144,7 +193,6 @@ var RemoteRoot = ({ store }) => {
|
|
|
144
193
|
};
|
|
145
194
|
var RemoteViewHost = ({
|
|
146
195
|
appUrl,
|
|
147
|
-
sourceText,
|
|
148
196
|
toolBridge,
|
|
149
197
|
getBackendSession,
|
|
150
198
|
components: components2,
|
|
@@ -152,7 +200,7 @@ var RemoteViewHost = ({
|
|
|
152
200
|
props
|
|
153
201
|
}) => {
|
|
154
202
|
const appKey = appUrl.toString();
|
|
155
|
-
const [state, setState] =
|
|
203
|
+
const [state, setState] = useState2(() => ({
|
|
156
204
|
appKey,
|
|
157
205
|
store: createRemoteViewStore({ components: components2, props })
|
|
158
206
|
}));
|
|
@@ -172,10 +220,9 @@ var RemoteViewHost = ({
|
|
|
172
220
|
appUrl,
|
|
173
221
|
createIframe,
|
|
174
222
|
getBackendSession,
|
|
175
|
-
sourceText,
|
|
176
223
|
toolBridge
|
|
177
224
|
}),
|
|
178
|
-
[appUrl,
|
|
225
|
+
[appUrl, toolBridge, getBackendSession, createIframe, store]
|
|
179
226
|
);
|
|
180
227
|
if (snapshot.status === "error" && snapshot.error) {
|
|
181
228
|
return createElement("div", null, formatError(snapshot.error));
|
|
@@ -262,7 +309,7 @@ var SlotRenderer = (options) => {
|
|
|
262
309
|
options.mode === "managed" ? "RenderSlot" : "RenderSlot.Controlled"
|
|
263
310
|
);
|
|
264
311
|
const reactId = useId2();
|
|
265
|
-
const [state, setState] =
|
|
312
|
+
const [state, setState] = useState3(() => ({
|
|
266
313
|
runtime: createSlotRuntime(store, options),
|
|
267
314
|
store
|
|
268
315
|
}));
|
|
@@ -294,7 +341,6 @@ var SlotRenderer = (options) => {
|
|
|
294
341
|
RemoteViewHost,
|
|
295
342
|
{
|
|
296
343
|
appUrl: snapshot.appUrl,
|
|
297
|
-
sourceText: snapshot.sourceText,
|
|
298
344
|
toolBridge: snapshot.toolBridge,
|
|
299
345
|
getBackendSession: snapshot.getBackendSession,
|
|
300
346
|
components: client.components,
|
|
@@ -319,7 +365,7 @@ import {
|
|
|
319
365
|
createComponentRegistry,
|
|
320
366
|
createTailorKitStore
|
|
321
367
|
} from "@tailorkit/client-core";
|
|
322
|
-
import { createElement as createElement2, useEffect as useEffect4, useMemo as useMemo8, useState as
|
|
368
|
+
import { createElement as createElement2, useEffect as useEffect4, useMemo as useMemo8, useState as useState4 } from "react";
|
|
323
369
|
|
|
324
370
|
// src/hooks/use-apps.ts
|
|
325
371
|
import { createValueMemo, createAppsQuery } from "@tailorkit/client-core";
|
|
@@ -427,7 +473,7 @@ var createReactTailorKitClient = (options) => {
|
|
|
427
473
|
const client = {
|
|
428
474
|
...clientConfig,
|
|
429
475
|
Provider: function Provider({ children, apps }) {
|
|
430
|
-
const [store] =
|
|
476
|
+
const [store] = useState4(
|
|
431
477
|
() => createTailorKitStore({
|
|
432
478
|
apps,
|
|
433
479
|
assetsBaseUrl: client.assetsBaseUrl,
|
|
@@ -440,12 +486,6 @@ var createReactTailorKitClient = (options) => {
|
|
|
440
486
|
useEffect4(() => {
|
|
441
487
|
store.setProvidedApps(apps);
|
|
442
488
|
}, [store, apps]);
|
|
443
|
-
useEffect4(
|
|
444
|
-
() => () => {
|
|
445
|
-
store.previews.dispose();
|
|
446
|
-
},
|
|
447
|
-
[store]
|
|
448
|
-
);
|
|
449
489
|
const context = useMemo8(() => ({ client, store }), [store]);
|
|
450
490
|
return createElement2(
|
|
451
491
|
TailorkitContext.Provider,
|
package/dist/remote-view.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { RemoteProps } from "@tailorkit/sandbox/protocol";
|
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
interface RemoteViewHostProps {
|
|
5
5
|
appUrl: string | URL;
|
|
6
|
-
sourceText?: string;
|
|
7
6
|
toolBridge?: ToolBridge;
|
|
8
7
|
getBackendSession?: (options: {
|
|
9
8
|
refresh: boolean;
|
|
@@ -12,7 +11,7 @@ interface RemoteViewHostProps {
|
|
|
12
11
|
createIframe?: () => HTMLIFrameElement;
|
|
13
12
|
props?: RemoteProps;
|
|
14
13
|
}
|
|
15
|
-
export declare const RemoteViewHost: ({ appUrl,
|
|
14
|
+
export declare const RemoteViewHost: ({ appUrl, toolBridge, getBackendSession, components, createIframe, props, }: RemoteViewHostProps) => ReactNode;
|
|
16
15
|
interface RemoteViewProps {
|
|
17
16
|
nodeId: string;
|
|
18
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailorkit/react",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.42",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
"@floating-ui/react-dom": "^2.1.9",
|
|
48
48
|
"@nanostores/react": "2.0.1",
|
|
49
49
|
"@standard-schema/spec": "^1.1.0",
|
|
50
|
-
"@tailorkit/app": "0.1.0-beta.
|
|
51
|
-
"@tailorkit/client-core": "0.1.0-beta.
|
|
52
|
-
"@tailorkit/client-platform": "0.1.0-beta.
|
|
53
|
-
"@tailorkit/core": "0.1.0-beta.
|
|
54
|
-
"@tailorkit/sandbox": "0.1.0-beta.
|
|
50
|
+
"@tailorkit/app": "0.1.0-beta.42",
|
|
51
|
+
"@tailorkit/client-core": "0.1.0-beta.42",
|
|
52
|
+
"@tailorkit/client-platform": "0.1.0-beta.42",
|
|
53
|
+
"@tailorkit/core": "0.1.0-beta.42",
|
|
54
|
+
"@tailorkit/sandbox": "0.1.0-beta.42",
|
|
55
55
|
"nanostores": "1.5.5"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|