@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.
Files changed (115) hide show
  1. package/dev-server/README.md +5 -5
  2. package/dev-server/components/SettingsPreview.tsx +330 -0
  3. package/dev-server/components/ui/dialog.tsx +6 -3
  4. package/dev-server/env.d.ts +8 -0
  5. package/dev-server/featured/main.tsx +48 -43
  6. package/dev-server/featured.html +21 -35
  7. package/dev-server/index.html +8 -1
  8. package/dev-server/lib/utils.ts +6 -0
  9. package/dev-server/package-lock.json +245 -287
  10. package/dev-server/package.json +7 -4
  11. package/dev-server/postcss/tailwind-source-fallback.js +94 -0
  12. package/dev-server/postcss.config.mjs +30 -0
  13. package/dev-server/preview/Preview.tsx +182 -381
  14. package/dev-server/preview/preview.css +22 -34
  15. package/dev-server/public/apple-touch-icon.png +0 -0
  16. package/dev-server/public/favicon-96x96.png +0 -0
  17. package/dev-server/public/favicon.ico +0 -0
  18. package/dev-server/public/favicon.svg +6 -0
  19. package/dev-server/public/site.webmanifest +21 -0
  20. package/dev-server/public/web-app-manifest-192x192.png +0 -0
  21. package/dev-server/public/web-app-manifest-512x512.png +0 -0
  22. package/dev-server/rsbuild.config.ts +45 -0
  23. package/dev-server/shared/theme-presets.ts +315 -0
  24. package/dev-server/shared/theme-utils.ts +38 -0
  25. package/dev-server/sheet/main.tsx +44 -0
  26. package/dev-server/sheet.html +56 -0
  27. package/dist/commands/add.d.ts.map +1 -1
  28. package/dist/commands/add.js +20 -12
  29. package/dist/commands/add.js.map +1 -1
  30. package/dist/commands/build.d.ts.map +1 -1
  31. package/dist/commands/build.js +55 -36
  32. package/dist/commands/build.js.map +1 -1
  33. package/dist/commands/deploy.d.ts.map +1 -1
  34. package/dist/commands/deploy.js +74 -59
  35. package/dist/commands/deploy.js.map +1 -1
  36. package/dist/commands/dev.d.ts.map +1 -1
  37. package/dist/commands/dev.js +564 -43
  38. package/dist/commands/dev.js.map +1 -1
  39. package/dist/commands/login.d.ts.map +1 -1
  40. package/dist/commands/login.js +19 -9
  41. package/dist/commands/login.js.map +1 -1
  42. package/dist/commands/logout.d.ts.map +1 -1
  43. package/dist/commands/logout.js +9 -4
  44. package/dist/commands/logout.js.map +1 -1
  45. package/dist/commands/test-url-match-rules.d.ts.map +1 -1
  46. package/dist/commands/test-url-match-rules.js +24 -13
  47. package/dist/commands/test-url-match-rules.js.map +1 -1
  48. package/dist/components/index.d.ts +0 -1
  49. package/dist/components/index.d.ts.map +1 -1
  50. package/dist/components/index.js +2 -1
  51. package/dist/components/index.js.map +1 -1
  52. package/dist/lib/auth/device-flow.d.ts +1 -6
  53. package/dist/lib/auth/device-flow.d.ts.map +1 -1
  54. package/dist/lib/auth/device-flow.js +3 -9
  55. package/dist/lib/auth/device-flow.js.map +1 -1
  56. package/dist/lib/auth/token-storage.d.ts +0 -5
  57. package/dist/lib/auth/token-storage.d.ts.map +1 -1
  58. package/dist/lib/auth/token-storage.js +16 -14
  59. package/dist/lib/auth/token-storage.js.map +1 -1
  60. package/dist/lib/build/detect-layouts.d.ts +1 -1
  61. package/dist/lib/build/detect-layouts.d.ts.map +1 -1
  62. package/dist/lib/build/detect-layouts.js +8 -7
  63. package/dist/lib/build/detect-layouts.js.map +1 -1
  64. package/dist/lib/deploy/generate-manifest-files.js +1 -1
  65. package/dist/lib/deploy/generate-manifest-files.js.map +1 -1
  66. package/dist/lib/deploy/pack-project.js +2 -2
  67. package/dist/lib/deploy/pack-project.js.map +1 -1
  68. package/dist/lib/deploy/test-url-match-rules.d.ts +2 -1
  69. package/dist/lib/deploy/test-url-match-rules.d.ts.map +1 -1
  70. package/dist/lib/deploy/test-url-match-rules.js +1 -1
  71. package/dist/lib/deploy/test-url-match-rules.js.map +1 -1
  72. package/dist/lib/deploy/upload.d.ts.map +1 -1
  73. package/dist/lib/deploy/upload.js +7 -3
  74. package/dist/lib/deploy/upload.js.map +1 -1
  75. package/dist/lib/deploy/validation.d.ts.map +1 -1
  76. package/dist/lib/deploy/validation.js +8 -5
  77. package/dist/lib/deploy/validation.js.map +1 -1
  78. package/dist/lib/rsbuild/config-factory.d.ts +24 -0
  79. package/dist/lib/rsbuild/config-factory.d.ts.map +1 -0
  80. package/dist/lib/rsbuild/config-factory.js +135 -0
  81. package/dist/lib/rsbuild/config-factory.js.map +1 -0
  82. package/dist/lib/rsbuild/plugins/asset-versioning.d.ts +11 -0
  83. package/dist/lib/rsbuild/plugins/asset-versioning.d.ts.map +1 -0
  84. package/dist/lib/rsbuild/plugins/asset-versioning.js +62 -0
  85. package/dist/lib/rsbuild/plugins/asset-versioning.js.map +1 -0
  86. package/dist/lib/rsbuild/plugins/copy-public.d.ts +11 -0
  87. package/dist/lib/rsbuild/plugins/copy-public.d.ts.map +1 -0
  88. package/dist/lib/rsbuild/plugins/copy-public.js +32 -0
  89. package/dist/lib/rsbuild/plugins/copy-public.js.map +1 -0
  90. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts +12 -0
  91. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts.map +1 -0
  92. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js +60 -0
  93. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js.map +1 -0
  94. package/dist/lib/utils/setup-runtime.d.ts.map +1 -1
  95. package/dist/lib/utils/setup-runtime.js +78 -17
  96. package/dist/lib/utils/setup-runtime.js.map +1 -1
  97. package/dist/lib/vite/config-factory.d.ts.map +1 -1
  98. package/dist/lib/vite/config-factory.js +8 -3
  99. package/dist/lib/vite/config-factory.js.map +1 -1
  100. package/dist/lib/vite/plugins/copy-public.d.ts +12 -0
  101. package/dist/lib/vite/plugins/copy-public.d.ts.map +1 -0
  102. package/dist/lib/vite/plugins/copy-public.js +31 -0
  103. package/dist/lib/vite/plugins/copy-public.js.map +1 -0
  104. package/dist/schema/config.schema.d.ts +121 -32
  105. package/dist/schema/config.schema.d.ts.map +1 -1
  106. package/dist/schema/config.schema.js +28 -17
  107. package/dist/schema/config.schema.js.map +1 -1
  108. package/dist/types.d.ts +6 -57
  109. package/dist/types.d.ts.map +1 -1
  110. package/dist/types.js.map +1 -1
  111. package/package.json +7 -4
  112. package/runtime/index.html +19 -36
  113. package/dev-server/classic/main.tsx +0 -62
  114. package/dev-server/classic.html +0 -70
  115. package/dev-server/vite.config.ts +0 -29
