@webstudio-is/sdk-components-react-radix 0.85.0 → 0.87.0
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/lib/__generated__/accordion.props.js +2134 -0
- package/lib/__generated__/button.props.js +454 -0
- package/lib/__generated__/dialog.props.js +0 -7
- package/lib/__generated__/input.props.js +451 -0
- package/lib/__generated__/label.props.js +421 -0
- package/lib/__generated__/popover.props.js +0 -7
- package/lib/__generated__/sheet.props.js +0 -7
- package/lib/__generated__/textarea.props.js +431 -0
- package/lib/__generated__/tooltip.props.js +0 -7
- package/lib/accordion.js +51 -0
- package/lib/accordion.ws.js +243 -0
- package/lib/button.js +8 -0
- package/lib/button.ws.js +133 -0
- package/lib/cjs/__generated__/accordion.props.js +2154 -0
- package/lib/cjs/__generated__/button.props.js +474 -0
- package/lib/cjs/__generated__/dialog.props.js +0 -7
- package/lib/cjs/__generated__/input.props.js +471 -0
- package/lib/cjs/__generated__/label.props.js +441 -0
- package/lib/cjs/__generated__/popover.props.js +0 -7
- package/lib/cjs/__generated__/sheet.props.js +0 -7
- package/lib/cjs/__generated__/textarea.props.js +451 -0
- package/lib/cjs/__generated__/tooltip.props.js +0 -7
- package/lib/cjs/accordion.js +60 -0
- package/lib/cjs/accordion.ws.js +261 -0
- package/lib/cjs/button.js +28 -0
- package/lib/cjs/button.ws.js +160 -0
- package/lib/cjs/collapsible.js +2 -16
- package/lib/cjs/collapsible.ws.js +1 -8
- package/lib/cjs/components.js +14 -0
- package/lib/cjs/dialog.js +38 -6
- package/lib/cjs/dialog.ws.js +15 -26
- package/lib/cjs/hooks.js +15 -1
- package/lib/cjs/input.js +28 -0
- package/lib/cjs/input.ws.js +103 -0
- package/lib/cjs/label.js +37 -0
- package/lib/cjs/label.ws.js +74 -0
- package/lib/cjs/metas.js +14 -0
- package/lib/cjs/popover.js +37 -5
- package/lib/cjs/popover.ws.js +15 -18
- package/lib/cjs/props.js +14 -0
- package/lib/cjs/sheet.js +34 -1
- package/lib/cjs/sheet.ws.js +33 -19
- package/lib/cjs/tabs.js +20 -1
- package/lib/cjs/tabs.ws.js +3 -25
- package/lib/cjs/textarea.js +28 -0
- package/lib/cjs/textarea.ws.js +98 -0
- package/lib/cjs/theme/tailwind-classes.js +186 -23
- package/lib/cjs/theme/tailwind-colors.js +10 -1
- package/lib/cjs/tooltip.js +36 -4
- package/lib/cjs/tooltip.ws.js +15 -18
- package/lib/collapsible.js +2 -16
- package/lib/collapsible.ws.js +1 -8
- package/lib/components.js +20 -0
- package/lib/dialog.js +38 -6
- package/lib/dialog.ws.js +15 -26
- package/lib/hooks.js +15 -1
- package/lib/input.js +8 -0
- package/lib/input.ws.js +75 -0
- package/lib/label.js +9 -0
- package/lib/label.ws.js +46 -0
- package/lib/metas.js +20 -0
- package/lib/popover.js +37 -5
- package/lib/popover.ws.js +15 -18
- package/lib/props.js +20 -0
- package/lib/sheet.js +34 -1
- package/lib/sheet.ws.js +33 -19
- package/lib/tabs.js +24 -2
- package/lib/tabs.ws.js +3 -25
- package/lib/textarea.js +8 -0
- package/lib/textarea.ws.js +70 -0
- package/lib/theme/tailwind-classes.js +191 -24
- package/lib/theme/tailwind-colors.js +10 -1
- package/lib/tooltip.js +36 -4
- package/lib/tooltip.ws.js +15 -18
- package/lib/types/__generated__/accordion.props.d.ts +6 -0
- package/lib/types/__generated__/button.props.d.ts +2 -0
- package/lib/types/__generated__/input.props.d.ts +2 -0
- package/lib/types/__generated__/label.props.d.ts +2 -0
- package/lib/types/__generated__/textarea.props.d.ts +2 -0
- package/lib/types/accordion.d.ts +12 -0
- package/lib/types/accordion.ws.d.ts +11 -0
- package/lib/types/button.d.ts +7 -0
- package/lib/types/button.stories.d.ts +20 -0
- package/lib/types/button.ws.d.ts +7 -0
- package/lib/types/components.d.ts +5 -0
- package/lib/types/dialog.d.ts +5 -11
- package/lib/types/input.d.ts +2 -0
- package/lib/types/input.stories.d.ts +20 -0
- package/lib/types/input.ws.d.ts +3 -0
- package/lib/types/label.d.ts +3 -0
- package/lib/types/label.stories.d.ts +9 -0
- package/lib/types/label.ws.d.ts +3 -0
- package/lib/types/metas.d.ts +5 -0
- package/lib/types/popover.d.ts +4 -10
- package/lib/types/props.d.ts +5 -0
- package/lib/types/sheet.d.ts +4 -4
- package/lib/types/tabs.d.ts +2 -0
- package/lib/types/textarea.d.ts +2 -0
- package/lib/types/textarea.stories.d.ts +14 -0
- package/lib/types/textarea.ws.d.ts +3 -0
- package/lib/types/theme/tailwind-classes.d.ts +16 -5
- package/lib/types/theme/tailwind-colors.d.ts +9 -0
- package/lib/types/tooltip.d.ts +3 -9
- package/package.json +9 -7
- package/src/__generated__/accordion.props.ts +2382 -0
- package/src/__generated__/button.props.ts +503 -0
- package/src/__generated__/dialog.props.ts +0 -7
- package/src/__generated__/input.props.ts +500 -0
- package/src/__generated__/label.props.ts +470 -0
- package/src/__generated__/popover.props.ts +0 -7
- package/src/__generated__/sheet.props.ts +0 -7
- package/src/__generated__/textarea.props.ts +480 -0
- package/src/__generated__/tooltip.props.ts +0 -7
- package/src/accordion.stories.tsx +21 -0
- package/src/accordion.tsx +81 -0
- package/src/accordion.ws.ts +270 -0
- package/src/button.stories.ts +35 -0
- package/src/button.tsx +25 -0
- package/src/button.ws.ts +155 -0
- package/src/collapsible.tsx +2 -16
- package/src/collapsible.ws.ts +1 -8
- package/src/components.ts +11 -0
- package/src/dialog.stories.tsx +21 -0
- package/src/dialog.tsx +50 -24
- package/src/dialog.ws.tsx +15 -26
- package/src/hooks.ts +15 -1
- package/src/input.stories.ts +31 -0
- package/src/input.tsx +12 -0
- package/src/input.ws.ts +78 -0
- package/src/label.stories.ts +22 -0
- package/src/label.tsx +15 -0
- package/src/label.ws.ts +48 -0
- package/src/metas.ts +11 -0
- package/src/popover.stories.tsx +21 -0
- package/src/popover.tsx +49 -23
- package/src/popover.ws.tsx +15 -18
- package/src/props.ts +11 -0
- package/src/sheet.tsx +39 -0
- package/src/sheet.ws.tsx +33 -19
- package/src/tabs.tsx +32 -1
- package/src/tabs.ws.ts +1 -23
- package/src/textarea.stories.ts +27 -0
- package/src/textarea.tsx +12 -0
- package/src/textarea.ws.ts +74 -0
- package/src/theme/tailwind-classes.ts +233 -38
- package/src/theme/tailwind-colors.ts +9 -16
- package/src/tooltip.stories.tsx +21 -0
- package/src/tooltip.tsx +46 -20
- package/src/tooltip.ws.tsx +15 -18
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccordionIcon,
|
|
3
|
+
ItemIcon,
|
|
4
|
+
HeaderIcon,
|
|
5
|
+
TriggerIcon,
|
|
6
|
+
ContentIcon,
|
|
7
|
+
} from "@webstudio-is/icons/svg";
|
|
8
|
+
import type {
|
|
9
|
+
EmbedTemplateStyleDecl,
|
|
10
|
+
PresetStyle,
|
|
11
|
+
WsComponentMeta,
|
|
12
|
+
WsComponentPropsMeta,
|
|
13
|
+
} from "@webstudio-is/react-sdk";
|
|
14
|
+
import { div, h3, button } from "@webstudio-is/react-sdk/css-normalize";
|
|
15
|
+
import * as tc from "./theme/tailwind-classes";
|
|
16
|
+
import {
|
|
17
|
+
propsAccordion,
|
|
18
|
+
propsAccordionItem,
|
|
19
|
+
propsAccordionHeader,
|
|
20
|
+
propsAccordionTrigger,
|
|
21
|
+
propsAccordionContent,
|
|
22
|
+
} from "./__generated__/accordion.props";
|
|
23
|
+
|
|
24
|
+
const presetStyle = {
|
|
25
|
+
div,
|
|
26
|
+
} satisfies PresetStyle<"div">;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Styles source without animations:
|
|
30
|
+
* https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/default/ui/accordion.tsx
|
|
31
|
+
*
|
|
32
|
+
* Attributions
|
|
33
|
+
* MIT License
|
|
34
|
+
* Copyright (c) 2023 shadcn
|
|
35
|
+
**/
|
|
36
|
+
|
|
37
|
+
// border-b
|
|
38
|
+
const accordionItemStyles: EmbedTemplateStyleDecl[] = [tc.borderB()].flat();
|
|
39
|
+
|
|
40
|
+
// flex
|
|
41
|
+
const accordionHeaderStyles: EmbedTemplateStyleDecl[] = [tc.flex()].flat();
|
|
42
|
+
|
|
43
|
+
// flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180
|
|
44
|
+
const accordionTriggerStyles: EmbedTemplateStyleDecl[] = [
|
|
45
|
+
tc.flex(),
|
|
46
|
+
tc.flex(1),
|
|
47
|
+
tc.items("center"),
|
|
48
|
+
tc.justify("between"),
|
|
49
|
+
tc.py(4),
|
|
50
|
+
tc.font("medium"),
|
|
51
|
+
tc.transition("all"),
|
|
52
|
+
tc.hover([tc.underline()].flat()),
|
|
53
|
+
].flat();
|
|
54
|
+
|
|
55
|
+
// overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down
|
|
56
|
+
// pb-4 pt-0
|
|
57
|
+
const accordionContentStyles: EmbedTemplateStyleDecl[] = [
|
|
58
|
+
tc.overflow("hidden"),
|
|
59
|
+
tc.text("sm"),
|
|
60
|
+
// transition does not work with display: none
|
|
61
|
+
// tc.transition("all"),
|
|
62
|
+
tc.pb(4),
|
|
63
|
+
].flat();
|
|
64
|
+
|
|
65
|
+
export const metaAccordion: WsComponentMeta = {
|
|
66
|
+
category: "radix",
|
|
67
|
+
type: "container",
|
|
68
|
+
icon: AccordionIcon,
|
|
69
|
+
presetStyle,
|
|
70
|
+
template: [
|
|
71
|
+
{
|
|
72
|
+
type: "instance",
|
|
73
|
+
component: "Accordion",
|
|
74
|
+
dataSources: {
|
|
75
|
+
accordionValue: { type: "variable", initialValue: "0" },
|
|
76
|
+
},
|
|
77
|
+
props: [
|
|
78
|
+
{ type: "boolean", name: "collapsible", value: true },
|
|
79
|
+
{ type: "dataSource", name: "value", dataSourceName: "accordionValue" },
|
|
80
|
+
{
|
|
81
|
+
name: "onValueChange",
|
|
82
|
+
type: "action",
|
|
83
|
+
value: [
|
|
84
|
+
{
|
|
85
|
+
type: "execute",
|
|
86
|
+
args: ["value"],
|
|
87
|
+
code: `accordionValue = value`,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
children: [
|
|
93
|
+
{
|
|
94
|
+
type: "instance",
|
|
95
|
+
component: "AccordionItem",
|
|
96
|
+
styles: accordionItemStyles,
|
|
97
|
+
children: [
|
|
98
|
+
{
|
|
99
|
+
type: "instance",
|
|
100
|
+
component: "AccordionHeader",
|
|
101
|
+
styles: accordionHeaderStyles,
|
|
102
|
+
children: [
|
|
103
|
+
{
|
|
104
|
+
type: "instance",
|
|
105
|
+
component: "AccordionTrigger",
|
|
106
|
+
styles: accordionTriggerStyles,
|
|
107
|
+
children: [{ type: "text", value: "Is it accessible?" }],
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: "instance",
|
|
113
|
+
component: "AccordionContent",
|
|
114
|
+
styles: accordionContentStyles,
|
|
115
|
+
children: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
value: "Yes. It adheres to the WAI-ARIA design pattern.",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
{
|
|
126
|
+
type: "instance",
|
|
127
|
+
component: "AccordionItem",
|
|
128
|
+
styles: accordionItemStyles,
|
|
129
|
+
children: [
|
|
130
|
+
{
|
|
131
|
+
type: "instance",
|
|
132
|
+
component: "AccordionHeader",
|
|
133
|
+
styles: accordionHeaderStyles,
|
|
134
|
+
children: [
|
|
135
|
+
{
|
|
136
|
+
type: "instance",
|
|
137
|
+
component: "AccordionTrigger",
|
|
138
|
+
styles: accordionTriggerStyles,
|
|
139
|
+
children: [{ type: "text", value: "Is it styled?" }],
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: "instance",
|
|
145
|
+
component: "AccordionContent",
|
|
146
|
+
styles: accordionContentStyles,
|
|
147
|
+
children: [
|
|
148
|
+
{
|
|
149
|
+
type: "text",
|
|
150
|
+
value:
|
|
151
|
+
"Yes. It comes with default styles that matches the other components' aesthetic.",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
{
|
|
159
|
+
type: "instance",
|
|
160
|
+
component: "AccordionItem",
|
|
161
|
+
styles: accordionItemStyles,
|
|
162
|
+
children: [
|
|
163
|
+
{
|
|
164
|
+
type: "instance",
|
|
165
|
+
component: "AccordionHeader",
|
|
166
|
+
styles: accordionHeaderStyles,
|
|
167
|
+
children: [
|
|
168
|
+
{
|
|
169
|
+
type: "instance",
|
|
170
|
+
component: "AccordionTrigger",
|
|
171
|
+
styles: accordionTriggerStyles,
|
|
172
|
+
children: [{ type: "text", value: "Is it animated?" }],
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: "instance",
|
|
178
|
+
component: "AccordionContent",
|
|
179
|
+
styles: accordionContentStyles,
|
|
180
|
+
children: [
|
|
181
|
+
{
|
|
182
|
+
type: "text",
|
|
183
|
+
value:
|
|
184
|
+
"Yes. It's animated by default, but you can disable it if you prefer.",
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export const metaAccordionItem: WsComponentMeta = {
|
|
196
|
+
category: "hidden",
|
|
197
|
+
type: "container",
|
|
198
|
+
icon: ItemIcon,
|
|
199
|
+
requiredAncestors: ["Accordion"],
|
|
200
|
+
indexWithinAncestor: "Accordion",
|
|
201
|
+
presetStyle,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export const metaAccordionHeader: WsComponentMeta = {
|
|
205
|
+
category: "hidden",
|
|
206
|
+
type: "container",
|
|
207
|
+
icon: HeaderIcon,
|
|
208
|
+
requiredAncestors: ["AccordionItem"],
|
|
209
|
+
detachable: false,
|
|
210
|
+
presetStyle: {
|
|
211
|
+
h3: [h3, tc.my(0)].flat(),
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const metaAccordionTrigger: WsComponentMeta = {
|
|
216
|
+
category: "hidden",
|
|
217
|
+
type: "container",
|
|
218
|
+
icon: TriggerIcon,
|
|
219
|
+
requiredAncestors: ["AccordionHeader"],
|
|
220
|
+
detachable: false,
|
|
221
|
+
presetStyle: {
|
|
222
|
+
button: [
|
|
223
|
+
button,
|
|
224
|
+
{
|
|
225
|
+
property: "backgroundColor",
|
|
226
|
+
value: { type: "keyword", value: "transparent" },
|
|
227
|
+
} as const,
|
|
228
|
+
{
|
|
229
|
+
property: "backgroundImage",
|
|
230
|
+
value: { type: "keyword", value: "none" },
|
|
231
|
+
} as const,
|
|
232
|
+
{
|
|
233
|
+
property: "cursor",
|
|
234
|
+
value: { type: "keyword", value: "pointer" },
|
|
235
|
+
} as const,
|
|
236
|
+
tc.px(0),
|
|
237
|
+
tc.border(0),
|
|
238
|
+
].flat(),
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
export const metaAccordionContent: WsComponentMeta = {
|
|
243
|
+
category: "hidden",
|
|
244
|
+
type: "container",
|
|
245
|
+
icon: ContentIcon,
|
|
246
|
+
requiredAncestors: ["AccordionItem"],
|
|
247
|
+
detachable: false,
|
|
248
|
+
presetStyle,
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export const propsMetaAccordion: WsComponentPropsMeta = {
|
|
252
|
+
props: propsAccordion,
|
|
253
|
+
initialProps: ["value", "collapsible", "dir", "orientation"],
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
export const propsMetaAccordionItem: WsComponentPropsMeta = {
|
|
257
|
+
props: propsAccordionItem,
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export const propsMetaAccordionHeader: WsComponentPropsMeta = {
|
|
261
|
+
props: propsAccordionHeader,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export const propsMetaAccordionTrigger: WsComponentPropsMeta = {
|
|
265
|
+
props: propsAccordionTrigger,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
export const propsMetaAccordionContent: WsComponentPropsMeta = {
|
|
269
|
+
props: propsAccordionContent,
|
|
270
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { renderComponentTemplate } from "@webstudio-is/react-sdk";
|
|
3
|
+
import { Button as ButtonPrimitive } from "./button";
|
|
4
|
+
import * as baseComponents from "@webstudio-is/sdk-components-react";
|
|
5
|
+
import * as baseMetas from "@webstudio-is/sdk-components-react/metas";
|
|
6
|
+
import * as radixComponents from "./components";
|
|
7
|
+
import * as radixMetas from "./metas";
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: "Components/Button",
|
|
11
|
+
component: ButtonPrimitive,
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
options: [
|
|
15
|
+
"default",
|
|
16
|
+
"destructive",
|
|
17
|
+
"outline",
|
|
18
|
+
"secondary",
|
|
19
|
+
"ghost",
|
|
20
|
+
"link",
|
|
21
|
+
],
|
|
22
|
+
control: { type: "select" },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
} satisfies Meta<typeof ButtonPrimitive>;
|
|
26
|
+
|
|
27
|
+
export const Button: StoryObj<typeof ButtonPrimitive> = {
|
|
28
|
+
render: (props) =>
|
|
29
|
+
renderComponentTemplate({
|
|
30
|
+
name: "Button",
|
|
31
|
+
props: { ...props },
|
|
32
|
+
components: { ...baseComponents, ...radixComponents },
|
|
33
|
+
metas: { ...baseMetas, ...radixMetas },
|
|
34
|
+
}),
|
|
35
|
+
};
|
package/src/button.tsx
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
2
|
+
// We can't use .displayName until this is merged https://github.com/styleguidist/react-docgen-typescript/pull/449
|
|
3
|
+
|
|
4
|
+
import { forwardRef, type ComponentPropsWithoutRef } from "react";
|
|
5
|
+
|
|
6
|
+
type ButtonVariants = {
|
|
7
|
+
variant:
|
|
8
|
+
| "default"
|
|
9
|
+
| "destructive"
|
|
10
|
+
| "outline"
|
|
11
|
+
| "secondary"
|
|
12
|
+
| "ghost"
|
|
13
|
+
| "link";
|
|
14
|
+
|
|
15
|
+
size: "default" | "sm" | "lg" | "icon";
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const Button = forwardRef<
|
|
19
|
+
HTMLButtonElement,
|
|
20
|
+
ComponentPropsWithoutRef<"button"> & ButtonVariants
|
|
21
|
+
>(({ variant = "default", size = "default", ...props }, ref) => {
|
|
22
|
+
return (
|
|
23
|
+
<button ref={ref} data-size={size} data-variant={variant} {...props} />
|
|
24
|
+
);
|
|
25
|
+
});
|
package/src/button.ws.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { ButtonElementIcon } from "@webstudio-is/icons/svg";
|
|
2
|
+
import {
|
|
3
|
+
defaultStates,
|
|
4
|
+
EmbedTemplateInstance,
|
|
5
|
+
type PresetStyle,
|
|
6
|
+
type WsComponentMeta,
|
|
7
|
+
type WsComponentPropsMeta,
|
|
8
|
+
} from "@webstudio-is/react-sdk";
|
|
9
|
+
import { button } from "@webstudio-is/react-sdk/css-normalize";
|
|
10
|
+
import { props } from "./__generated__/button.props";
|
|
11
|
+
import * as tc from "./theme/tailwind-classes";
|
|
12
|
+
|
|
13
|
+
const presetStyle = {
|
|
14
|
+
button,
|
|
15
|
+
} satisfies PresetStyle<"button">;
|
|
16
|
+
|
|
17
|
+
export const template = (props?: {
|
|
18
|
+
props?: EmbedTemplateInstance["props"];
|
|
19
|
+
children?: WsComponentMeta["template"];
|
|
20
|
+
}): NonNullable<WsComponentMeta["template"]> => [
|
|
21
|
+
{
|
|
22
|
+
type: "instance",
|
|
23
|
+
component: "Button",
|
|
24
|
+
styles: [
|
|
25
|
+
// 'inline-flex items-center justify-center rounded-md text-sm font-medium
|
|
26
|
+
// ring-offset-background transition-colors
|
|
27
|
+
// focus-visible:outline-none focus-visible:ring-2
|
|
28
|
+
// focus-visible:ring-ring focus-visible:ring-offset-2
|
|
29
|
+
// disabled:pointer-events-none disabled:opacity-50'
|
|
30
|
+
tc.border(0),
|
|
31
|
+
tc.bg("transparent"),
|
|
32
|
+
tc.inlineFlex(),
|
|
33
|
+
tc.items("center"),
|
|
34
|
+
tc.justify("center"),
|
|
35
|
+
tc.rounded("md"),
|
|
36
|
+
tc.text("sm"),
|
|
37
|
+
tc.font("medium"),
|
|
38
|
+
tc.focusVisible(
|
|
39
|
+
[tc.outline("none"), tc.ring("ring", 2, "background", 2)].flat()
|
|
40
|
+
),
|
|
41
|
+
tc.state([tc.pointerEvents("none"), tc.opacity(50)].flat(), ":disabled"),
|
|
42
|
+
|
|
43
|
+
// VARIANT
|
|
44
|
+
// default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
45
|
+
tc.state(
|
|
46
|
+
[tc.bg("primary"), tc.text("primaryForeground")].flat(),
|
|
47
|
+
"[data-variant=default]"
|
|
48
|
+
),
|
|
49
|
+
tc.state(
|
|
50
|
+
[[tc.bg("primary", 90)].flat()].flat(),
|
|
51
|
+
"[data-variant=default]:hover"
|
|
52
|
+
),
|
|
53
|
+
|
|
54
|
+
// destructive:'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
55
|
+
tc.state(
|
|
56
|
+
[tc.bg("destructive"), tc.text("destructiveForeground")].flat(),
|
|
57
|
+
"[data-variant=destructive]"
|
|
58
|
+
),
|
|
59
|
+
tc.state(
|
|
60
|
+
[[tc.bg("destructive", 90)].flat()].flat(),
|
|
61
|
+
"[data-variant=destructive]:hover"
|
|
62
|
+
),
|
|
63
|
+
|
|
64
|
+
// outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
65
|
+
tc.state(
|
|
66
|
+
[tc.border(), tc.border("input"), tc.bg("background")].flat(),
|
|
67
|
+
"[data-variant=outline]"
|
|
68
|
+
),
|
|
69
|
+
tc.state(
|
|
70
|
+
[[tc.bg("accent", 90), tc.text("accentForeground")].flat()].flat(),
|
|
71
|
+
"[data-variant=outline]:hover"
|
|
72
|
+
),
|
|
73
|
+
|
|
74
|
+
// secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
75
|
+
tc.state(
|
|
76
|
+
[tc.bg("secondary"), tc.text("secondaryForeground")].flat(),
|
|
77
|
+
"[data-variant=secondary]"
|
|
78
|
+
),
|
|
79
|
+
tc.state(
|
|
80
|
+
[[tc.bg("secondary", 80)].flat()].flat(),
|
|
81
|
+
"[data-variant=secondary]:hover"
|
|
82
|
+
),
|
|
83
|
+
|
|
84
|
+
// ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
85
|
+
tc.state(
|
|
86
|
+
[[tc.bg("accent"), tc.text("accentForeground")].flat()].flat(),
|
|
87
|
+
"[data-variant=ghost]:hover"
|
|
88
|
+
),
|
|
89
|
+
|
|
90
|
+
// link: 'text-primary underline-offset-4 hover:underline',
|
|
91
|
+
tc.state(
|
|
92
|
+
[tc.text("primary"), tc.underlineOffset(4)].flat(),
|
|
93
|
+
"[data-variant=link]"
|
|
94
|
+
),
|
|
95
|
+
tc.state([[tc.underline()].flat()].flat(), "[data-variant=link]:hover"),
|
|
96
|
+
|
|
97
|
+
// SIZE
|
|
98
|
+
// default: 'h-10 px-4 py-2',
|
|
99
|
+
tc.state([tc.h(10), tc.px(4), tc.py(2)].flat(), "[data-size=default]"),
|
|
100
|
+
|
|
101
|
+
// sm: 'h-9 rounded-md px-3',
|
|
102
|
+
tc.state([tc.h(10), tc.px(3)].flat(), "[data-size=sm]"),
|
|
103
|
+
|
|
104
|
+
// lg: 'h-11 rounded-md px-8',
|
|
105
|
+
tc.state([tc.h(11), tc.px(8)].flat(), "[data-size=lg]"),
|
|
106
|
+
|
|
107
|
+
// icon: 'h-10 w-10',
|
|
108
|
+
tc.state([tc.h(10), tc.w(10)].flat(), "[data-size=icon]"),
|
|
109
|
+
].flat(),
|
|
110
|
+
|
|
111
|
+
children: props?.children ?? [{ type: "text", value: "Button" }],
|
|
112
|
+
props: props?.props,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
export const meta: WsComponentMeta = {
|
|
117
|
+
category: "radix",
|
|
118
|
+
type: "container",
|
|
119
|
+
invalidAncestors: ["Button"],
|
|
120
|
+
icon: ButtonElementIcon,
|
|
121
|
+
presetStyle,
|
|
122
|
+
states: [
|
|
123
|
+
...defaultStates,
|
|
124
|
+
{ selector: ":disabled", label: "Disabled" },
|
|
125
|
+
{ selector: ":enabled", label: "Enabled" },
|
|
126
|
+
|
|
127
|
+
{ selector: "[data-variant=default]", label: "Default" },
|
|
128
|
+
{ selector: "[data-variant=default]:hover", label: "Default Hover" },
|
|
129
|
+
|
|
130
|
+
{ selector: "[data-variant=destructive]", label: "Destructive" },
|
|
131
|
+
{
|
|
132
|
+
selector: "[data-variant=destructive]:hover",
|
|
133
|
+
label: "Destructive Hover",
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
{ selector: "[data-variant=outline]", label: "Outline" },
|
|
137
|
+
{ selector: "[data-variant=outline]:hover", label: "Outline Hover" },
|
|
138
|
+
|
|
139
|
+
{ selector: "[data-variant=secondary]", label: "Secondary" },
|
|
140
|
+
{ selector: "[data-variant=secondary]:hover", label: "Secondary Hover" },
|
|
141
|
+
|
|
142
|
+
{ selector: "[data-variant=ghost]", label: "Ghost" },
|
|
143
|
+
{ selector: "[data-variant=ghost]:hover", label: "Ghost Hover" },
|
|
144
|
+
|
|
145
|
+
{ selector: "[data-variant=link]", label: "Link" },
|
|
146
|
+
{ selector: "[data-variant=link]:hover", label: "Link Hover" },
|
|
147
|
+
],
|
|
148
|
+
order: 1,
|
|
149
|
+
template: template(),
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export const propsMeta: WsComponentPropsMeta = {
|
|
153
|
+
props,
|
|
154
|
+
initialProps: ["id", "type", "variant", "size", "aria-label"],
|
|
155
|
+
};
|
package/src/collapsible.tsx
CHANGED
|
@@ -45,25 +45,11 @@ const namespace = "@webstudio-is/sdk-components-react-radix";
|
|
|
45
45
|
// we identify its closest parent Collapsible component
|
|
46
46
|
// and update its open prop bound to variable.
|
|
47
47
|
export const hooksCollapsible: Hook = {
|
|
48
|
-
onNavigatorUnselect: (context, event) => {
|
|
49
|
-
for (const instance of event.instanceSelection) {
|
|
50
|
-
if (instance.component === `${namespace}:CollapsibleContent`) {
|
|
51
|
-
const collapsible = getClosestInstance(
|
|
52
|
-
event.instanceSelection,
|
|
53
|
-
instance,
|
|
54
|
-
`${namespace}:Collapsible`
|
|
55
|
-
);
|
|
56
|
-
if (collapsible) {
|
|
57
|
-
context.setPropVariable(collapsible.id, "open", false);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
48
|
onNavigatorSelect: (context, event) => {
|
|
63
|
-
for (const instance of event.
|
|
49
|
+
for (const instance of event.instancePath) {
|
|
64
50
|
if (instance.component === `${namespace}:CollapsibleContent`) {
|
|
65
51
|
const collapsible = getClosestInstance(
|
|
66
|
-
event.
|
|
52
|
+
event.instancePath,
|
|
67
53
|
instance,
|
|
68
54
|
`${namespace}:Collapsible`
|
|
69
55
|
);
|
package/src/collapsible.ws.ts
CHANGED
|
@@ -23,7 +23,6 @@ export const metaCollapsible: WsComponentMeta = {
|
|
|
23
23
|
category: "radix",
|
|
24
24
|
type: "container",
|
|
25
25
|
presetStyle,
|
|
26
|
-
label: "Collapsible",
|
|
27
26
|
icon: CollapsibleIcon,
|
|
28
27
|
template: [
|
|
29
28
|
{
|
|
@@ -42,11 +41,7 @@ export const metaCollapsible: WsComponentMeta = {
|
|
|
42
41
|
name: "onOpenChange",
|
|
43
42
|
type: "action",
|
|
44
43
|
value: [
|
|
45
|
-
{
|
|
46
|
-
type: "execute",
|
|
47
|
-
args: ["open"],
|
|
48
|
-
code: `collapsibleOpen = open`,
|
|
49
|
-
},
|
|
44
|
+
{ type: "execute", args: ["open"], code: `collapsibleOpen = open` },
|
|
50
45
|
],
|
|
51
46
|
},
|
|
52
47
|
],
|
|
@@ -81,7 +76,6 @@ export const metaCollapsible: WsComponentMeta = {
|
|
|
81
76
|
export const metaCollapsibleTrigger: WsComponentMeta = {
|
|
82
77
|
category: "hidden",
|
|
83
78
|
type: "container",
|
|
84
|
-
label: "Collapsible Trigger",
|
|
85
79
|
icon: TriggerIcon,
|
|
86
80
|
stylable: false,
|
|
87
81
|
detachable: false,
|
|
@@ -91,7 +85,6 @@ export const metaCollapsibleContent: WsComponentMeta = {
|
|
|
91
85
|
category: "hidden",
|
|
92
86
|
type: "container",
|
|
93
87
|
presetStyle,
|
|
94
|
-
label: "Collapsible Content",
|
|
95
88
|
icon: ContentIcon,
|
|
96
89
|
detachable: false,
|
|
97
90
|
};
|
package/src/components.ts
CHANGED
|
@@ -24,3 +24,14 @@ export {
|
|
|
24
24
|
SheetDescription,
|
|
25
25
|
} from "./sheet";
|
|
26
26
|
export { Tabs, TabsList, TabsTrigger, TabsContent } from "./tabs";
|
|
27
|
+
export { Button } from "./button";
|
|
28
|
+
export { Input } from "./input";
|
|
29
|
+
export { Textarea } from "./textarea";
|
|
30
|
+
export { Label } from "./label";
|
|
31
|
+
export {
|
|
32
|
+
Accordion,
|
|
33
|
+
AccordionItem,
|
|
34
|
+
AccordionHeader,
|
|
35
|
+
AccordionTrigger,
|
|
36
|
+
AccordionContent,
|
|
37
|
+
} from "./accordion";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { renderComponentTemplate } from "@webstudio-is/react-sdk";
|
|
3
|
+
import { Dialog as DialogPrimitive } from "./dialog";
|
|
4
|
+
import * as baseComponents from "@webstudio-is/sdk-components-react";
|
|
5
|
+
import * as baseMetas from "@webstudio-is/sdk-components-react/metas";
|
|
6
|
+
import * as radixComponents from "./components";
|
|
7
|
+
import * as radixMetas from "./metas";
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: "Components/Dialog",
|
|
11
|
+
component: DialogPrimitive,
|
|
12
|
+
} satisfies Meta<typeof DialogPrimitive>;
|
|
13
|
+
|
|
14
|
+
export const Dialog: StoryObj<typeof DialogPrimitive> = {
|
|
15
|
+
render: () =>
|
|
16
|
+
renderComponentTemplate({
|
|
17
|
+
name: "Dialog",
|
|
18
|
+
components: { ...baseComponents, ...radixComponents },
|
|
19
|
+
metas: { ...baseMetas, ...radixMetas },
|
|
20
|
+
}),
|
|
21
|
+
};
|
package/src/dialog.tsx
CHANGED
|
@@ -1,33 +1,21 @@
|
|
|
1
1
|
/* eslint-disable react/display-name */
|
|
2
2
|
// We can't use .displayName until this is merged https://github.com/styleguidist/react-docgen-typescript/pull/449
|
|
3
3
|
|
|
4
|
-
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
5
|
-
|
|
6
4
|
import {
|
|
7
|
-
forwardRef,
|
|
8
|
-
type ElementRef,
|
|
9
5
|
type ComponentPropsWithoutRef,
|
|
10
|
-
Children,
|
|
11
6
|
type ReactNode,
|
|
7
|
+
forwardRef,
|
|
8
|
+
Children,
|
|
12
9
|
} from "react";
|
|
10
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
11
|
+
import { getClosestInstance, type Hook } from "@webstudio-is/react-sdk";
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
* We don't have support for boolean or undefined nor in UI not at Data variables,
|
|
16
|
-
* instead of binding on "open" prop we bind variable on a isOpen prop to be able to show Dialog in the builder
|
|
17
|
-
**/
|
|
18
|
-
type BuilderDialogProps = {
|
|
19
|
-
isOpen: "initial" | "open" | "closed";
|
|
20
|
-
};
|
|
21
|
-
|
|
13
|
+
// wrap in forwardRef because Root is functional component without ref
|
|
22
14
|
export const Dialog = forwardRef<
|
|
23
|
-
|
|
24
|
-
ComponentPropsWithoutRef<typeof DialogPrimitive.Root>
|
|
25
|
-
>((
|
|
26
|
-
|
|
27
|
-
openProp ??
|
|
28
|
-
(isOpen === "open" ? true : isOpen === "closed" ? false : undefined);
|
|
29
|
-
|
|
30
|
-
return <DialogPrimitive.Root open={open} {...props} />;
|
|
15
|
+
HTMLDivElement,
|
|
16
|
+
Omit<ComponentPropsWithoutRef<typeof DialogPrimitive.Root>, "defaultOpen">
|
|
17
|
+
>((props, _ref) => {
|
|
18
|
+
return <DialogPrimitive.Root {...props} />;
|
|
31
19
|
});
|
|
32
20
|
|
|
33
21
|
/**
|
|
@@ -37,20 +25,20 @@ export const Dialog = forwardRef<
|
|
|
37
25
|
* which would prevent us from displaying styles properly in the builder.
|
|
38
26
|
*/
|
|
39
27
|
export const DialogTrigger = forwardRef<
|
|
40
|
-
|
|
28
|
+
HTMLButtonElement,
|
|
41
29
|
{ children: ReactNode }
|
|
42
30
|
>(({ children, ...props }, ref) => {
|
|
43
31
|
const firstChild = Children.toArray(children)[0];
|
|
44
32
|
|
|
45
33
|
return (
|
|
46
|
-
<DialogPrimitive.Trigger asChild={true} {...props}>
|
|
34
|
+
<DialogPrimitive.Trigger ref={ref} asChild={true} {...props}>
|
|
47
35
|
{firstChild ?? <button>Add button or link</button>}
|
|
48
36
|
</DialogPrimitive.Trigger>
|
|
49
37
|
);
|
|
50
38
|
});
|
|
51
39
|
|
|
52
40
|
export const DialogOverlay = forwardRef<
|
|
53
|
-
|
|
41
|
+
HTMLDivElement,
|
|
54
42
|
ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
55
43
|
>((props, ref) => {
|
|
56
44
|
return (
|
|
@@ -64,3 +52,41 @@ export const DialogContent = DialogPrimitive.Content;
|
|
|
64
52
|
export const DialogClose = DialogPrimitive.Close;
|
|
65
53
|
export const DialogTitle = DialogPrimitive.Title;
|
|
66
54
|
export const DialogDescription = DialogPrimitive.Description;
|
|
55
|
+
|
|
56
|
+
/* BUILDER HOOKS */
|
|
57
|
+
|
|
58
|
+
const namespace = "@webstudio-is/sdk-components-react-radix";
|
|
59
|
+
|
|
60
|
+
// For each DialogOverlay component within the selection,
|
|
61
|
+
// we identify its closest parent Dialog component
|
|
62
|
+
// and update its open prop bound to variable.
|
|
63
|
+
export const hooksDialog: Hook = {
|
|
64
|
+
onNavigatorUnselect: (context, event) => {
|
|
65
|
+
for (const instance of event.instancePath) {
|
|
66
|
+
if (instance.component === `${namespace}:DialogOverlay`) {
|
|
67
|
+
const dialog = getClosestInstance(
|
|
68
|
+
event.instancePath,
|
|
69
|
+
instance,
|
|
70
|
+
`${namespace}:Dialog`
|
|
71
|
+
);
|
|
72
|
+
if (dialog) {
|
|
73
|
+
context.setPropVariable(dialog.id, "open", false);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
onNavigatorSelect: (context, event) => {
|
|
79
|
+
for (const instance of event.instancePath) {
|
|
80
|
+
if (instance.component === `${namespace}:DialogOverlay`) {
|
|
81
|
+
const dialog = getClosestInstance(
|
|
82
|
+
event.instancePath,
|
|
83
|
+
instance,
|
|
84
|
+
`${namespace}:Dialog`
|
|
85
|
+
);
|
|
86
|
+
if (dialog) {
|
|
87
|
+
context.setPropVariable(dialog.id, "open", true);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|