@valbuild/ui 0.26.0 → 0.28.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/dist/valbuild-ui.cjs.js +41 -15
- package/dist/valbuild-ui.esm.js +41 -15
- package/package.json +7 -3
- package/server/.tmp/assets/index-18cfa26c.css +1 -0
- package/server/.tmp/assets/index-513f7a9c.js +197 -0
- package/{index.html → server/.tmp/index.html} +3 -1
- package/server/dist/style.css +0 -3
- package/server/dist/valbuild-ui-main.cjs.js +60 -34
- package/server/dist/valbuild-ui-main.esm.js +60 -34
- package/server/dist/valbuild-ui-server.cjs.js +1 -1
- package/server/dist/valbuild-ui-server.esm.js +1 -1
- package/.babelrc.json +0 -10
- package/.storybook/main.js +0 -25
- package/.storybook/preview-head.html +0 -6
- package/.storybook/preview.js +0 -33
- package/.storybook/theme.css +0 -34
- package/CHANGELOG.md +0 -0
- package/components.json +0 -16
- package/fix-server-hack.js +0 -54
- package/fullscreen.vite.config.ts +0 -9
- package/jest.config.js +0 -4
- package/postcss.config.js +0 -6
- package/rollup.config.js +0 -23
- package/server.vite.config.ts +0 -31
- package/src/App.tsx +0 -73
- package/src/assets/icons/Bold.tsx +0 -23
- package/src/assets/icons/Chevron.tsx +0 -28
- package/src/assets/icons/FontColor.tsx +0 -30
- package/src/assets/icons/ImageIcon.tsx +0 -29
- package/src/assets/icons/Italic.tsx +0 -24
- package/src/assets/icons/Logo.tsx +0 -103
- package/src/assets/icons/Section.tsx +0 -41
- package/src/assets/icons/Strikethrough.tsx +0 -22
- package/src/assets/icons/TextIcon.tsx +0 -20
- package/src/assets/icons/Underline.tsx +0 -22
- package/src/assets/icons/Undo.tsx +0 -20
- package/src/components/Button.tsx +0 -68
- package/src/components/Checkbox.tsx +0 -51
- package/src/components/DraggableList.stories.tsx +0 -20
- package/src/components/DraggableList.tsx +0 -95
- package/src/components/Dropdown.tsx +0 -101
- package/src/components/EditButton.tsx +0 -10
- package/src/components/ErrorText.tsx +0 -3
- package/src/components/ExpandLogo.tsx +0 -72
- package/src/components/Grid.stories.tsx +0 -43
- package/src/components/Grid.tsx +0 -139
- package/src/components/RichTextEditor/ContentEditable.tsx +0 -117
- package/src/components/RichTextEditor/Nodes/ImageNode.tsx +0 -100
- package/src/components/RichTextEditor/Plugins/AutoFocus.tsx +0 -12
- package/src/components/RichTextEditor/Plugins/ImagePlugin.tsx +0 -45
- package/src/components/RichTextEditor/Plugins/LinkEditorPlugin.tsx +0 -58
- package/src/components/RichTextEditor/Plugins/Toolbar.tsx +0 -412
- package/src/components/RichTextEditor/RichTextEditor.tsx +0 -105
- package/src/components/UploadModal.tsx +0 -109
- package/src/components/User.tsx +0 -17
- package/src/components/ValFormField.tsx +0 -574
- package/src/components/ValFullscreen.tsx +0 -1278
- package/src/components/ValMenu.tsx +0 -92
- package/src/components/ValOverlay.tsx +0 -488
- package/src/components/ValOverlayContext.tsx +0 -80
- package/src/components/ValWindow.stories.tsx +0 -146
- package/src/components/ValWindow.tsx +0 -220
- package/src/components/dashboard/DashboardButton.tsx +0 -25
- package/src/components/dashboard/DashboardDropdown.tsx +0 -59
- package/src/components/dashboard/Dropdown.stories.tsx +0 -11
- package/src/components/dashboard/Dropdown.tsx +0 -70
- package/src/components/dashboard/FormGroup.stories.tsx +0 -37
- package/src/components/dashboard/FormGroup.tsx +0 -42
- package/src/components/dashboard/Grid2.stories.tsx +0 -56
- package/src/components/dashboard/Grid2.tsx +0 -72
- package/src/components/dashboard/Tree.stories.tsx +0 -91
- package/src/components/dashboard/Tree.tsx +0 -72
- package/src/components/dashboard/ValDashboardEditor.tsx +0 -269
- package/src/components/dashboard/ValDashboardGrid.tsx +0 -142
- package/src/components/dashboard/ValTreeNavigator.tsx +0 -253
- package/src/components/forms/Form.tsx +0 -126
- package/src/components/forms/FormContainer.tsx +0 -24
- package/src/components/forms/ImageForm.tsx +0 -195
- package/src/components/forms/TextArea.tsx +0 -24
- package/src/components/ui/accordion.tsx +0 -58
- package/src/components/ui/alert-dialog.tsx +0 -139
- package/src/components/ui/avatar.tsx +0 -48
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/calendar.tsx +0 -62
- package/src/components/ui/card.tsx +0 -86
- package/src/components/ui/checkbox.tsx +0 -28
- package/src/components/ui/command.tsx +0 -153
- package/src/components/ui/dialog.tsx +0 -120
- package/src/components/ui/dropdown-menu.tsx +0 -198
- package/src/components/ui/form.tsx +0 -177
- package/src/components/ui/input.tsx +0 -24
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/popover.tsx +0 -29
- package/src/components/ui/progress.tsx +0 -26
- package/src/components/ui/radio-group.tsx +0 -42
- package/src/components/ui/scroll-area.tsx +0 -51
- package/src/components/ui/select.tsx +0 -119
- package/src/components/ui/switch.tsx +0 -27
- package/src/components/ui/tabs.tsx +0 -53
- package/src/components/ui/toggle.tsx +0 -43
- package/src/components/ui/tooltip.tsx +0 -28
- package/src/components/usePatch.ts +0 -86
- package/src/components/useTheme.ts +0 -45
- package/src/dto/SerializedSchema.ts +0 -69
- package/src/dto/Session.ts +0 -12
- package/src/dto/SessionMode.ts +0 -5
- package/src/dto/Tree.ts +0 -18
- package/src/exports.ts +0 -6
- package/src/index.css +0 -115
- package/src/index.tsx +0 -14
- package/src/lib/IValStore.ts +0 -6
- package/src/lib/utils.ts +0 -6
- package/src/main.jsx +0 -10
- package/src/richtext/conversion/conversion.test.ts +0 -146
- package/src/richtext/conversion/lexicalToRichTextSource.test.ts +0 -89
- package/src/richtext/conversion/lexicalToRichTextSource.ts +0 -285
- package/src/richtext/conversion/parseRichTextSource.test.ts +0 -469
- package/src/richtext/conversion/parseRichTextSource.ts +0 -233
- package/src/richtext/conversion/richTextSourceToLexical.test.ts +0 -381
- package/src/richtext/conversion/richTextSourceToLexical.ts +0 -293
- package/src/richtext/shadowRootPolyFill.js +0 -115
- package/src/server.ts +0 -70
- package/src/stories/Button.stories.tsx +0 -20
- package/src/stories/Checkbox.stories.tsx +0 -14
- package/src/stories/Dropdown.stories.tsx +0 -23
- package/src/stories/Introduction.mdx +0 -221
- package/src/stories/RichTextEditor.stories.tsx +0 -24
- package/src/stories/assets/code-brackets.svg +0 -1
- package/src/stories/assets/colors.svg +0 -1
- package/src/stories/assets/comments.svg +0 -1
- package/src/stories/assets/direction.svg +0 -1
- package/src/stories/assets/flow.svg +0 -1
- package/src/stories/assets/plugin.svg +0 -1
- package/src/stories/assets/repo.svg +0 -1
- package/src/stories/assets/stackalt.svg +0 -1
- package/src/utils/Remote.ts +0 -15
- package/src/utils/imageMimeType.ts +0 -23
- package/src/utils/readImage.ts +0 -54
- package/src/utils/resolvePath.ts +0 -32
- package/src/vite-env.d.ts +0 -1
- package/src/vite-index.tsx +0 -7
- package/src/vite-server.ts +0 -42
- package/tailwind.config.js +0 -83
- package/tsconfig.json +0 -19
- package/vite.config.ts +0 -43
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { RichTextEditor } from "../exports";
|
|
3
|
-
import { FormContainer } from "./forms/FormContainer";
|
|
4
|
-
import { ImageForm } from "./forms/ImageForm";
|
|
5
|
-
import { TextArea } from "./forms/TextArea";
|
|
6
|
-
|
|
7
|
-
import { ValWindow } from "./ValWindow";
|
|
8
|
-
|
|
9
|
-
const meta: Meta<typeof ValWindow> = { component: ValWindow };
|
|
10
|
-
|
|
11
|
-
export default meta;
|
|
12
|
-
type Story = StoryObj<typeof ValWindow>;
|
|
13
|
-
|
|
14
|
-
const EXAMPLE_IMAGE =
|
|
15
|
-
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAFgAWAAD/4QDkRXhpZgAASUkqAAgAAAAJABIBAwABAAAAAQAAABoBBQABAAAAegAAABsBBQABAAAAggAAACgBAwABAAAAAgAAADEBAgANAAAAigAAADIBAgAUAAAAmAAAAGmHBAABAAAAygAAAHySAgAHAAAArAAAAIaSAgAWAAAAtAAAAAAAAAAWAAAAAQAAABYAAAABAAAAR0lNUCAyLjEwLjM0AAAyMDIzOjA1OjI0IDE0OjQ3OjA1AE9wZW5BSQAATWFkZSB3aXRoIE9wZW5BSSBMYWJzAAEAAaADAAEAAAABAAAAAAAAAP/hDM9odHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6R0lNUD0iaHR0cDovL3d3dy5naW1wLm9yZy94bXAvIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDo1NDk5MWU4Yy01YjkxLTQwYWYtYjk4ZC00ZjEwMWYwY2QxZWQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Y2JmMjFlNjMtNGZiYi00MjI5LThlM2UtN2MzMWI0ZDNiNWFhIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6YzQ3ZWZmNDktNzg4Yy00NzdjLWJkNTEtZGM5YzJjYTY4NzBjIiBkYzpGb3JtYXQ9ImltYWdlL2pwZWciIEdJTVA6QVBJPSIyLjAiIEdJTVA6UGxhdGZvcm09IkxpbnV4IiBHSU1QOlRpbWVTdGFtcD0iMTY4NDkzMjQyNzk4NDA2MCIgR0lNUDpWZXJzaW9uPSIyLjEwLjM0IiB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMzowNToyNFQxNDo0NzowNSswMjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjM6MDU6MjRUMTQ6NDc6MDUrMDI6MDAiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6Y2hhbmdlZD0iLyIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxNjIyMWEyMS0wZmMzLTQ1NmEtOWZlOC1hOTAyMmY0NjBhOTEiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkdpbXAgMi4xMCAoTGludXgpIiBzdEV2dDp3aGVuPSIyMDIzLTA1LTI0VDE0OjQ3OjA3KzAyOjAwIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/+ICsElDQ19QUk9GSUxFAAEBAAACoGxjbXMEQAAAbW50clJHQiBYWVogB+cABQAYAAwALQAJYWNzcEFQUEwAAAAAAAAA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";
|
|
16
|
-
const EXAMPLE_TEXT = `
|
|
17
|
-
Vi gjør mange ting sammen i Blank, men det vi lever av er å designe og utvikle digitale tjenester for kundene våre.
|
|
18
|
-
|
|
19
|
-
Noen av selskapene vi jobber med er små, andre er store. Alle har de høye ambisjoner for sine digitale løsninger, og stiller høye krav til hvem de jobber med.
|
|
20
|
-
|
|
21
|
-
Noen ganger starter vi nye, egne, selskaper også, mest fordi det er gøy (og fordi vi liker å bygge ting), men også fordi smarte folk har gode idéer som fortjener å bli realisert.
|
|
22
|
-
Ting vi har bygd for kundene våre
|
|
23
|
-
`;
|
|
24
|
-
export const ShortText: Story = {
|
|
25
|
-
args: {
|
|
26
|
-
isInitialized: true,
|
|
27
|
-
children: (
|
|
28
|
-
<FormContainer
|
|
29
|
-
onSubmit={() => {
|
|
30
|
-
/* */
|
|
31
|
-
}}
|
|
32
|
-
>
|
|
33
|
-
<TextArea
|
|
34
|
-
name="/apps/blogs.0.title"
|
|
35
|
-
text="Hva skjer'a, Bagera?"
|
|
36
|
-
onChange={() => {
|
|
37
|
-
console.log("onChange");
|
|
38
|
-
}}
|
|
39
|
-
/>
|
|
40
|
-
</FormContainer>
|
|
41
|
-
),
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
export const LongText: Story = {
|
|
45
|
-
args: {
|
|
46
|
-
isInitialized: true,
|
|
47
|
-
children: (
|
|
48
|
-
<FormContainer
|
|
49
|
-
onSubmit={() => {
|
|
50
|
-
/* */
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
<div className="h-full grid grid-rows-[1fr,_min-content] ">
|
|
54
|
-
<TextArea
|
|
55
|
-
name="/apps/blogs.0.title"
|
|
56
|
-
text={EXAMPLE_TEXT}
|
|
57
|
-
onChange={() => {
|
|
58
|
-
console.log("onChange");
|
|
59
|
-
}}
|
|
60
|
-
/>
|
|
61
|
-
</div>
|
|
62
|
-
</FormContainer>
|
|
63
|
-
),
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const RichText: Story = {
|
|
68
|
-
args: {
|
|
69
|
-
isInitialized: true,
|
|
70
|
-
children: (
|
|
71
|
-
<FormContainer
|
|
72
|
-
onSubmit={() => {
|
|
73
|
-
/* */
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
<RichTextEditor
|
|
77
|
-
richtext={{
|
|
78
|
-
_type: "richtext",
|
|
79
|
-
templateStrings: ["# Title 1"],
|
|
80
|
-
exprs: [],
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
</FormContainer>
|
|
84
|
-
),
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export const EmptyImage: Story = {
|
|
89
|
-
args: {
|
|
90
|
-
isInitialized: true,
|
|
91
|
-
children: (
|
|
92
|
-
<FormContainer
|
|
93
|
-
onSubmit={() => {
|
|
94
|
-
/* */
|
|
95
|
-
}}
|
|
96
|
-
>
|
|
97
|
-
<ImageForm
|
|
98
|
-
name="/apps/blogs.0.image"
|
|
99
|
-
error={null}
|
|
100
|
-
data={null}
|
|
101
|
-
onChange={() => {
|
|
102
|
-
console.log("onChange");
|
|
103
|
-
}}
|
|
104
|
-
/>
|
|
105
|
-
</FormContainer>
|
|
106
|
-
),
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export const Image: Story = {
|
|
111
|
-
args: {
|
|
112
|
-
isInitialized: true,
|
|
113
|
-
children: (
|
|
114
|
-
<div className="h-full grid grid-rows-[1fr,_min-content] overflow-scroll">
|
|
115
|
-
<img src={EXAMPLE_IMAGE} />
|
|
116
|
-
<div className="flex justify-end">
|
|
117
|
-
<button className="px-4 py-2 border border-highlight">Submit</button>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
),
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
export const ImageError: Story = {
|
|
125
|
-
args: {
|
|
126
|
-
isInitialized: true,
|
|
127
|
-
children: (
|
|
128
|
-
<FormContainer
|
|
129
|
-
onSubmit={() => {
|
|
130
|
-
/* */
|
|
131
|
-
}}
|
|
132
|
-
>
|
|
133
|
-
<ImageForm
|
|
134
|
-
name="/apps/blogs.0.image"
|
|
135
|
-
error={"invalid-file"}
|
|
136
|
-
data={{
|
|
137
|
-
url: EXAMPLE_IMAGE,
|
|
138
|
-
}}
|
|
139
|
-
onChange={() => {
|
|
140
|
-
console.log("onChange");
|
|
141
|
-
}}
|
|
142
|
-
/>
|
|
143
|
-
</FormContainer>
|
|
144
|
-
),
|
|
145
|
-
},
|
|
146
|
-
};
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
-
import classNames from "classnames";
|
|
3
|
-
import { Resizable } from "react-resizable";
|
|
4
|
-
import { useValOverlayContext } from "./ValOverlayContext";
|
|
5
|
-
import { AlignJustifyIcon, XIcon } from "lucide-react";
|
|
6
|
-
import { ScrollArea } from "./ui/scroll-area";
|
|
7
|
-
|
|
8
|
-
export type ValWindowProps = {
|
|
9
|
-
children:
|
|
10
|
-
| [React.ReactNode, React.ReactNode, React.ReactNode]
|
|
11
|
-
| React.ReactNode;
|
|
12
|
-
|
|
13
|
-
onClose: () => void;
|
|
14
|
-
position?: { left: number; top: number };
|
|
15
|
-
isInitialized?: true;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const MIN_WIDTH = 320;
|
|
19
|
-
const MIN_HEIGHT = 320;
|
|
20
|
-
|
|
21
|
-
export function ValWindow({
|
|
22
|
-
position,
|
|
23
|
-
onClose,
|
|
24
|
-
children,
|
|
25
|
-
}: ValWindowProps): React.ReactElement {
|
|
26
|
-
const [draggedPosition, isInitialized, dragRef, onMouseDownDrag] = useDrag({
|
|
27
|
-
position,
|
|
28
|
-
});
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
const closeOnEscape = (e: KeyboardEvent) => {
|
|
31
|
-
if (e.key === "Escape") {
|
|
32
|
-
onClose();
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
document.addEventListener("keyup", closeOnEscape);
|
|
36
|
-
return () => {
|
|
37
|
-
document.removeEventListener("keyup", closeOnEscape);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
//
|
|
41
|
-
const { windowSize, setWindowSize } = useValOverlayContext();
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (!windowSize) {
|
|
44
|
-
setWindowSize({
|
|
45
|
-
height: MIN_HEIGHT,
|
|
46
|
-
width: MIN_WIDTH,
|
|
47
|
-
innerHeight:
|
|
48
|
-
MIN_HEIGHT -
|
|
49
|
-
(64 + (bottomRef.current?.getBoundingClientRect()?.height || 0)),
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}, [windowSize]);
|
|
53
|
-
//
|
|
54
|
-
const bottomRef = useRef<HTMLDivElement>(null);
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<Resizable
|
|
58
|
-
minConstraints={[MIN_WIDTH, MIN_HEIGHT]}
|
|
59
|
-
width={windowSize?.width || MIN_WIDTH}
|
|
60
|
-
height={windowSize?.height || MIN_HEIGHT}
|
|
61
|
-
onResize={(_, { size }) =>
|
|
62
|
-
setWindowSize({
|
|
63
|
-
...size,
|
|
64
|
-
|
|
65
|
-
innerHeight:
|
|
66
|
-
(windowSize?.height || MIN_HEIGHT) -
|
|
67
|
-
(64 + (bottomRef.current?.getBoundingClientRect()?.height || 0)),
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
handle={
|
|
71
|
-
<div className="fixed bottom-0 right-0 cursor-se-resize">
|
|
72
|
-
<svg
|
|
73
|
-
height="18"
|
|
74
|
-
viewBox="0 0 18 18"
|
|
75
|
-
width="18"
|
|
76
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
77
|
-
>
|
|
78
|
-
<path
|
|
79
|
-
d="m14.228 16.227a1 1 0 0 1 -.707-1.707l1-1a1 1 0 0 1 1.416 1.414l-1 1a1 1 0 0 1 -.707.293zm-5.638 0a1 1 0 0 1 -.707-1.707l6.638-6.638a1 1 0 0 1 1.416 1.414l-6.638 6.638a1 1 0 0 1 -.707.293zm-5.84 0a1 1 0 0 1 -.707-1.707l12.477-12.477a1 1 0 1 1 1.415 1.414l-12.478 12.477a1 1 0 0 1 -.707.293z"
|
|
80
|
-
fill="currentColor"
|
|
81
|
-
/>
|
|
82
|
-
</svg>
|
|
83
|
-
</div>
|
|
84
|
-
}
|
|
85
|
-
draggableOpts={{}}
|
|
86
|
-
className={classNames(
|
|
87
|
-
"absolute inset-0 tablet:w-auto tablet:h-auto tablet:min-h-fit rounded-lg bg-background text-primary drop-shadow-2xl min-w-[320px]",
|
|
88
|
-
{
|
|
89
|
-
"opacity-0": !isInitialized,
|
|
90
|
-
"opacity-100": isInitialized,
|
|
91
|
-
}
|
|
92
|
-
)}
|
|
93
|
-
>
|
|
94
|
-
<div
|
|
95
|
-
style={{
|
|
96
|
-
width: windowSize?.width || MIN_WIDTH,
|
|
97
|
-
height: windowSize?.height || MIN_HEIGHT,
|
|
98
|
-
left: draggedPosition.left,
|
|
99
|
-
top: draggedPosition.top,
|
|
100
|
-
}}
|
|
101
|
-
>
|
|
102
|
-
<div
|
|
103
|
-
ref={dragRef}
|
|
104
|
-
className="relative flex items-center justify-center px-2 pt-2 text-primary"
|
|
105
|
-
>
|
|
106
|
-
<AlignJustifyIcon
|
|
107
|
-
size={16}
|
|
108
|
-
className="w-full cursor-grab tablet:block"
|
|
109
|
-
onMouseDown={(e) => {
|
|
110
|
-
e.preventDefault();
|
|
111
|
-
e.stopPropagation();
|
|
112
|
-
onMouseDownDrag();
|
|
113
|
-
}}
|
|
114
|
-
/>
|
|
115
|
-
<button
|
|
116
|
-
className="absolute top-0 right-0 px-4 py-2 focus:outline-none focus-visible:outline-accent"
|
|
117
|
-
onClick={onClose}
|
|
118
|
-
>
|
|
119
|
-
<XIcon size={16} />
|
|
120
|
-
</button>
|
|
121
|
-
</div>
|
|
122
|
-
<form
|
|
123
|
-
className="h-full"
|
|
124
|
-
onSubmit={(ev) => {
|
|
125
|
-
ev.preventDefault();
|
|
126
|
-
}}
|
|
127
|
-
>
|
|
128
|
-
{Array.isArray(children) && children.slice(0, 1)}
|
|
129
|
-
<ScrollArea
|
|
130
|
-
className="relative"
|
|
131
|
-
style={{
|
|
132
|
-
height: windowSize?.innerHeight,
|
|
133
|
-
}}
|
|
134
|
-
>
|
|
135
|
-
{Array.isArray(children) ? children.slice(1, -1) : children}
|
|
136
|
-
</ScrollArea>
|
|
137
|
-
<div ref={bottomRef} className="w-full px-4 pb-0">
|
|
138
|
-
{Array.isArray(children) && children.slice(-1)}
|
|
139
|
-
</div>
|
|
140
|
-
</form>
|
|
141
|
-
</div>
|
|
142
|
-
</Resizable>
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function useDrag({
|
|
147
|
-
position: initPosition,
|
|
148
|
-
}: {
|
|
149
|
-
position?: { left: number; top: number };
|
|
150
|
-
}) {
|
|
151
|
-
const [position, setPosition] = useState({ left: 0, top: 0 });
|
|
152
|
-
useEffect(() => {
|
|
153
|
-
if (initPosition) {
|
|
154
|
-
const left =
|
|
155
|
-
initPosition.left -
|
|
156
|
-
(ref?.current?.getBoundingClientRect()?.width || 0) / 2;
|
|
157
|
-
const top = initPosition.top - 16;
|
|
158
|
-
setPosition({
|
|
159
|
-
left: left < 0 ? 0 : left,
|
|
160
|
-
top: top < 0 ? 0 : top,
|
|
161
|
-
});
|
|
162
|
-
} else {
|
|
163
|
-
const left = window.innerWidth / 2 - MIN_WIDTH / 2 - window.scrollX;
|
|
164
|
-
const top = window.innerHeight / 2 - MIN_HEIGHT / 2 + window.scrollY;
|
|
165
|
-
setPosition({
|
|
166
|
-
left,
|
|
167
|
-
top,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
}, [initPosition]);
|
|
171
|
-
|
|
172
|
-
const [mouseDown, setMouseDown] = useState(false);
|
|
173
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
const onMouseUp = () => {
|
|
176
|
-
setMouseDown(false);
|
|
177
|
-
};
|
|
178
|
-
const onMouseMove = (e: MouseEvent) => {
|
|
179
|
-
if (mouseDown) {
|
|
180
|
-
e.preventDefault();
|
|
181
|
-
e.stopPropagation();
|
|
182
|
-
const left =
|
|
183
|
-
-((ref?.current?.getBoundingClientRect()?.width || 0) / 2) + e.pageX;
|
|
184
|
-
const top =
|
|
185
|
-
-((ref?.current?.getBoundingClientRect()?.height || 0) / 2) +
|
|
186
|
-
+e.pageY;
|
|
187
|
-
setPosition({
|
|
188
|
-
left: left < 0 ? 0 : left,
|
|
189
|
-
top: top < 0 ? 0 : top,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
document.addEventListener("mouseup", onMouseUp);
|
|
195
|
-
document.addEventListener("mousemove", onMouseMove);
|
|
196
|
-
return () => {
|
|
197
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
198
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
199
|
-
};
|
|
200
|
-
}, [mouseDown]);
|
|
201
|
-
|
|
202
|
-
// TODO: rename hook from useDrag to usePosition or something since we also check for screen width here?
|
|
203
|
-
useEffect(() => {
|
|
204
|
-
const onResize = () => {
|
|
205
|
-
if (window.screen.width < MIN_WIDTH * 2) {
|
|
206
|
-
setPosition({
|
|
207
|
-
left: 0,
|
|
208
|
-
top: 0,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
window.addEventListener("resize", onResize);
|
|
213
|
-
return () => {
|
|
214
|
-
window.removeEventListener("resize", onResize);
|
|
215
|
-
};
|
|
216
|
-
}, []);
|
|
217
|
-
const handleMouseDown = () => setMouseDown(true);
|
|
218
|
-
const isInitialized = !!ref?.current?.getBoundingClientRect()?.width;
|
|
219
|
-
return [position, isInitialized, ref, handleMouseDown] as const;
|
|
220
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { FC, ReactNode } from "react";
|
|
2
|
-
import ExpandLogo from "../ExpandLogo";
|
|
3
|
-
|
|
4
|
-
export const DashboardButton: FC<{
|
|
5
|
-
onClick?: () => void;
|
|
6
|
-
expanded: boolean;
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
}> = ({ onClick, children, expanded }) => {
|
|
9
|
-
return (
|
|
10
|
-
<button
|
|
11
|
-
onClick={onClick}
|
|
12
|
-
className="py-2 px-3 font-serif text-[12px] tracking-[0.04em] font-[500] border rounded-md text-white dark:border-white border-warm-black bg-warm-black group dark:hover:border-highlight hover:text-highlight "
|
|
13
|
-
>
|
|
14
|
-
<span className="flex flex-row items-center justify-center gap-2">
|
|
15
|
-
{
|
|
16
|
-
<ExpandLogo
|
|
17
|
-
expanded={expanded}
|
|
18
|
-
className="fill-white group-hover:fill-highlight"
|
|
19
|
-
/>
|
|
20
|
-
}
|
|
21
|
-
{children}
|
|
22
|
-
</span>
|
|
23
|
-
</button>
|
|
24
|
-
);
|
|
25
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { SerializedModule } from "@valbuild/core";
|
|
2
|
-
import React, { FC, useRef, useState } from "react";
|
|
3
|
-
import classNames from "classnames";
|
|
4
|
-
import Chevron from "../../assets/icons/Chevron";
|
|
5
|
-
|
|
6
|
-
interface DashboardDropdownProps {
|
|
7
|
-
selectedModule: SerializedModule;
|
|
8
|
-
setSelectedModule: React.Dispatch<React.SetStateAction<SerializedModule>>;
|
|
9
|
-
modules: SerializedModule[];
|
|
10
|
-
}
|
|
11
|
-
export const DashboardDropdown: FC<DashboardDropdownProps> = ({
|
|
12
|
-
selectedModule,
|
|
13
|
-
setSelectedModule,
|
|
14
|
-
modules,
|
|
15
|
-
}) => {
|
|
16
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
17
|
-
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<div ref={dropdownRef} className="font-serif relative w-full max-w-[300px]">
|
|
21
|
-
<button
|
|
22
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
23
|
-
className={classNames("w-full")}
|
|
24
|
-
>
|
|
25
|
-
<span className="flex flex-row items-center justify-between w-full">
|
|
26
|
-
<p>
|
|
27
|
-
{selectedModule ? selectedModule.path : "No module selected..."}
|
|
28
|
-
</p>
|
|
29
|
-
<Chevron className={classNames({ "rotate-90": !isOpen })} />
|
|
30
|
-
</span>
|
|
31
|
-
</button>
|
|
32
|
-
<div
|
|
33
|
-
className={classNames(
|
|
34
|
-
{ block: isOpen, hidden: !isOpen },
|
|
35
|
-
"absolute right-0 flex flex-col bg-dark-gray z-10"
|
|
36
|
-
)}
|
|
37
|
-
>
|
|
38
|
-
{modules.map((module, idx) => (
|
|
39
|
-
<button
|
|
40
|
-
key={idx}
|
|
41
|
-
className={classNames(
|
|
42
|
-
{
|
|
43
|
-
"bg-light-gray hover:bg-dark-gray ": selectedModule === module,
|
|
44
|
-
"hover:bg-light-gray": selectedModule !== module,
|
|
45
|
-
},
|
|
46
|
-
" w-full px-4 py-4"
|
|
47
|
-
)}
|
|
48
|
-
onClick={() => {
|
|
49
|
-
setSelectedModule(module);
|
|
50
|
-
setIsOpen(false);
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
{module.path}
|
|
54
|
-
</button>
|
|
55
|
-
))}
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Dropdown } from "./Dropdown";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof Dropdown> = { component: Dropdown };
|
|
5
|
-
|
|
6
|
-
export default meta;
|
|
7
|
-
type Story = StoryObj<typeof Dropdown>;
|
|
8
|
-
|
|
9
|
-
export const Default: Story = {
|
|
10
|
-
render: () => <Dropdown options={["/blogs", "/journals"]} />,
|
|
11
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import classNames from "classnames";
|
|
2
|
-
import { ReactElement, ReactNode, useRef, useState } from "react";
|
|
3
|
-
|
|
4
|
-
type DropdownProps = {
|
|
5
|
-
options?: string[];
|
|
6
|
-
onClick?: (path: string) => void;
|
|
7
|
-
};
|
|
8
|
-
export function Dropdown({
|
|
9
|
-
options = [],
|
|
10
|
-
onClick,
|
|
11
|
-
}: DropdownProps): ReactElement {
|
|
12
|
-
const [selected, setSelected] = useState<string>(options[0]);
|
|
13
|
-
const dropdownRef = useRef<HTMLSelectElement>(null);
|
|
14
|
-
|
|
15
|
-
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
|
16
|
-
setSelected(event.target.value);
|
|
17
|
-
if (onClick) onClick(event.target.value);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<select
|
|
22
|
-
className="relative justify-start w-full px-4 mx-2 font-serif text-xs text-white group bg-warm-black hover:bg-dark-gray"
|
|
23
|
-
onChange={handleChange}
|
|
24
|
-
ref={dropdownRef}
|
|
25
|
-
>
|
|
26
|
-
{options.map((option, index) => (
|
|
27
|
-
<option
|
|
28
|
-
key={index}
|
|
29
|
-
value={option}
|
|
30
|
-
className={classNames(
|
|
31
|
-
{ "bg-yellow": selected === option },
|
|
32
|
-
{ "bg-red": selected !== option }
|
|
33
|
-
)}
|
|
34
|
-
>
|
|
35
|
-
{option}
|
|
36
|
-
</option>
|
|
37
|
-
))}
|
|
38
|
-
</select>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
type DropdownChildProps = {
|
|
43
|
-
children?: ReactNode | ReactNode[];
|
|
44
|
-
id?: string | number;
|
|
45
|
-
onClick?: () => void;
|
|
46
|
-
selected?: boolean;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
Dropdown.Child = ({
|
|
50
|
-
children,
|
|
51
|
-
onClick,
|
|
52
|
-
selected,
|
|
53
|
-
}: DropdownChildProps): ReactElement => {
|
|
54
|
-
return (
|
|
55
|
-
<div
|
|
56
|
-
onClick={() => {
|
|
57
|
-
if (onClick) {
|
|
58
|
-
onClick();
|
|
59
|
-
}
|
|
60
|
-
}}
|
|
61
|
-
className={classNames(
|
|
62
|
-
"flex flex-col py-2 px-3 w-full justify-start items-start bg-warm-black group-hover:bg-dark-gray hover:bg-dark-gray tracking-wider text-[12px] font-[400] font-serif hover:cursor-pointer",
|
|
63
|
-
{ "bg-yellow text-warm-black ": selected },
|
|
64
|
-
{ "text-white ": !selected }
|
|
65
|
-
)}
|
|
66
|
-
>
|
|
67
|
-
{children}
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { FormGroup } from "./FormGroup";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof FormGroup> = { component: FormGroup };
|
|
5
|
-
|
|
6
|
-
export default meta;
|
|
7
|
-
type Story = StoryObj<typeof FormGroup>;
|
|
8
|
-
|
|
9
|
-
export const Default: Story = {
|
|
10
|
-
render: () => (
|
|
11
|
-
<FormGroup>
|
|
12
|
-
<div>Object 1</div>
|
|
13
|
-
<div>Object 2</div>
|
|
14
|
-
<div>Object 3</div>
|
|
15
|
-
<div>Object 4</div>
|
|
16
|
-
</FormGroup>
|
|
17
|
-
),
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const SeveralGroups: Story = {
|
|
21
|
-
render: () => (
|
|
22
|
-
<div>
|
|
23
|
-
<FormGroup>
|
|
24
|
-
<div>Object 1</div>
|
|
25
|
-
<div>Object 2</div>
|
|
26
|
-
<div>Object 3</div>
|
|
27
|
-
<div>Object 4</div>
|
|
28
|
-
</FormGroup>
|
|
29
|
-
<FormGroup>
|
|
30
|
-
<div>Object 5</div>
|
|
31
|
-
<div>Object 6</div>
|
|
32
|
-
<div>Object 7</div>
|
|
33
|
-
<div>Object 8</div>
|
|
34
|
-
</FormGroup>
|
|
35
|
-
</div>
|
|
36
|
-
),
|
|
37
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import classNames from "classnames";
|
|
2
|
-
import { Children, ReactNode, useState } from "react";
|
|
3
|
-
|
|
4
|
-
interface FormGroupProps {
|
|
5
|
-
children: ReactNode | ReactNode[];
|
|
6
|
-
className?: string;
|
|
7
|
-
defaultExpanded?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const FormGroup = ({
|
|
11
|
-
children,
|
|
12
|
-
className,
|
|
13
|
-
defaultExpanded,
|
|
14
|
-
}: FormGroupProps) => {
|
|
15
|
-
const [firstChild, ...rest] = Children.toArray(children);
|
|
16
|
-
const [expanded, setExpanded] = useState<boolean>(defaultExpanded ?? true);
|
|
17
|
-
const defaultClass = "py-3 " + (className ? ` ${className}` : "");
|
|
18
|
-
return (
|
|
19
|
-
<div>
|
|
20
|
-
<div className="flex flex-col font-serif text-xs leading-4 tracking-wider text-white">
|
|
21
|
-
<button
|
|
22
|
-
className={classNames(
|
|
23
|
-
defaultClass,
|
|
24
|
-
"bg-warm-black flex justify-between items-center",
|
|
25
|
-
{ "border-y border-highlight": !expanded }
|
|
26
|
-
)}
|
|
27
|
-
onClick={() => setExpanded(!expanded)}
|
|
28
|
-
>
|
|
29
|
-
{firstChild}
|
|
30
|
-
<div>{expanded ? "Collapse" : "Expand"}</div>
|
|
31
|
-
</button>
|
|
32
|
-
{expanded && (
|
|
33
|
-
<div className="flex flex-col bg-background">
|
|
34
|
-
{Children.map(rest, (child) => (
|
|
35
|
-
<div className={classNames(defaultClass)}>{child}</div>
|
|
36
|
-
))}
|
|
37
|
-
</div>
|
|
38
|
-
)}
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Grid } from "./Grid2";
|
|
3
|
-
import { Tree } from "./Tree";
|
|
4
|
-
import { Dropdown } from "./Dropdown";
|
|
5
|
-
import { FormGroup } from "./FormGroup";
|
|
6
|
-
|
|
7
|
-
const meta: Meta<typeof Grid> = { component: Grid };
|
|
8
|
-
|
|
9
|
-
export default meta;
|
|
10
|
-
type Story = StoryObj<typeof Grid>;
|
|
11
|
-
export const Default: Story = {
|
|
12
|
-
render: () => (
|
|
13
|
-
<Grid>
|
|
14
|
-
<Grid.Row>
|
|
15
|
-
<Dropdown options={["/blogs", "/journals"]} />
|
|
16
|
-
<div className="font-serif text-xs w-full h-full flex justify-between items-center px-3 text-white">
|
|
17
|
-
<p>Content</p>
|
|
18
|
-
<button className="flex justify-between gap-1 flex-shrink-0">
|
|
19
|
-
<span className="w-fit">+</span>
|
|
20
|
-
<span className="w-fit">Add item</span>
|
|
21
|
-
</button>
|
|
22
|
-
</div>
|
|
23
|
-
<div className="text-white">History</div>
|
|
24
|
-
</Grid.Row>
|
|
25
|
-
<Grid.Row fill>
|
|
26
|
-
<Tree>
|
|
27
|
-
<Tree.Node path="Main nav" type="section" />
|
|
28
|
-
<Tree.Node path="H1" type="string">
|
|
29
|
-
<Tree.Node path="Section 3" type="string" />
|
|
30
|
-
<Tree.Node path="Section 4" type="section">
|
|
31
|
-
<Tree.Node path="Section 5" type="string" />
|
|
32
|
-
<Tree.Node path="Section 6" type="section">
|
|
33
|
-
<Tree.Node path="Section 7" type="string" />
|
|
34
|
-
</Tree.Node>
|
|
35
|
-
</Tree.Node>
|
|
36
|
-
</Tree.Node>
|
|
37
|
-
</Tree>
|
|
38
|
-
<div>
|
|
39
|
-
<FormGroup>
|
|
40
|
-
<div>Object 1</div>
|
|
41
|
-
<div>Object 2</div>
|
|
42
|
-
<div>Object 3</div>
|
|
43
|
-
<div>Object 4</div>
|
|
44
|
-
</FormGroup>
|
|
45
|
-
<FormGroup>
|
|
46
|
-
<div>Object 5</div>
|
|
47
|
-
<div>Object 6</div>
|
|
48
|
-
<div>Object 7</div>
|
|
49
|
-
<div>Object 8</div>
|
|
50
|
-
</FormGroup>
|
|
51
|
-
</div>
|
|
52
|
-
<div className="text-white">hey</div>
|
|
53
|
-
</Grid.Row>
|
|
54
|
-
</Grid>
|
|
55
|
-
),
|
|
56
|
-
};
|