@@ -1,7 +1,8 @@
1
1
  @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
3
 
4
- @custom-variant dark (&:is(.dark *));
4
+ @source "../components";
5
+ @source "../preview";
5
6
 
6
7
  @theme inline {
7
8
  --color-background: var(--background);
@@ -41,6 +42,26 @@
41
42
  --radius-md: calc(var(--radius) - 2px);
42
43
  --radius-lg: var(--radius);
43
44
  --radius-xl: calc(var(--radius) + 4px);
45
+
46
+ --color-linktree-button-bg: var(--button-style-background);
47
+ --color-linktree-button-bg-hover: var(--button-style-background-hover);
48
+ --color-linktree-button-text: var(--button-style-text);
49
+ --color-linktree-button-border: var(--button-style-border-color);
50
+ --color-linktree-button-contrast: var(--button-style-contrast-color);
51
+ --color-linktree-profile-bg: var(--profileBackground);
52
+ --color-linktree-body-text: var(--bodyText);
53
+ --color-linktree-link-bg: var(--linkBackground);
54
+ --color-linktree-link-text: var(--linkText);
55
+ --color-linktree-link-bg-hover: var(--linkHoverBackground);
56
+ --color-linktree-link-hover-text: var(--linkHoverText);
57
+ --color-linktree-frame: var(--desktop-frame-color);
58
+ --radius-linktree-button: var(--button-style-radius);
59
+ --radius-linktree-button-inner: var(--button-style-inner-radius);
60
+ --spacing-linktree-link-gap: var(--link-gap);
61
+ --spacing-linktree-inner-padding: var(--link-inner-padding);
62
+ --font-linktree-primary: var(--profileFontFamilyPrimary);
63
+ --font-linktree-secondary: var(--profileFontFamilySecondary);
64
+ --shadow-linktree-button: var(--button-style-shadow);
44
65
  }
