@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.
Files changed (149) hide show
  1. package/lib/__generated__/accordion.props.js +2134 -0
  2. package/lib/__generated__/button.props.js +454 -0
  3. package/lib/__generated__/dialog.props.js +0 -7
  4. package/lib/__generated__/input.props.js +451 -0
  5. package/lib/__generated__/label.props.js +421 -0
  6. package/lib/__generated__/popover.props.js +0 -7
  7. package/lib/__generated__/sheet.props.js +0 -7
  8. package/lib/__generated__/textarea.props.js +431 -0
  9. package/lib/__generated__/tooltip.props.js +0 -7
  10. package/lib/accordion.js +51 -0
  11. package/lib/accordion.ws.js +243 -0
  12. package/lib/button.js +8 -0
  13. package/lib/button.ws.js +133 -0
  14. package/lib/cjs/__generated__/accordion.props.js +2154 -0
  15. package/lib/cjs/__generated__/button.props.js +474 -0
  16. package/lib/cjs/__generated__/dialog.props.js +0 -7
  17. package/lib/cjs/__generated__/input.props.js +471 -0
  18. package/lib/cjs/__generated__/label.props.js +441 -0
  19. package/lib/cjs/__generated__/popover.props.js +0 -7
  20. package/lib/cjs/__generated__/sheet.props.js +0 -7
  21. package/lib/cjs/__generated__/textarea.props.js +451 -0
  22. package/lib/cjs/__generated__/tooltip.props.js +0 -7
  23. package/lib/cjs/accordion.js +60 -0
  24. package/lib/cjs/accordion.ws.js +261 -0
  25. package/lib/cjs/button.js +28 -0
  26. package/lib/cjs/button.ws.js +160 -0
  27. package/lib/cjs/collapsible.js +2 -16
  28. package/lib/cjs/collapsible.ws.js +1 -8
  29. package/lib/cjs/components.js +14 -0
  30. package/lib/cjs/dialog.js +38 -6
  31. package/lib/cjs/dialog.ws.js +15 -26
  32. package/lib/cjs/hooks.js +15 -1
  33. package/lib/cjs/input.js +28 -0
  34. package/lib/cjs/input.ws.js +103 -0
  35. package/lib/cjs/label.js +37 -0
  36. package/lib/cjs/label.ws.js +74 -0
  37. package/lib/cjs/metas.js +14 -0
  38. package/lib/cjs/popover.js +37 -5
  39. package/lib/cjs/popover.ws.js +15 -18
  40. package/lib/cjs/props.js +14 -0
  41. package/lib/cjs/sheet.js +34 -1
  42. package/lib/cjs/sheet.ws.js +33 -19
  43. package/lib/cjs/tabs.js +20 -1
  44. package/lib/cjs/tabs.ws.js +3 -25
  45. package/lib/cjs/textarea.js +28 -0
  46. package/lib/cjs/textarea.ws.js +98 -0
  47. package/lib/cjs/theme/tailwind-classes.js +186 -23
  48. package/lib/cjs/theme/tailwind-colors.js +10 -1
  49. package/lib/cjs/tooltip.js +36 -4
  50. package/lib/cjs/tooltip.ws.js +15 -18
  51. package/lib/collapsible.js +2 -16
  52. package/lib/collapsible.ws.js +1 -8
  53. package/lib/components.js +20 -0
  54. package/lib/dialog.js +38 -6
  55. package/lib/dialog.ws.js +15 -26
  56. package/lib/hooks.js +15 -1
  57. package/lib/input.js +8 -0
  58. package/lib/input.ws.js +75 -0
  59. package/lib/label.js +9 -0
  60. package/lib/label.ws.js +46 -0
  61. package/lib/metas.js +20 -0
  62. package/lib/popover.js +37 -5
  63. package/lib/popover.ws.js +15 -18
  64. package/lib/props.js +20 -0
  65. package/lib/sheet.js +34 -1
  66. package/lib/sheet.ws.js +33 -19
  67. package/lib/tabs.js +24 -2
  68. package/lib/tabs.ws.js +3 -25
  69. package/lib/textarea.js +8 -0
  70. package/lib/textarea.ws.js +70 -0
  71. package/lib/theme/tailwind-classes.js +191 -24
  72. package/lib/theme/tailwind-colors.js +10 -1
  73. package/lib/tooltip.js +36 -4
  74. package/lib/tooltip.ws.js +15 -18
  75. package/lib/types/__generated__/accordion.props.d.ts +6 -0
  76. package/lib/types/__generated__/button.props.d.ts +2 -0
  77. package/lib/types/__generated__/input.props.d.ts +2 -0
  78. package/lib/types/__generated__/label.props.d.ts +2 -0
  79. package/lib/types/__generated__/textarea.props.d.ts +2 -0
  80. package/lib/types/accordion.d.ts +12 -0
  81. package/lib/types/accordion.ws.d.ts +11 -0
  82. package/lib/types/button.d.ts +7 -0
  83. package/lib/types/button.stories.d.ts +20 -0
  84. package/lib/types/button.ws.d.ts +7 -0
  85. package/lib/types/components.d.ts +5 -0
  86. package/lib/types/dialog.d.ts +5 -11
  87. package/lib/types/input.d.ts +2 -0
  88. package/lib/types/input.stories.d.ts +20 -0
  89. package/lib/types/input.ws.d.ts +3 -0
  90. package/lib/types/label.d.ts +3 -0
  91. package/lib/types/label.stories.d.ts +9 -0
  92. package/lib/types/label.ws.d.ts +3 -0
  93. package/lib/types/metas.d.ts +5 -0
  94. package/lib/types/popover.d.ts +4 -10
  95. package/lib/types/props.d.ts +5 -0
  96. package/lib/types/sheet.d.ts +4 -4
  97. package/lib/types/tabs.d.ts +2 -0
  98. package/lib/types/textarea.d.ts +2 -0
  99. package/lib/types/textarea.stories.d.ts +14 -0
  100. package/lib/types/textarea.ws.d.ts +3 -0
  101. package/lib/types/theme/tailwind-classes.d.ts +16 -5
  102. package/lib/types/theme/tailwind-colors.d.ts +9 -0
  103. package/lib/types/tooltip.d.ts +3 -9
  104. package/package.json +9 -7
  105. package/src/__generated__/accordion.props.ts +2382 -0
  106. package/src/__generated__/button.props.ts +503 -0
  107. package/src/__generated__/dialog.props.ts +0 -7
  108. package/src/__generated__/input.props.ts +500 -0
  109. package/src/__generated__/label.props.ts +470 -0
  110. package/src/__generated__/popover.props.ts +0 -7
  111. package/src/__generated__/sheet.props.ts +0 -7
  112. package/src/__generated__/textarea.props.ts +480 -0
  113. package/src/__generated__/tooltip.props.ts +0 -7
  114. package/src/accordion.stories.tsx +21 -0
  115. package/src/accordion.tsx +81 -0
  116. package/src/accordion.ws.ts +270 -0
  117. package/src/button.stories.ts +35 -0
  118. package/src/button.tsx +25 -0
  119. package/src/button.ws.ts +155 -0
  120. package/src/collapsible.tsx +2 -16
  121. package/src/collapsible.ws.ts +1 -8
  122. package/src/components.ts +11 -0
  123. package/src/dialog.stories.tsx +21 -0
  124. package/src/dialog.tsx +50 -24
  125. package/src/dialog.ws.tsx +15 -26
  126. package/src/hooks.ts +15 -1
  127. package/src/input.stories.ts +31 -0
  128. package/src/input.tsx +12 -0
  129. package/src/input.ws.ts +78 -0
  130. package/src/label.stories.ts +22 -0
  131. package/src/label.tsx +15 -0
  132. package/src/label.ws.ts +48 -0
  133. package/src/metas.ts +11 -0
  134. package/src/popover.stories.tsx +21 -0
  135. package/src/popover.tsx +49 -23
  136. package/src/popover.ws.tsx +15 -18
  137. package/src/props.ts +11 -0
  138. package/src/sheet.tsx +39 -0
  139. package/src/sheet.ws.tsx +33 -19
  140. package/src/tabs.tsx +32 -1
  141. package/src/tabs.ws.ts +1 -23
  142. package/src/textarea.stories.ts +27 -0
  143. package/src/textarea.tsx +12 -0
  144. package/src/textarea.ws.ts +74 -0
  145. package/src/theme/tailwind-classes.ts +233 -38
  146. package/src/theme/tailwind-colors.ts +9 -16
  147. package/src/tooltip.stories.tsx +21 -0
  148. package/src/tooltip.tsx +46 -20
  149. 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
+ });
@@ -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
+ };
@@ -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.instanceSelection) {
49
+ for (const instance of event.instancePath) {
64
50
  if (instance.component === `${namespace}:CollapsibleContent`) {
65
51
  const collapsible = getClosestInstance(
66
- event.instanceSelection,
52
+ event.instancePath,
67
53
  instance,
68
54
  `${namespace}:Collapsible`
69
55
  );
@@ -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
- ElementRef<"div">,
24
- ComponentPropsWithoutRef<typeof DialogPrimitive.Root> & BuilderDialogProps
25
- >(({ open: openProp, isOpen, ...props }, ref) => {
26
- const open =
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
- ElementRef<"div">,
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
- ElementRef<"div">,
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
+ };