@linktr.ee/linkapp 0.0.21 → 0.0.23
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/dev-server/README.md +5 -5
- package/dev-server/components/SettingsPreview.tsx +330 -0
- package/dev-server/components/ui/dialog.tsx +6 -3
- package/dev-server/env.d.ts +8 -0
- package/dev-server/featured/main.tsx +48 -43
- package/dev-server/featured.html +21 -35
- package/dev-server/index.html +8 -1
- package/dev-server/lib/utils.ts +6 -0
- package/dev-server/package-lock.json +245 -287
- package/dev-server/package.json +7 -4
- package/dev-server/postcss/tailwind-source-fallback.js +94 -0
- package/dev-server/postcss.config.mjs +30 -0
- package/dev-server/preview/Preview.tsx +182 -381
- package/dev-server/preview/preview.css +22 -34
- package/dev-server/public/apple-touch-icon.png +0 -0
- package/dev-server/public/favicon-96x96.png +0 -0
- package/dev-server/public/favicon.ico +0 -0
- package/dev-server/public/favicon.svg +6 -0
- package/dev-server/public/site.webmanifest +21 -0
- package/dev-server/public/web-app-manifest-192x192.png +0 -0
- package/dev-server/public/web-app-manifest-512x512.png +0 -0
- package/dev-server/rsbuild.config.ts +45 -0
- package/dev-server/shared/theme-presets.ts +315 -0
- package/dev-server/shared/theme-utils.ts +38 -0
- package/dev-server/sheet/main.tsx +44 -0
- package/dev-server/sheet.html +56 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +20 -12
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +55 -36
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +74 -59
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +564 -43
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +19 -9
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +9 -4
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/test-url-match-rules.d.ts.map +1 -1
- package/dist/commands/test-url-match-rules.js +24 -13
- package/dist/commands/test-url-match-rules.js.map +1 -1
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/lib/auth/device-flow.d.ts +1 -6
- package/dist/lib/auth/device-flow.d.ts.map +1 -1
- package/dist/lib/auth/device-flow.js +3 -9
- package/dist/lib/auth/device-flow.js.map +1 -1
- package/dist/lib/auth/token-storage.d.ts +0 -5
- package/dist/lib/auth/token-storage.d.ts.map +1 -1
- package/dist/lib/auth/token-storage.js +16 -14
- package/dist/lib/auth/token-storage.js.map +1 -1
- package/dist/lib/build/detect-layouts.d.ts +1 -1
- package/dist/lib/build/detect-layouts.d.ts.map +1 -1
- package/dist/lib/build/detect-layouts.js +8 -7
- package/dist/lib/build/detect-layouts.js.map +1 -1
- package/dist/lib/deploy/generate-manifest-files.js +1 -1
- package/dist/lib/deploy/generate-manifest-files.js.map +1 -1
- package/dist/lib/deploy/pack-project.js +2 -2
- package/dist/lib/deploy/pack-project.js.map +1 -1
- package/dist/lib/deploy/test-url-match-rules.d.ts +2 -1
- package/dist/lib/deploy/test-url-match-rules.d.ts.map +1 -1
- package/dist/lib/deploy/test-url-match-rules.js +1 -1
- package/dist/lib/deploy/test-url-match-rules.js.map +1 -1
- package/dist/lib/deploy/upload.d.ts.map +1 -1
- package/dist/lib/deploy/upload.js +7 -3
- package/dist/lib/deploy/upload.js.map +1 -1
- package/dist/lib/deploy/validation.d.ts.map +1 -1
- package/dist/lib/deploy/validation.js +8 -5
- package/dist/lib/deploy/validation.js.map +1 -1
- package/dist/lib/rsbuild/config-factory.d.ts +24 -0
- package/dist/lib/rsbuild/config-factory.d.ts.map +1 -0
- package/dist/lib/rsbuild/config-factory.js +135 -0
- package/dist/lib/rsbuild/config-factory.js.map +1 -0
- package/dist/lib/rsbuild/plugins/asset-versioning.d.ts +11 -0
- package/dist/lib/rsbuild/plugins/asset-versioning.d.ts.map +1 -0
- package/dist/lib/rsbuild/plugins/asset-versioning.js +62 -0
- package/dist/lib/rsbuild/plugins/asset-versioning.js.map +1 -0
- package/dist/lib/rsbuild/plugins/copy-public.d.ts +11 -0
- package/dist/lib/rsbuild/plugins/copy-public.d.ts.map +1 -0
- package/dist/lib/rsbuild/plugins/copy-public.js +32 -0
- package/dist/lib/rsbuild/plugins/copy-public.js.map +1 -0
- package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts +12 -0
- package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts.map +1 -0
- package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js +60 -0
- package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js.map +1 -0
- package/dist/lib/utils/setup-runtime.d.ts.map +1 -1
- package/dist/lib/utils/setup-runtime.js +78 -17
- package/dist/lib/utils/setup-runtime.js.map +1 -1
- package/dist/lib/vite/config-factory.d.ts.map +1 -1
- package/dist/lib/vite/config-factory.js +8 -3
- package/dist/lib/vite/config-factory.js.map +1 -1
- package/dist/lib/vite/plugins/copy-public.d.ts +12 -0
- package/dist/lib/vite/plugins/copy-public.d.ts.map +1 -0
- package/dist/lib/vite/plugins/copy-public.js +31 -0
- package/dist/lib/vite/plugins/copy-public.js.map +1 -0
- package/dist/schema/config.schema.d.ts +121 -32
- package/dist/schema/config.schema.d.ts.map +1 -1
- package/dist/schema/config.schema.js +28 -17
- package/dist/schema/config.schema.js.map +1 -1
- package/dist/types.d.ts +6 -57
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -4
- package/runtime/index.html +19 -36
- package/dev-server/classic/main.tsx +0 -62
- package/dev-server/classic.html +0 -70
- package/dev-server/vite.config.ts +0 -29
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Portal } from "@radix-ui/react-portal";
|
|
2
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import IframeResizer, { IFrameComponent } from "iframe-resizer-react";
|
|
3
4
|
import {
|
|
4
5
|
Dialog,
|
|
5
6
|
DialogContent,
|
|
@@ -12,389 +13,102 @@ import {
|
|
|
12
13
|
TabsList,
|
|
13
14
|
TabsTrigger,
|
|
14
15
|
} from "../components/ui/tabs";
|
|
15
|
-
import { cn } from "../lib/utils";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// Based on actual CSS variables from live Linktree profiles
|
|
19
|
-
const THEME_PRESETS = {
|
|
20
|
-
default: {
|
|
21
|
-
name: "Default (Light)",
|
|
22
|
-
variables: {
|
|
23
|
-
"--button-style-text": "#000000",
|
|
24
|
-
"--button-style-background": "#ffffff",
|
|
25
|
-
"--button-style-background-hover":
|
|
26
|
-
"color-mix(in srgb, #ffffff 93%, #000000 7%)",
|
|
27
|
-
"--button-style-border": "none",
|
|
28
|
-
"--button-style-border-color": "transparent",
|
|
29
|
-
"--button-style-shadow": "none",
|
|
30
|
-
"--button-style-shadow-color": "#000000",
|
|
31
|
-
"--button-style-contrast-color": "#000000",
|
|
32
|
-
"--button-style-radius": "8px",
|
|
33
|
-
"--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
|
|
34
|
-
"--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
|
|
35
|
-
"--link-gap": "14px",
|
|
36
|
-
"--link-inner-padding": "7px",
|
|
37
|
-
"--link-preview-thumbnail-width": "160px",
|
|
38
|
-
"--linkRadius": "8px",
|
|
39
|
-
"--profile-container-desktop-width": "580px",
|
|
40
|
-
"--profileBackground": "#eceef1",
|
|
41
|
-
"--background-contrast-color": "#000000",
|
|
42
|
-
"--bodyText": "#000000",
|
|
43
|
-
"--profileTitleText": "#000000",
|
|
44
|
-
"--profileDescriptionText": "#000000",
|
|
45
|
-
"--defaultAvatarBackground": "#000000",
|
|
46
|
-
"--defaultAvatarText": "#ffffff",
|
|
47
|
-
"--socialLinkFill": "#000000",
|
|
48
|
-
"--linkBackground": "#ffffff",
|
|
49
|
-
"--linkText": "#000000",
|
|
50
|
-
"--linkHoverBackground": "color-mix(in srgb, #ffffff 93%, #000000 7%)",
|
|
51
|
-
"--linkHoverText": "#000000",
|
|
52
|
-
"--linkShadow": "#000000",
|
|
53
|
-
"--bannerBackground": "#ffffff",
|
|
54
|
-
"--bannerText": "#000000",
|
|
55
|
-
"--desktop-frame-color": "color-mix(in srgb, #eceef1 88%, black 12%)",
|
|
56
|
-
"--profileFontFamilyPrimary":
|
|
57
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
58
|
-
"--profileFontFamilySecondary":
|
|
59
|
-
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
60
|
-
"--header-font-family":
|
|
61
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
62
|
-
"--profileFontWeightNormal": "500",
|
|
63
|
-
"--profileFontWeightBold": "700",
|
|
64
|
-
"--profileDescriptionFontWeight": "500",
|
|
65
|
-
"--linkTextFontWeight": "500",
|
|
66
|
-
"--headerFontWeight": "700",
|
|
67
|
-
"--header-font-weight": "600",
|
|
68
|
-
"--embedLinkTextFontWeight": "500",
|
|
69
|
-
"--signupSubmitTextFontWeight": "700",
|
|
70
|
-
"--bannerFontWeight": "700",
|
|
71
|
-
"--headerFontSize": "normal",
|
|
72
|
-
"--header-bio-font-size": "16px",
|
|
73
|
-
"--embedLinkTextFontSize": "14px",
|
|
74
|
-
"--signupSubmitTextFontSize": "14px",
|
|
75
|
-
"--linkHeaderFontSize": "14px",
|
|
76
|
-
"--bannerFontSize": "14px",
|
|
77
|
-
"--profileDescriptionLineHeight": "1.5",
|
|
78
|
-
"--headerLineHeight": "1.5",
|
|
79
|
-
"--header-text-color": "#000000",
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
dark: {
|
|
83
|
-
name: "Dark",
|
|
84
|
-
variables: {
|
|
85
|
-
"--button-style-text": "#ffffff",
|
|
86
|
-
"--button-style-background": "#1f2937",
|
|
87
|
-
"--button-style-background-hover":
|
|
88
|
-
"color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
|
|
89
|
-
"--button-style-border": "none",
|
|
90
|
-
"--button-style-border-color": "transparent",
|
|
91
|
-
"--button-style-shadow": "none",
|
|
92
|
-
"--button-style-shadow-color": "#000000",
|
|
93
|
-
"--button-style-contrast-color": "#ffffff",
|
|
94
|
-
"--button-style-radius": "8px",
|
|
95
|
-
"--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
|
|
96
|
-
"--button-style-skeleton-color": "rgba(255, 255, 255, 0.1)",
|
|
97
|
-
"--link-gap": "14px",
|
|
98
|
-
"--link-inner-padding": "7px",
|
|
99
|
-
"--link-preview-thumbnail-width": "160px",
|
|
100
|
-
"--linkRadius": "8px",
|
|
101
|
-
"--profile-container-desktop-width": "580px",
|
|
102
|
-
"--profileBackground": "#111827",
|
|
103
|
-
"--background-contrast-color": "#ffffff",
|
|
104
|
-
"--bodyText": "#ffffff",
|
|
105
|
-
"--profileTitleText": "#ffffff",
|
|
106
|
-
"--profileDescriptionText": "#ffffff",
|
|
107
|
-
"--defaultAvatarBackground": "#ffffff",
|
|
108
|
-
"--defaultAvatarText": "#000000",
|
|
109
|
-
"--socialLinkFill": "#ffffff",
|
|
110
|
-
"--linkBackground": "#1f2937",
|
|
111
|
-
"--linkText": "#ffffff",
|
|
112
|
-
"--linkHoverBackground": "color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
|
|
113
|
-
"--linkHoverText": "#ffffff",
|
|
114
|
-
"--linkShadow": "#000000",
|
|
115
|
-
"--bannerBackground": "#1f2937",
|
|
116
|
-
"--bannerText": "#ffffff",
|
|
117
|
-
"--desktop-frame-color": "color-mix(in srgb, #111827 88%, white 12%)",
|
|
118
|
-
"--profileFontFamilyPrimary":
|
|
119
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
120
|
-
"--profileFontFamilySecondary":
|
|
121
|
-
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
122
|
-
"--header-font-family":
|
|
123
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
124
|
-
"--profileFontWeightNormal": "500",
|
|
125
|
-
"--profileFontWeightBold": "700",
|
|
126
|
-
"--profileDescriptionFontWeight": "500",
|
|
127
|
-
"--linkTextFontWeight": "500",
|
|
128
|
-
"--headerFontWeight": "700",
|
|
129
|
-
"--header-font-weight": "600",
|
|
130
|
-
"--embedLinkTextFontWeight": "500",
|
|
131
|
-
"--signupSubmitTextFontWeight": "700",
|
|
132
|
-
"--bannerFontWeight": "700",
|
|
133
|
-
"--headerFontSize": "normal",
|
|
134
|
-
"--header-bio-font-size": "16px",
|
|
135
|
-
"--embedLinkTextFontSize": "14px",
|
|
136
|
-
"--signupSubmitTextFontSize": "14px",
|
|
137
|
-
"--linkHeaderFontSize": "14px",
|
|
138
|
-
"--bannerFontSize": "14px",
|
|
139
|
-
"--profileDescriptionLineHeight": "1.5",
|
|
140
|
-
"--headerLineHeight": "1.5",
|
|
141
|
-
"--header-text-color": "#ffffff",
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
purple: {
|
|
145
|
-
name: "Purple",
|
|
146
|
-
variables: {
|
|
147
|
-
"--button-style-text": "#ffffff",
|
|
148
|
-
"--button-style-background": "#7c3aed",
|
|
149
|
-
"--button-style-background-hover":
|
|
150
|
-
"color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
|
|
151
|
-
"--button-style-border": "none",
|
|
152
|
-
"--button-style-border-color": "transparent",
|
|
153
|
-
"--button-style-shadow": "none",
|
|
154
|
-
"--button-style-shadow-color": "#000000",
|
|
155
|
-
"--button-style-contrast-color": "#ede9fe",
|
|
156
|
-
"--button-style-radius": "16px",
|
|
157
|
-
"--button-style-inner-radius": "min(16px, max(4px, calc(16px - 8px)))",
|
|
158
|
-
"--button-style-skeleton-color": "rgba(124, 58, 237, 0.1)",
|
|
159
|
-
"--link-gap": "14px",
|
|
160
|
-
"--link-inner-padding": "7px",
|
|
161
|
-
"--link-preview-thumbnail-width": "160px",
|
|
162
|
-
"--linkRadius": "16px",
|
|
163
|
-
"--profile-container-desktop-width": "580px",
|
|
164
|
-
"--profileBackground": "#faf5ff",
|
|
165
|
-
"--background-contrast-color": "#1f2937",
|
|
166
|
-
"--bodyText": "#1f2937",
|
|
167
|
-
"--profileTitleText": "#1f2937",
|
|
168
|
-
"--profileDescriptionText": "#1f2937",
|
|
169
|
-
"--defaultAvatarBackground": "#7c3aed",
|
|
170
|
-
"--defaultAvatarText": "#ffffff",
|
|
171
|
-
"--socialLinkFill": "#1f2937",
|
|
172
|
-
"--linkBackground": "#7c3aed",
|
|
173
|
-
"--linkText": "#ffffff",
|
|
174
|
-
"--linkHoverBackground": "color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
|
|
175
|
-
"--linkHoverText": "#ffffff",
|
|
176
|
-
"--linkShadow": "#7c3aed",
|
|
177
|
-
"--bannerBackground": "#7c3aed",
|
|
178
|
-
"--bannerText": "#ffffff",
|
|
179
|
-
"--desktop-frame-color": "color-mix(in srgb, #faf5ff 88%, black 12%)",
|
|
180
|
-
"--profileFontFamilyPrimary":
|
|
181
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
182
|
-
"--profileFontFamilySecondary":
|
|
183
|
-
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
184
|
-
"--header-font-family":
|
|
185
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
186
|
-
"--profileFontWeightNormal": "500",
|
|
187
|
-
"--profileFontWeightBold": "700",
|
|
188
|
-
"--profileDescriptionFontWeight": "500",
|
|
189
|
-
"--linkTextFontWeight": "500",
|
|
190
|
-
"--headerFontWeight": "700",
|
|
191
|
-
"--header-font-weight": "600",
|
|
192
|
-
"--embedLinkTextFontWeight": "500",
|
|
193
|
-
"--signupSubmitTextFontWeight": "700",
|
|
194
|
-
"--bannerFontWeight": "700",
|
|
195
|
-
"--headerFontSize": "normal",
|
|
196
|
-
"--header-bio-font-size": "16px",
|
|
197
|
-
"--embedLinkTextFontSize": "14px",
|
|
198
|
-
"--signupSubmitTextFontSize": "14px",
|
|
199
|
-
"--linkHeaderFontSize": "14px",
|
|
200
|
-
"--bannerFontSize": "14px",
|
|
201
|
-
"--profileDescriptionLineHeight": "1.5",
|
|
202
|
-
"--headerLineHeight": "1.5",
|
|
203
|
-
"--header-text-color": "#1f2937",
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
outline: {
|
|
207
|
-
name: "Outline Style",
|
|
208
|
-
variables: {
|
|
209
|
-
"--button-style-text": "#000000",
|
|
210
|
-
"--button-style-background": "transparent",
|
|
211
|
-
"--button-style-background-hover": "rgba(0, 0, 0, 0.05)",
|
|
212
|
-
"--button-style-border": "2px solid currentColor",
|
|
213
|
-
"--button-style-border-color": "#000000",
|
|
214
|
-
"--button-style-shadow": "none",
|
|
215
|
-
"--button-style-shadow-color": "#000000",
|
|
216
|
-
"--button-style-contrast-color": "#ffffff",
|
|
217
|
-
"--button-style-radius": "24px",
|
|
218
|
-
"--button-style-inner-radius": "min(24px, max(4px, calc(24px - 8px)))",
|
|
219
|
-
"--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
|
|
220
|
-
"--link-gap": "14px",
|
|
221
|
-
"--link-inner-padding": "7px",
|
|
222
|
-
"--link-preview-thumbnail-width": "160px",
|
|
223
|
-
"--linkRadius": "24px",
|
|
224
|
-
"--profile-container-desktop-width": "580px",
|
|
225
|
-
"--profileBackground": "#ffffff",
|
|
226
|
-
"--background-contrast-color": "#000000",
|
|
227
|
-
"--bodyText": "#000000",
|
|
228
|
-
"--profileTitleText": "#000000",
|
|
229
|
-
"--profileDescriptionText": "#000000",
|
|
230
|
-
"--defaultAvatarBackground": "#000000",
|
|
231
|
-
"--defaultAvatarText": "#ffffff",
|
|
232
|
-
"--socialLinkFill": "#000000",
|
|
233
|
-
"--linkBackground": "transparent",
|
|
234
|
-
"--linkText": "#000000",
|
|
235
|
-
"--linkHoverBackground": "rgba(0, 0, 0, 0.05)",
|
|
236
|
-
"--linkHoverText": "#000000",
|
|
237
|
-
"--linkShadow": "#000000",
|
|
238
|
-
"--bannerBackground": "#ffffff",
|
|
239
|
-
"--bannerText": "#000000",
|
|
240
|
-
"--desktop-frame-color": "color-mix(in srgb, #ffffff 88%, black 12%)",
|
|
241
|
-
"--profileFontFamilyPrimary":
|
|
242
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
243
|
-
"--profileFontFamilySecondary":
|
|
244
|
-
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
245
|
-
"--header-font-family":
|
|
246
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
247
|
-
"--profileFontWeightNormal": "500",
|
|
248
|
-
"--profileFontWeightBold": "700",
|
|
249
|
-
"--profileDescriptionFontWeight": "500",
|
|
250
|
-
"--linkTextFontWeight": "500",
|
|
251
|
-
"--headerFontWeight": "700",
|
|
252
|
-
"--header-font-weight": "600",
|
|
253
|
-
"--embedLinkTextFontWeight": "500",
|
|
254
|
-
"--signupSubmitTextFontWeight": "700",
|
|
255
|
-
"--bannerFontWeight": "700",
|
|
256
|
-
"--headerFontSize": "normal",
|
|
257
|
-
"--header-bio-font-size": "16px",
|
|
258
|
-
"--embedLinkTextFontSize": "14px",
|
|
259
|
-
"--signupSubmitTextFontSize": "14px",
|
|
260
|
-
"--linkHeaderFontSize": "14px",
|
|
261
|
-
"--bannerFontSize": "14px",
|
|
262
|
-
"--profileDescriptionLineHeight": "1.5",
|
|
263
|
-
"--headerLineHeight": "1.5",
|
|
264
|
-
"--header-text-color": "#000000",
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
rounded: {
|
|
268
|
-
name: "Fully Rounded",
|
|
269
|
-
variables: {
|
|
270
|
-
"--button-style-text": "#ffffff",
|
|
271
|
-
"--button-style-background": "#059669",
|
|
272
|
-
"--button-style-background-hover":
|
|
273
|
-
"color-mix(in srgb, #059669 93%, #ffffff 7%)",
|
|
274
|
-
"--button-style-border": "none",
|
|
275
|
-
"--button-style-border-color": "transparent",
|
|
276
|
-
"--button-style-shadow": "none",
|
|
277
|
-
"--button-style-shadow-color": "#000000",
|
|
278
|
-
"--button-style-contrast-color": "#d1fae5",
|
|
279
|
-
"--button-style-radius": "9999px",
|
|
280
|
-
"--button-style-inner-radius": "9999px",
|
|
281
|
-
"--button-style-skeleton-color": "rgba(5, 150, 105, 0.1)",
|
|
282
|
-
"--link-gap": "14px",
|
|
283
|
-
"--link-inner-padding": "7px",
|
|
284
|
-
"--link-preview-thumbnail-width": "160px",
|
|
285
|
-
"--linkRadius": "9999px",
|
|
286
|
-
"--profile-container-desktop-width": "580px",
|
|
287
|
-
"--profileBackground": "#ecfdf5",
|
|
288
|
-
"--background-contrast-color": "#1f2937",
|
|
289
|
-
"--bodyText": "#1f2937",
|
|
290
|
-
"--profileTitleText": "#1f2937",
|
|
291
|
-
"--profileDescriptionText": "#1f2937",
|
|
292
|
-
"--defaultAvatarBackground": "#059669",
|
|
293
|
-
"--defaultAvatarText": "#ffffff",
|
|
294
|
-
"--socialLinkFill": "#1f2937",
|
|
295
|
-
"--linkBackground": "#059669",
|
|
296
|
-
"--linkText": "#ffffff",
|
|
297
|
-
"--linkHoverBackground": "color-mix(in srgb, #059669 93%, #ffffff 7%)",
|
|
298
|
-
"--linkHoverText": "#ffffff",
|
|
299
|
-
"--linkShadow": "#059669",
|
|
300
|
-
"--bannerBackground": "#059669",
|
|
301
|
-
"--bannerText": "#ffffff",
|
|
302
|
-
"--desktop-frame-color": "color-mix(in srgb, #ecfdf5 88%, black 12%)",
|
|
303
|
-
"--profileFontFamilyPrimary":
|
|
304
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
305
|
-
"--profileFontFamilySecondary":
|
|
306
|
-
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
307
|
-
"--header-font-family":
|
|
308
|
-
'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
309
|
-
"--profileFontWeightNormal": "500",
|
|
310
|
-
"--profileFontWeightBold": "700",
|
|
311
|
-
"--profileDescriptionFontWeight": "500",
|
|
312
|
-
"--linkTextFontWeight": "500",
|
|
313
|
-
"--headerFontWeight": "700",
|
|
314
|
-
"--header-font-weight": "600",
|
|
315
|
-
"--embedLinkTextFontWeight": "500",
|
|
316
|
-
"--signupSubmitTextFontWeight": "700",
|
|
317
|
-
"--bannerFontWeight": "700",
|
|
318
|
-
"--headerFontSize": "normal",
|
|
319
|
-
"--header-bio-font-size": "16px",
|
|
320
|
-
"--embedLinkTextFontSize": "14px",
|
|
321
|
-
"--signupSubmitTextFontSize": "14px",
|
|
322
|
-
"--linkHeaderFontSize": "14px",
|
|
323
|
-
"--bannerFontSize": "14px",
|
|
324
|
-
"--profileDescriptionLineHeight": "1.5",
|
|
325
|
-
"--headerLineHeight": "1.5",
|
|
326
|
-
"--header-text-color": "#1f2937",
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
};
|
|
16
|
+
import { cn, renderCssVariables } from "../lib/utils";
|
|
17
|
+
import { SettingsPreview } from "../components/SettingsPreview";
|
|
18
|
+
import { THEME_PRESETS } from "../shared/theme-presets";
|
|
330
19
|
|
|
331
20
|
export default function Preview() {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
|
|
21
|
+
// Initialize state from localStorage
|
|
22
|
+
const [selectedTab, setSelectedTab] = useState<"sheet" | "featured" | "settings">(() => {
|
|
23
|
+
const saved = localStorage.getItem("linkapp-preview-tab");
|
|
24
|
+
return (saved as "sheet" | "featured" | "settings") || "sheet";
|
|
25
|
+
});
|
|
26
|
+
const [selectedTheme, setSelectedTheme] = useState<keyof typeof THEME_PRESETS>(() => {
|
|
27
|
+
const saved = localStorage.getItem("linkapp-preview-theme");
|
|
28
|
+
return (saved as keyof typeof THEME_PRESETS) || "default";
|
|
29
|
+
});
|
|
30
|
+
const [selectedGroupLayoutOption, setSelectedGroupLayoutOption] = useState<string | undefined>(() => {
|
|
31
|
+
const saved = localStorage.getItem("linkapp-preview-groupLayoutOption");
|
|
32
|
+
return saved || undefined;
|
|
33
|
+
});
|
|
339
34
|
|
|
340
|
-
//
|
|
341
|
-
const
|
|
342
|
-
(
|
|
343
|
-
iframe: HTMLIFrameElement | null,
|
|
344
|
-
themeName: keyof typeof THEME_PRESETS,
|
|
345
|
-
) => {
|
|
346
|
-
if (!iframe || !iframe.contentWindow) return;
|
|
35
|
+
// Popup dialog state
|
|
36
|
+
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
|
347
37
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
name: themeName,
|
|
353
|
-
variables: theme.variables,
|
|
354
|
-
},
|
|
355
|
-
};
|
|
38
|
+
// Generate unique IDs for iframes using timestamp
|
|
39
|
+
const sheetIframeId = useMemo(() => `preview-iframe-sheet-${Date.now()}`, []);
|
|
40
|
+
const featuredIframeId = useMemo(() => `preview-iframe-featured-${Date.now()}`, []);
|
|
41
|
+
const popupIframeId = useMemo(() => `preview-iframe-popup-${Date.now()}`, []);
|
|
356
42
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
);
|
|
43
|
+
// Save selected tab to localStorage
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
localStorage.setItem("linkapp-preview-tab", selectedTab);
|
|
46
|
+
}, [selectedTab]);
|
|
47
|
+
|
|
48
|
+
// Save selected theme to localStorage
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
localStorage.setItem("linkapp-preview-theme", selectedTheme);
|
|
51
|
+
}, [selectedTheme]);
|
|
361
52
|
|
|
362
|
-
//
|
|
53
|
+
// Save selected groupLayoutOption to localStorage
|
|
363
54
|
useEffect(() => {
|
|
364
|
-
|
|
365
|
-
|
|
55
|
+
if (selectedGroupLayoutOption) {
|
|
56
|
+
localStorage.setItem("linkapp-preview-groupLayoutOption", selectedGroupLayoutOption);
|
|
57
|
+
} else {
|
|
58
|
+
localStorage.removeItem("linkapp-preview-groupLayoutOption");
|
|
59
|
+
}
|
|
60
|
+
}, [selectedGroupLayoutOption]);
|
|
61
|
+
|
|
62
|
+
// Handle iframe resize events
|
|
63
|
+
const handleResized = useCallback(
|
|
64
|
+
(ev: { iframe: IFrameComponent; height: number; width: number; type: string }): void => {
|
|
65
|
+
// IframeResizer automatically handles height adjustments
|
|
66
|
+
// This callback is available for debugging if needed
|
|
67
|
+
},
|
|
68
|
+
[]
|
|
69
|
+
);
|
|
366
70
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
71
|
+
// Handle postMessage from featured iframe for OPEN_POPUP
|
|
72
|
+
const handleMessage = useCallback((event: MessageEvent) => {
|
|
73
|
+
if (
|
|
74
|
+
event.data &&
|
|
75
|
+
typeof event.data === 'object' &&
|
|
76
|
+
event.data.source === 'linkapp' &&
|
|
77
|
+
event.data.type === 'OPEN_POPUP'
|
|
78
|
+
) {
|
|
79
|
+
setIsPopupOpen(true);
|
|
80
|
+
}
|
|
81
|
+
}, []);
|
|
371
82
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
83
|
+
// Add message listener
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
window.addEventListener('message', handleMessage);
|
|
86
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
87
|
+
}, [handleMessage]);
|
|
375
88
|
|
|
376
|
-
// Listen for iframe load events
|
|
377
|
-
classicIframe?.addEventListener("load", handleClassicLoad);
|
|
378
|
-
featuredIframe?.addEventListener("load", handleFeaturedLoad);
|
|
379
89
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}, [selectedTheme, sendThemeUpdate]);
|
|
90
|
+
const renderedCssVariables = useMemo(() => {
|
|
91
|
+
const themeVariables = THEME_PRESETS[selectedTheme] || THEME_PRESETS.default
|
|
92
|
+
return renderCssVariables(themeVariables.variables);
|
|
93
|
+
}, [selectedTheme])
|
|
385
94
|
|
|
386
95
|
return (
|
|
96
|
+
<>
|
|
97
|
+
<style>{`:root {
|
|
98
|
+
${renderedCssVariables}
|
|
99
|
+
}`}</style>
|
|
100
|
+
|
|
387
101
|
<div
|
|
388
102
|
className={cn("min-h-screen", {
|
|
389
103
|
"bg-black/50": selectedTab === "classic",
|
|
390
|
-
"bg-
|
|
104
|
+
"bg-linktree-frame": selectedTab === "featured",
|
|
391
105
|
})}
|
|
392
106
|
id="preview"
|
|
393
107
|
>
|
|
394
108
|
<Tabs
|
|
395
109
|
value={selectedTab}
|
|
396
110
|
onValueChange={(value) =>
|
|
397
|
-
setSelectedTab(value as "
|
|
111
|
+
setSelectedTab(value as "sheet" | "featured" | "settings")
|
|
398
112
|
}
|
|
399
113
|
>
|
|
400
114
|
<Portal>
|
|
@@ -403,8 +117,9 @@ export default function Preview() {
|
|
|
403
117
|
style={{ zIndex: 1000000 }}
|
|
404
118
|
>
|
|
405
119
|
<TabsList>
|
|
406
|
-
<TabsTrigger value="
|
|
120
|
+
<TabsTrigger value="sheet">Sheet</TabsTrigger>
|
|
407
121
|
<TabsTrigger value="featured">Featured</TabsTrigger>
|
|
122
|
+
<TabsTrigger value="settings">Settings</TabsTrigger>
|
|
408
123
|
</TabsList>
|
|
409
124
|
|
|
410
125
|
{/* Theme Switcher */}
|
|
@@ -427,29 +142,66 @@ export default function Preview() {
|
|
|
427
142
|
))}
|
|
428
143
|
</select>
|
|
429
144
|
</div>
|
|
145
|
+
|
|
146
|
+
{/* Group Layout Option Switcher - Only show for Featured tab */}
|
|
147
|
+
{selectedTab === "featured" && (
|
|
148
|
+
<div className="flex items-center gap-2">
|
|
149
|
+
<label htmlFor="groupLayoutOption-select" className="text-sm font-medium">
|
|
150
|
+
Layout:
|
|
151
|
+
</label>
|
|
152
|
+
<select
|
|
153
|
+
id="groupLayoutOption-select"
|
|
154
|
+
value={selectedGroupLayoutOption || "default"}
|
|
155
|
+
onChange={(e) =>
|
|
156
|
+
setSelectedGroupLayoutOption(e.target.value === "default" ? undefined : e.target.value)
|
|
157
|
+
}
|
|
158
|
+
className="h-9 px-3 py-1 text-sm border border-input bg-background rounded-md focus:outline-none focus:ring-2 focus:ring-ring"
|
|
159
|
+
>
|
|
160
|
+
<option value="default">Default</option>
|
|
161
|
+
<option value="carousel">Carousel</option>
|
|
162
|
+
</select>
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
430
165
|
</div>
|
|
431
166
|
</Portal>
|
|
432
167
|
|
|
433
168
|
{/* Main Content with Padding for Fixed Tabs */}
|
|
434
169
|
<div className="pt-20">
|
|
435
|
-
<TabsContent value="
|
|
436
|
-
{/*
|
|
170
|
+
<TabsContent value="sheet" className="m-0">
|
|
171
|
+
{/* Sheet Modal - Always Open */}
|
|
437
172
|
<Dialog open={true} modal={false}>
|
|
438
173
|
<DialogContent
|
|
439
|
-
className="max-w-[
|
|
174
|
+
className="h-[calc(100dvh-2rem)] max-w-[608px] md:min-h-[25vh] md:h-[80%] md:max-h-[900px] overflow-auto"
|
|
440
175
|
showCloseButton={false}
|
|
441
176
|
>
|
|
442
177
|
<DialogHeader className="sticky top-0 bg-white px-4">
|
|
443
|
-
<
|
|
178
|
+
<div className="grid h-16 grid-cols-[32px_auto_32px] items-center gap-4">
|
|
179
|
+
<button className="flex size-8 items-center justify-center rounded-sm focus-visible:outline-none">
|
|
180
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className=" " role="img" aria-hidden="true"><path fill="currentColor" d="m10.65 3.85.35.36.7-.71-.35-.35-3-3h-.7l-3 3-.36.35.71.7.35-.35L7.5 1.71V10h1V1.7l2.15 2.15ZM1 5.5l.5-.5H4v1H2v9h12V6h-2V5h2.5l.5.5v10l-.5.5h-13l-.5-.5v-10Z"></path></svg>
|
|
181
|
+
</button>
|
|
182
|
+
|
|
183
|
+
<DialogTitle className="self-center truncate py-3 text-center">
|
|
184
|
+
Sheet
|
|
185
|
+
</DialogTitle>
|
|
186
|
+
|
|
187
|
+
<button className="flex size-8 items-center justify-center rounded-sm focus-visible:outline-none">
|
|
188
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className=" " role="img" aria-hidden="true"><path fill="currentColor" d="m13.63 3.12.37-.38-.74-.74-.38.37.75.75ZM2.37 12.89l-.37.37.74.74.38-.37-.75-.75Zm.75-10.52L2.74 2 2 2.74l.37.38.75-.75Zm9.76 11.26.38.37.74-.74-.37-.38-.75.75Zm0-11.26L2.38 12.9l.74.74 10.5-10.51-.74-.75Zm-10.5.75 10.5 10.5.75-.73L3.12 2.37l-.75.75Z"></path></svg>
|
|
189
|
+
</button>
|
|
190
|
+
</div>
|
|
444
191
|
</DialogHeader>
|
|
445
192
|
|
|
446
|
-
<div className="
|
|
447
|
-
<
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
193
|
+
<div className="flex h-[calc(100%-64px)] flex-1 flex-col justify-between overflow-hidden">
|
|
194
|
+
<div className="h-full overflow-y-auto overflow-x-hidden">
|
|
195
|
+
<IframeResizer
|
|
196
|
+
key={`sheet-${selectedTheme}`}
|
|
197
|
+
id={sheetIframeId}
|
|
198
|
+
src={`/sheet?theme=${selectedTheme}`}
|
|
199
|
+
style={{ height: '0px', width: '1px', minWidth: '100%', border: 0 }}
|
|
200
|
+
checkOrigin={false}
|
|
201
|
+
onResized={handleResized}
|
|
202
|
+
heightCalculationMethod="max"
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
453
205
|
</div>
|
|
454
206
|
</DialogContent>
|
|
455
207
|
</Dialog>
|
|
@@ -457,19 +209,68 @@ export default function Preview() {
|
|
|
457
209
|
|
|
458
210
|
<TabsContent value="featured" className="m-0 flex justify-center p-8">
|
|
459
211
|
{/* Featured Iframe - Max Width 524px */}
|
|
460
|
-
<div className="w-full max-w-[580px]
|
|
212
|
+
<div className="w-full max-w-[580px] flex flex-col px-[28px] py-7 items-center bg-linktree-profile-bg">
|
|
213
|
+
|
|
461
214
|
<div className="w-full max-w-[524px]">
|
|
462
|
-
<
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
215
|
+
<div className="bg-linktree-button-bg hover:bg-linktree-button-bg-hover border-linktree-button-border text-linktree-button-text rounded-linktree-button shadow-linktree-button overflow-hidden">
|
|
216
|
+
<IframeResizer
|
|
217
|
+
key={`featured-${selectedTheme}-${selectedGroupLayoutOption || 'default'}`}
|
|
218
|
+
id={featuredIframeId}
|
|
219
|
+
src={`/featured?theme=${selectedTheme}${selectedGroupLayoutOption ? `&groupLayoutOption=${selectedGroupLayoutOption}` : ''}`}
|
|
220
|
+
style={{ height: '0px', width: '1px', minWidth: '100%', border: 0 }}
|
|
221
|
+
checkOrigin={false}
|
|
222
|
+
onResized={handleResized}
|
|
223
|
+
heightCalculationMethod="max"
|
|
224
|
+
/>
|
|
225
|
+
</div>
|
|
468
226
|
</div>
|
|
469
227
|
</div>
|
|
470
228
|
</TabsContent>
|
|
229
|
+
|
|
230
|
+
<TabsContent value="settings" className="m-0">
|
|
231
|
+
<SettingsPreview settings={__SETTINGS_CONFIG__} />
|
|
232
|
+
</TabsContent>
|
|
471
233
|
</div>
|
|
472
234
|
</Tabs>
|
|
235
|
+
|
|
236
|
+
{/* Popup Dialog for OPEN_POPUP message */}
|
|
237
|
+
<Dialog open={isPopupOpen} onOpenChange={setIsPopupOpen} modal={false}>
|
|
238
|
+
<DialogContent
|
|
239
|
+
className="h-[calc(100dvh-2rem)] max-w-[608px] md:min-h-[25vh] md:h-[80%] md:max-h-[900px] overflow-auto"
|
|
240
|
+
showCloseButton={false}
|
|
241
|
+
>
|
|
242
|
+
<DialogHeader className="sticky top-0 bg-white px-4">
|
|
243
|
+
<div className="grid h-16 grid-cols-[32px_auto_32px] items-center gap-4">
|
|
244
|
+
<button className="flex size-8 items-center justify-center rounded-sm focus-visible:outline-none">
|
|
245
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className=" " role="img" aria-hidden="true"><path fill="currentColor" d="m10.65 3.85.35.36.7-.71-.35-.35-3-3h-.7l-3 3-.36.35.71.7.35-.35L7.5 1.71V10h1V1.7l2.15 2.15ZM1 5.5l.5-.5H4v1H2v9h12V6h-2V5h2.5l.5.5v10l-.5.5h-13l-.5-.5v-10Z"></path></svg>
|
|
246
|
+
</button>
|
|
247
|
+
|
|
248
|
+
<DialogTitle className="self-center truncate py-3 text-center">
|
|
249
|
+
Sheet
|
|
250
|
+
</DialogTitle>
|
|
251
|
+
|
|
252
|
+
<button className="flex size-8 items-center justify-center rounded-sm focus-visible:outline-none">
|
|
253
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className=" " role="img" aria-hidden="true"><path fill="currentColor" d="m13.63 3.12.37-.38-.74-.74-.38.37.75.75ZM2.37 12.89l-.37.37.74.74.38-.37-.75-.75Zm.75-10.52L2.74 2 2 2.74l.37.38.75-.75Zm9.76 11.26.38.37.74-.74-.37-.38-.75.75Zm0-11.26L2.38 12.9l.74.74 10.5-10.51-.74-.75Zm-10.5.75 10.5 10.5.75-.73L3.12 2.37l-.75.75Z"></path></svg>
|
|
254
|
+
</button>
|
|
255
|
+
</div>
|
|
256
|
+
</DialogHeader>
|
|
257
|
+
|
|
258
|
+
<div className="flex h-[calc(100%-64px)] flex-1 flex-col justify-between overflow-hidden">
|
|
259
|
+
<div className="h-full overflow-y-auto overflow-x-hidden">
|
|
260
|
+
<IframeResizer
|
|
261
|
+
key={`popup-${selectedTheme}`}
|
|
262
|
+
id={popupIframeId}
|
|
263
|
+
src={`/sheet?theme=${selectedTheme}`}
|
|
264
|
+
style={{ height: '0px', width: '1px', minWidth: '100%', border: 0 }}
|
|
265
|
+
checkOrigin={false}
|
|
266
|
+
onResized={handleResized}
|
|
267
|
+
heightCalculationMethod="max"
|
|
268
|
+
/>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
</DialogContent>
|
|
272
|
+
</Dialog>
|
|
473
273
|
</div>
|
|
274
|
+
</>
|
|
474
275
|
);
|
|
475
276
|
}
|