45
66
 
46
67
  :root {
@@ -78,39 +99,6 @@
78
99
  --sidebar-ring: oklch(0.708 0 0);
79
100
  }
80
101
 
81
- .dark {
82
- --background: oklch(0.145 0 0);
83
- --foreground: oklch(0.985 0 0);
84
- --card: oklch(0.205 0 0);
85
- --card-foreground: oklch(0.985 0 0);
86
- --popover: oklch(0.205 0 0);
87
- --popover-foreground: oklch(0.985 0 0);
88
- --primary: oklch(0.922 0 0);
89
- --primary-foreground: oklch(0.205 0 0);
90
- --secondary: oklch(0.269 0 0);
91
- --secondary-foreground: oklch(0.985 0 0);
92
- --muted: oklch(0.269 0 0);
93
- --muted-foreground: oklch(0.708 0 0);
94
- --accent: oklch(0.269 0 0);
95
- --accent-foreground: oklch(0.985 0 0);
96
- --destructive: oklch(0.704 0.191 22.216);
97
- --border: oklch(1 0 0 / 10%);
98
- --input: oklch(1 0 0 / 15%);
99
- --ring: oklch(0.556 0 0);
100
- --chart-1: oklch(0.488 0.243 264.376);
101
- --chart-2: oklch(0.696 0.17 162.48);
102
- --chart-3: oklch(0.769 0.188 70.08);
103
- --chart-4: oklch(0.627 0.265 303.9);
104
- --chart-5: oklch(0.645 0.246 16.439);
105
- --sidebar: oklch(0.205 0 0);
106
- --sidebar-foreground: oklch(0.985 0 0);
107
- --sidebar-primary: oklch(0.488 0.243 264.376);
108
- --sidebar-primary-foreground: oklch(0.985 0 0);
109
- --sidebar-accent: oklch(0.269 0 0);
110
- --sidebar-accent-foreground: oklch(0.985 0 0);
111
- --sidebar-border: oklch(1 0 0 / 10%);
112
- --sidebar-ring: oklch(0.556 0 0);
113
- }
114
102
 
115
103
  @layer base {
116
104
  * {
Binary file
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500"><svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="500" height="500" rx="132" fill="#45E55F"></rect>
3
+ <path d="M226.993 168.546L173.931 114L143.128 145.546L198.786 198.607H120.499V242.395H199.157L143.128 296.822L173.931 327.745L249.993 251.312L326.055 327.745L356.859 296.941L300.829 242.515H379.501V198.607H301.214L356.872 145.546L326.069 114L273.007 168.546V91H226.993V168.546ZM273.007 305.102H226.993V409H273.007V305.102Z" fill="black"></path>
4
+ </svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
5
+ @media (prefers-color-scheme: dark) { :root { filter: none; } }
6
+ </style></svg>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "Linktree",
3
+ "short_name": "Linktree",
4
+ "icons": [
5
+ {
6
+ "src": "/web-app-manifest-192x192.png",
7
+ "sizes": "192x192",
8
+ "type": "image/png",
9
+ "purpose": "maskable"
10
+ },
11
+ {
12
+ "src": "/web-app-manifest-512x512.png",
13
+ "sizes": "512x512",
14
+ "type": "image/png",
15
+ "purpose": "maskable"
16
+ }
17
+ ],
18
+ "theme_color": "#ffffff",
19
+ "background_color": "#ffffff",
20
+ "display": "standalone"
21
+ }
@@ -0,0 +1,45 @@
1
+ import { defineConfig } from '@rsbuild/core'
2
+ import { pluginReact } from '@rsbuild/plugin-react'
3
+ import { resolve } from 'path'
4
+
5
+ export default defineConfig({
6
+ plugins: [pluginReact()],
7
+ source: {
8
+ // Define fallback values - these will be overridden by dev.ts
9
+ define: {
10
+ __PREVIEW_PROPS__: 'undefined',
11
+ __SETTINGS_CONFIG__: 'undefined',
12
+ },
13
+ },
14
+ resolve: {
15
+ alias: {
16
+ '@': resolve(__dirname, '..'),
17
+ '@/components': resolve(__dirname, 'components'),
18
+ '@/lib': resolve(__dirname, 'lib'),
19
+ },
20
+ },
21
+ html: {
22
+ template: resolve(__dirname, 'index.html'),
23
+ },
24
+ server: {
25
+ port: 3000,
26
+ strictPort: true,
27
+ },
28
+ tools: {
29
+ postcss: (opts) => {
30
+ // Support Tailwind CSS v4 via PostCSS
31
+ opts.postcssOptions = opts.postcssOptions || {}
32
+ opts.postcssOptions.plugins = opts.postcssOptions.plugins || []
33
+
34
+ // Add Tailwind CSS PostCSS plugin
35
+ try {
36
+ const tailwindPostcss = require('@tailwindcss/postcss')
37
+ opts.postcssOptions.plugins.push(tailwindPostcss())
38
+ } catch {
39
+ // @tailwindcss/postcss not installed
40
+ }
41
+
42
+ return opts
43
+ },
44
+ },
45
+ })
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Theme presets for testing LinkApps in dev mode
3
+ * Based on actual CSS variables from live Linktree profiles
4
+ */
5
+ export const THEME_PRESETS = {
6
+ default: {
7
+ name: "Default (Light)",
8
+ variables: {
9
+ "--button-style-text": "#000000",
10
+ "--button-style-background": "#ffffff",
11
+ "--button-style-background-hover":
12
+ "color-mix(in srgb, #ffffff 93%, #000000 7%)",
13
+ "--button-style-border": "none",
14
+ "--button-style-border-color": "transparent",
15
+ "--button-style-shadow": "none",
16
+ "--button-style-shadow-color": "#000000",
17
+ "--button-style-contrast-color": "#000000",
18
+ "--button-style-radius": "8px",
19
+ "--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
20
+ "--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
21
+ "--link-gap": "14px",
22
+ "--link-inner-padding": "7px",
23
+ "--link-preview-thumbnail-width": "160px",
24
+ "--linkRadius": "8px",
25
+ "--profile-container-desktop-width": "580px",
26
+ "--profileBackground": "#eceef1",
27
+ "--background-contrast-color": "#000000",
28
+ "--bodyText": "#000000",
29
+ "--profileTitleText": "#000000",
30
+ "--profileDescriptionText": "#000000",
31
+ "--defaultAvatarBackground": "#000000",
32
+ "--defaultAvatarText": "#ffffff",
33
+ "--socialLinkFill": "#000000",
34
+ "--linkBackground": "#ffffff",
35
+ "--linkText": "#000000",
36
+ "--linkHoverBackground": "color-mix(in srgb, #ffffff 93%, #000000 7%)",
37
+ "--linkHoverText": "#000000",
38
+ "--linkShadow": "#000000",
39
+ "--bannerBackground": "#ffffff",
40
+ "--bannerText": "#000000",
41
+ "--desktop-frame-color": "color-mix(in srgb, #eceef1 88%, black 12%)",
42
+ "--profileFontFamilyPrimary":
43
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
44
+ "--profileFontFamilySecondary":
45
+ 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
46
+ "--header-font-family":
47
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
48
+ "--profileFontWeightNormal": "500",
49
+ "--profileFontWeightBold": "700",
50
+ "--profileDescriptionFontWeight": "500",
51
+ "--linkTextFontWeight": "500",
52
+ "--headerFontWeight": "700",
53
+ "--header-font-weight": "600",
54
+ "--embedLinkTextFontWeight": "500",
55
+ "--signupSubmitTextFontWeight": "700",
56
+ "--bannerFontWeight": "700",
57
+ "--headerFontSize": "normal",
58
+ "--header-bio-font-size": "16px",
59
+ "--embedLinkTextFontSize": "14px",
60
+ "--signupSubmitTextFontSize": "14px",
61
+ "--linkHeaderFontSize": "14px",
62
+ "--bannerFontSize": "14px",
63
+ "--profileDescriptionLineHeight": "1.5",
64
+ "--headerLineHeight": "1.5",
65
+ "--header-text-color": "#000000",
66
+ },
67
+ },
68
+ dark: {
69
+ name: "Dark",
70
+ variables: {
71
+ "--button-style-text": "#ffffff",
72
+ "--button-style-background": "#1f2937",
73
+ "--button-style-background-hover":
74
+ "color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
75
+ "--button-style-border": "none",
76
+ "--button-style-border-color": "transparent",
77
+ "--button-style-shadow": "none",
78
+ "--button-style-shadow-color": "#000000",
79
+ "--button-style-contrast-color": "#ffffff",
80
+ "--button-style-radius": "8px",
81
+ "--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
82
+ "--button-style-skeleton-color": "rgba(255, 255, 255, 0.1)",
83
+ "--link-gap": "14px",
84
+ "--link-inner-padding": "7px",
85
+ "--link-preview-thumbnail-width": "160px",
86
+ "--linkRadius": "8px",
87
+ "--profile-container-desktop-width": "580px",
88
+ "--profileBackground": "#111827",
89
+ "--background-contrast-color": "#ffffff",
90
+ "--bodyText": "#ffffff",
91
+ "--profileTitleText": "#ffffff",
92
+ "--profileDescriptionText": "#ffffff",
93
+ "--defaultAvatarBackground": "#ffffff",
94
+ "--defaultAvatarText": "#000000",
95
+ "--socialLinkFill": "#ffffff",
96
+ "--linkBackground": "#1f2937",
97
+ "--linkText": "#ffffff",
98
+ "--linkHoverBackground": "color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
99
+ "--linkHoverText": "#ffffff",
100
+ "--linkShadow": "#000000",
101
+ "--bannerBackground": "#1f2937",
102
+ "--bannerText": "#ffffff",
103
+ "--desktop-frame-color": "color-mix(in srgb, #111827 88%, white 12%)",
104
+ "--profileFontFamilyPrimary":
105
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
106
+ "--profileFontFamilySecondary":
107
+ 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
108
+ "--header-font-family":
109
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
110
+ "--profileFontWeightNormal": "500",
111
+ "--profileFontWeightBold": "700",
112
+ "--profileDescriptionFontWeight": "500",
113
+ "--linkTextFontWeight": "500",
114
+ "--headerFontWeight": "700",
115
+ "--header-font-weight": "600",
116
+ "--embedLinkTextFontWeight": "500",
117
+ "--signupSubmitTextFontWeight": "700",
118
+ "--bannerFontWeight": "700",
119
+ "--headerFontSize": "normal",
120
+ "--header-bio-font-size": "16px",
121
+ "--embedLinkTextFontSize": "14px",
122
+ "--signupSubmitTextFontSize": "14px",
123
+ "--linkHeaderFontSize": "14px",
124
+ "--bannerFontSize": "14px",
125
+ "--profileDescriptionLineHeight": "1.5",
126
+ "--headerLineHeight": "1.5",
127
+ "--header-text-color": "#ffffff",
128
+ },
129
+ },
130
+ purple: {
131
+ name: "Purple",
132
+ variables: {
133
+ "--button-style-text": "#ffffff",
134
+ "--button-style-background": "#7c3aed",
135
+ "--button-style-background-hover":
136
+ "color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
137
+ "--button-style-border": "none",
138
+ "--button-style-border-color": "transparent",
139
+ "--button-style-shadow": "none",
140
+ "--button-style-shadow-color": "#000000",
141
+ "--button-style-contrast-color": "#ede9fe",
142
+ "--button-style-radius": "16px",
143
+ "--button-style-inner-radius": "min(16px, max(4px, calc(16px - 8px)))",
144
+ "--button-style-skeleton-color": "rgba(124, 58, 237, 0.1)",
145
+ "--link-gap": "14px",
146
+ "--link-inner-padding": "7px",
147
+ "--link-preview-thumbnail-width": "160px",
148
+ "--linkRadius": "16px",
149
+ "--profile-container-desktop-width": "580px",
150
+ "--profileBackground": "#faf5ff",
151
+ "--background-contrast-color": "#1f2937",
152
+ "--bodyText": "#1f2937",
153
+ "--profileTitleText": "#1f2937",
154
+ "--profileDescriptionText": "#1f2937",
155
+ "--defaultAvatarBackground": "#7c3aed",
156
+ "--defaultAvatarText": "#ffffff",
157
+ "--socialLinkFill": "#1f2937",
158
+ "--linkBackground": "#7c3aed",
159
+ "--linkText": "#ffffff",
160
+ "--linkHoverBackground": "color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
161
+ "--linkHoverText": "#ffffff",
162
+ "--linkShadow": "#7c3aed",
163
+ "--bannerBackground": "#7c3aed",
164
+ "--bannerText": "#ffffff",
165
+ "--desktop-frame-color": "color-mix(in srgb, #faf5ff 88%, black 12%)",
166
+ "--profileFontFamilyPrimary":
167
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
168
+ "--profileFontFamilySecondary":
169
+ 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
170
+ "--header-font-family":
171
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
172
+ "--profileFontWeightNormal": "500",
173
+ "--profileFontWeightBold": "700",
174
+ "--profileDescriptionFontWeight": "500",
175
+ "--linkTextFontWeight": "500",
176
+ "--headerFontWeight": "700",
177
+ "--header-font-weight": "600",
178
+ "--embedLinkTextFontWeight": "500",
179
+ "--signupSubmitTextFontWeight": "700",
180
+ "--bannerFontWeight": "700",
181
+ "--headerFontSize": "normal",
182
+ "--header-bio-font-size": "16px",
183
+ "--embedLinkTextFontSize": "14px",
184
+ "--signupSubmitTextFontSize": "14px",
185
+ "--linkHeaderFontSize": "14px",
186
+ "--bannerFontSize": "14px",
187
+ "--profileDescriptionLineHeight": "1.5",
188
+ "--headerLineHeight": "1.5",
189
+ "--header-text-color": "#1f2937",
190
+ },
191
+ },
192
+ outline: {
193
+ name: "Outline Style",
194
+ variables: {
195
+ "--button-style-text": "#000000",
196
+ "--button-style-background": "transparent",
197
+ "--button-style-background-hover": "rgba(0, 0, 0, 0.05)",
198
+ "--button-style-border": "2px solid currentColor",
199
+ "--button-style-border-color": "#000000",
200
+ "--button-style-shadow": "none",
201
+ "--button-style-shadow-color": "#000000",
202
+ "--button-style-contrast-color": "#ffffff",
203
+ "--button-style-radius": "24px",
204
+ "--button-style-inner-radius": "min(24px, max(4px, calc(24px - 8px)))",
205
+ "--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
206
+ "--link-gap": "14px",
207
+ "--link-inner-padding": "7px",
208
+ "--link-preview-thumbnail-width": "160px",
209
+ "--linkRadius": "24px",
210
+ "--profile-container-desktop-width": "580px",
211
+ "--profileBackground": "#ffffff",
212
+ "--background-contrast-color": "#000000",
213
+ "--bodyText": "#000000",
214
+ "--profileTitleText": "#000000",
215
+ "--profileDescriptionText": "#000000",
216
+ "--defaultAvatarBackground": "#000000",
217
+ "--defaultAvatarText": "#ffffff",
218
+ "--socialLinkFill": "#000000",
219
+ "--linkBackground": "transparent",
220
+ "--linkText": "#000000",
221
+ "--linkHoverBackground": "rgba(0, 0, 0, 0.05)",
222
+ "--linkHoverText": "#000000",
223
+ "--linkShadow": "#000000",
224
+ "--bannerBackground": "#ffffff",
225
+ "--bannerText": "#000000",
226
+ "--desktop-frame-color": "color-mix(in srgb, #ffffff 88%, black 12%)",
227
+ "--profileFontFamilyPrimary":
228
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
229
+ "--profileFontFamilySecondary":
230
+ 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
231
+ "--header-font-family":
232
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
233
+ "--profileFontWeightNormal": "500",
234
+ "--profileFontWeightBold": "700",
235
+ "--profileDescriptionFontWeight": "500",
236
+ "--linkTextFontWeight": "500",
237
+ "--headerFontWeight": "700",
238
+ "--header-font-weight": "600",
239
+ "--embedLinkTextFontWeight": "500",
240
+ "--signupSubmitTextFontWeight": "700",
241
+ "--bannerFontWeight": "700",
242
+ "--headerFontSize": "normal",
243
+ "--header-bio-font-size": "16px",
244
+ "--embedLinkTextFontSize": "14px",
245
+ "--signupSubmitTextFontSize": "14px",
246
+ "--linkHeaderFontSize": "14px",
247
+ "--bannerFontSize": "14px",
248
+ "--profileDescriptionLineHeight": "1.5",
249
+ "--headerLineHeight": "1.5",
250
+ "--header-text-color": "#000000",
251
+ },
252
+ },
253
+ rounded: {
254
+ name: "Fully Rounded",
255
+ variables: {
256
+ "--button-style-text": "#ffffff",
257
+ "--button-style-background": "#059669",
258
+ "--button-style-background-hover":
259
+ "color-mix(in srgb, #059669 93%, #ffffff 7%)",
260
+ "--button-style-border": "none",
261
+ "--button-style-border-color": "transparent",
262
+ "--button-style-shadow": "none",
263
+ "--button-style-shadow-color": "#000000",
264
+ "--button-style-contrast-color": "#d1fae5",
265
+ "--button-style-radius": "28px",
266
+ "--button-style-inner-radius": "28px",
267
+ "--button-style-skeleton-color": "rgba(5, 150, 105, 0.1)",
268
+ "--link-gap": "14px",
269
+ "--link-inner-padding": "7px",
270
+ "--link-preview-thumbnail-width": "160px",
271
+ "--linkRadius": "28px",
272
+ "--profile-container-desktop-width": "580px",
273
+ "--profileBackground": "#ecfdf5",
274
+ "--background-contrast-color": "#1f2937",
275
+ "--bodyText": "#1f2937",
276
+ "--profileTitleText": "#1f2937",
277
+ "--profileDescriptionText": "#1f2937",
278
+ "--defaultAvatarBackground": "#059669",
279
+ "--defaultAvatarText": "#ffffff",
280
+ "--socialLinkFill": "#1f2937",
281
+ "--linkBackground": "#059669",
282
+ "--linkText": "#ffffff",
283
+ "--linkHoverBackground": "color-mix(in srgb, #059669 93%, #ffffff 7%)",
284
+ "--linkHoverText": "#ffffff",
285
+ "--linkShadow": "#059669",
286
+ "--bannerBackground": "#059669",
287
+ "--bannerText": "#ffffff",
288
+ "--desktop-frame-color": "color-mix(in srgb, #ecfdf5 88%, black 12%)",
289
+ "--profileFontFamilyPrimary":
290
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
291
+ "--profileFontFamilySecondary":
292
+ 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
293
+ "--header-font-family":
294
+ 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
295
+ "--profileFontWeightNormal": "500",
296
+ "--profileFontWeightBold": "700",
297
+ "--profileDescriptionFontWeight": "500",
298
+ "--linkTextFontWeight": "500",
299
+ "--headerFontWeight": "700",
300
+ "--header-font-weight": "600",
301
+ "--embedLinkTextFontWeight": "500",
302
+ "--signupSubmitTextFontWeight": "700",
303
+ "--bannerFontWeight": "700",
304
+ "--headerFontSize": "normal",
305
+ "--header-bio-font-size": "16px",
306
+ "--embedLinkTextFontSize": "14px",
307
+ "--signupSubmitTextFontSize": "14px",
308
+ "--linkHeaderFontSize": "14px",
309
+ "--bannerFontSize": "14px",
310
+ "--profileDescriptionLineHeight": "1.5",
311
+ "--headerLineHeight": "1.5",
312
+ "--header-text-color": "#1f2937",
313
+ },
314
+ },
315
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Utility functions for theme handling in dev mode
3
+ */
4
+
5
+ /**
6
+ * Merges theme CSS variables with preview props and creates a theme object
7
+ * compatible with the LinkApp runtime
8
+ */
9
+ export function mergeThemeProps(
10
+ themeVariables: Record<string, string>,
11
+ previewProps: Record<string, unknown> = {},
12
+ additionalProps: Record<string, unknown> = {}
13
+ ) {
14
+ return {
15
+ ...previewProps,
16
+ ...additionalProps,
17
+ theme: {
18
+ cssVariables: themeVariables,
19
+ // Legacy properties (deprecated) - derived from cssVariables
20
+ textColor: themeVariables["--button-style-text"] || "#000000",
21
+ backgroundColor: themeVariables["--button-style-background"] || "#ffffff",
22
+ borderRadius: themeVariables["--button-style-inner-radius"] || "12px",
23
+ borderColor: themeVariables["--button-style-border-color"] || "#e5e7eb",
24
+ backgroundHover: themeVariables["--button-style-background-hover"] || "#f3f4f6",
25
+ contrastColor: themeVariables["--button-style-contrast-color"] || "#ffffff",
26
+ textHoverColor: themeVariables["--linkHoverText"] || "#111827",
27
+ },
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Gets theme variables from URL parameters
33
+ */
34
+ export function getThemeFromUrl(presets: Record<string, Record<string, string>>): Record<string, string> {
35
+ const params = new URLSearchParams(window.location.search);
36
+ const themeParam = params.get('theme') || 'default';
37
+ return presets[themeParam] || presets.default;
38
+ }
@@ -0,0 +1,44 @@
1
+ import Sheet from "@/app/sheet";
2
+ import { StrictMode } from "react";
3
+ import { createRoot } from "react-dom/client";
4
+ import "@/app/globals.css";
5
+ import { THEME_PRESETS } from "../shared/theme-presets";
6
+ import { getThemeFromUrl, mergeThemeProps } from "../shared/theme-utils";
7
+
8
+ // Declare global window property for theme application
9
+ declare global {
10
+ interface Window {
11
+ __linkapp_applyTheme?: (variables: Record<string, string>) => void
12
+ }
13
+ }
14
+
15
+ // Preview props injected by dev server via Vite define
16
+ declare const __PREVIEW_PROPS__: Record<string, unknown>;
17
+
18
+ // Extract just the variables from THEME_PRESETS for theme lookups
19
+ const THEME_VARS = Object.fromEntries(
20
+ Object.entries(THEME_PRESETS).map(([key, { variables }]) => [key, variables])
21
+ );
22
+
23
+ // Get theme variables from URL
24
+ const themeVariables = getThemeFromUrl(THEME_VARS);
25
+
26
+ // Merge with preview props
27
+ const previewProps = __PREVIEW_PROPS__ || {};
28
+ const mergedProps = mergeThemeProps(themeVariables, previewProps);
29
+
30
+ // Apply theme CSS variables on mount
31
+ if (themeVariables && window.__linkapp_applyTheme) {
32
+ window.__linkapp_applyTheme(themeVariables);
33
+ }
34
+
35
+ const rootElement = document.getElementById("root");
36
+ if (!rootElement) {
37
+ throw new Error("Root element not found");
38
+ }
39
+
40
+ createRoot(rootElement).render(
41
+ <StrictMode>
42
+ <Sheet {...mergedProps} />
43
+ </StrictMode>,
44
+ );
@@ -0,0 +1,56 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Sheet - LinkApp</title>
7
+
8
+ <!-- iframe-resizer: Required for iframe height auto-adjustment -->
9
+ <script crossorigin src="https://unpkg.com/iframe-resizer@4.3.2/js/iframeResizer.contentWindow.js"></script>
10
+
11
+ <!-- Linktree theme variables will be injected here -->
12
+ <style id="linktree-theme"></style>
13
+
14
+ <script>
15
+ /**
16
+ * Helper function to convert CSS variables object to CSS string
17
+ * @param {Record<string, string>} vars - Object with CSS variable names as keys
18
+ * @returns {string} CSS string like "--var1: value1; --var2: value2;"
19
+ */
20
+ function renderCssVariables(vars) {
21
+ return Object.entries(vars)
22
+ .map((entry) => entry.join(': '))
23
+ .join('; ') + ';'
24
+ }
25
+
26
+ /**
27
+ * Apply theme CSS variables to :root
28
+ * Called once on mount from main.tsx
29
+ * @param {Record<string, string>} variables - CSS variables to apply
30
+ */
31
+ function applyTheme(variables) {
32
+ if (!variables || typeof variables !== 'object') {
33
+ return
34
+ }
35
+
36
+ // Get the style element where theme variables are injected
37
+ const themeStyle = document.getElementById('linktree-theme')
38
+
39
+ if (!themeStyle) {
40
+ console.warn('linktree-theme style element not found')
41
+ return
42
+ }
43
+
44
+ // Inject CSS variables into :root
45
+ themeStyle.textContent = ':root { ' + renderCssVariables(variables) + ' }'
46
+ }
47
+
48
+ // Export applyTheme to be used by main.tsx
49
+ window.__linkapp_applyTheme = applyTheme
50
+ </script>
51
+ </head>
52
+ <body>
53
+ <div id="root"></div>
54
+ <script type="module" src="/sheet/main.tsx"></script>
55
+ </body>
56
+ </html>
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAMA,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAKD,wBAAsB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,iBA+D5E"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAUA,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAKD,wBAAsB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,iBAoE5E"}