@linktr.ee/linkapp 0.0.22 → 0.0.24

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 (76) hide show
  1. package/dev-server/README.md +5 -5
  2. package/dev-server/{vite-env.d.ts → env.d.ts} +1 -1
  3. package/dev-server/featured/main.tsx +32 -311
  4. package/dev-server/package.json +5 -6
  5. package/dev-server/postcss/tailwind-source-fallback.js +94 -0
  6. package/dev-server/postcss.config.mjs +28 -3
  7. package/dev-server/preview/Preview.tsx +114 -339
  8. package/dev-server/preview/preview.css +3 -0
  9. package/dev-server/rsbuild.config.ts +45 -0
  10. package/dev-server/shared/theme-presets.ts +315 -0
  11. package/dev-server/shared/theme-utils.ts +38 -0
  12. package/dev-server/sheet/main.tsx +44 -0
  13. package/dev-server/{classic.html → sheet.html} +2 -2
  14. package/dist/commands/add.d.ts.map +1 -1
  15. package/dist/commands/add.js +20 -12
  16. package/dist/commands/add.js.map +1 -1
  17. package/dist/commands/build.d.ts.map +1 -1
  18. package/dist/commands/build.js +55 -36
  19. package/dist/commands/build.js.map +1 -1
  20. package/dist/commands/deploy.d.ts.map +1 -1
  21. package/dist/commands/deploy.js +58 -45
  22. package/dist/commands/deploy.js.map +1 -1
  23. package/dist/commands/dev.d.ts.map +1 -1
  24. package/dist/commands/dev.js +541 -128
  25. package/dist/commands/dev.js.map +1 -1
  26. package/dist/commands/login.d.ts.map +1 -1
  27. package/dist/commands/login.js +19 -9
  28. package/dist/commands/login.js.map +1 -1
  29. package/dist/commands/logout.d.ts.map +1 -1
  30. package/dist/commands/logout.js +9 -4
  31. package/dist/commands/logout.js.map +1 -1
  32. package/dist/commands/test-url-match-rules.d.ts.map +1 -1
  33. package/dist/commands/test-url-match-rules.js +24 -13
  34. package/dist/commands/test-url-match-rules.js.map +1 -1
  35. package/dist/lib/build/detect-layouts.d.ts +1 -1
  36. package/dist/lib/build/detect-layouts.d.ts.map +1 -1
  37. package/dist/lib/build/detect-layouts.js +8 -7
  38. package/dist/lib/build/detect-layouts.js.map +1 -1
  39. package/dist/lib/deploy/pack-project.js +1 -1
  40. package/dist/lib/deploy/pack-project.js.map +1 -1
  41. package/dist/lib/deploy/validation.d.ts.map +1 -1
  42. package/dist/lib/deploy/validation.js +8 -5
  43. package/dist/lib/deploy/validation.js.map +1 -1
  44. package/dist/lib/rsbuild/config-factory.d.ts +24 -0
  45. package/dist/lib/rsbuild/config-factory.d.ts.map +1 -0
  46. package/dist/lib/rsbuild/config-factory.js +135 -0
  47. package/dist/lib/rsbuild/config-factory.js.map +1 -0
  48. package/dist/lib/rsbuild/plugins/asset-versioning.d.ts +11 -0
  49. package/dist/lib/rsbuild/plugins/asset-versioning.d.ts.map +1 -0
  50. package/dist/lib/rsbuild/plugins/asset-versioning.js +62 -0
  51. package/dist/lib/rsbuild/plugins/asset-versioning.js.map +1 -0
  52. package/dist/lib/rsbuild/plugins/copy-public.d.ts +11 -0
  53. package/dist/lib/rsbuild/plugins/copy-public.d.ts.map +1 -0
  54. package/dist/lib/rsbuild/plugins/copy-public.js +32 -0
  55. package/dist/lib/rsbuild/plugins/copy-public.js.map +1 -0
  56. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts +12 -0
  57. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.d.ts.map +1 -0
  58. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js +60 -0
  59. package/dist/lib/rsbuild/postcss/tailwind-source-fallback.js.map +1 -0
  60. package/dist/lib/utils/setup-runtime.d.ts.map +1 -1
  61. package/dist/lib/utils/setup-runtime.js +60 -26
  62. package/dist/lib/utils/setup-runtime.js.map +1 -1
  63. package/dist/lib/vite/config-factory.d.ts.map +1 -1
  64. package/dist/lib/vite/config-factory.js +5 -1
  65. package/dist/lib/vite/config-factory.js.map +1 -1
  66. package/dist/lib/vite/plugins/copy-public.d.ts +12 -0
  67. package/dist/lib/vite/plugins/copy-public.d.ts.map +1 -0
  68. package/dist/lib/vite/plugins/copy-public.js +31 -0
  69. package/dist/lib/vite/plugins/copy-public.js.map +1 -0
  70. package/dist/schema/config.schema.d.ts +18 -1
  71. package/dist/schema/config.schema.d.ts.map +1 -1
  72. package/dist/schema/config.schema.js +1 -0
  73. package/dist/schema/config.schema.js.map +1 -1
  74. package/package.json +7 -3
  75. package/dev-server/classic/main.tsx +0 -346
  76. package/dev-server/vite.config.ts +0 -34
@@ -1,13 +1,13 @@
1
1
  # Development Server Setup
2
2
 
3
- This directory contains a custom Vite-based development server for previewing LinkApp components with multiple routes and iframe embeds.
3
+ This directory contains a custom Rsbuild-based development server for previewing LinkApp components with multiple routes and iframe embeds.
4
4
 
5
5
  ## Structure
6
6
 
7
7
  ```
8
8
  dev-server/
9
9
  ├── index.html # Root preview page entry
10
- ├── vite.config.ts # Vite configuration (MPA setup)
10
+ ├── rsbuild.config.ts # Rsbuild configuration
11
11
  ├── server.ts # TypeScript server launcher
12
12
  ├── preview/
13
13
  │ ├── main.tsx # Preview page React entry
@@ -44,12 +44,12 @@ dev-server/
44
44
  npm run dev:preview
45
45
  ```
46
46
 
47
- This command uses `tsx` to run the TypeScript server script, which programmatically starts Vite with the custom configuration.
47
+ This command uses `tsx` to run the TypeScript server script, which programmatically starts Rsbuild with the custom configuration.
48
48
 
49
49
  ## Technical Details
50
50
 
51
51
  ### Multi-Page Application (MPA)
52
- The setup uses Vite's MPA capability with multiple HTML entry points:
52
+ The setup uses Rsbuild's MPA capability with multiple HTML entry points:
53
53
  - Root: `index.html` → Preview page
54
54
  - `/classic/`: `classic/index.html` → Classic layout
55
55
  - `/featured/`: `featured/index.html` → Featured layout
@@ -77,6 +77,6 @@ Server runs on port 3000 with `strictPort: true` to match requirements.
77
77
  This implementation follows a clean separation of concerns:
78
78
  - Original app files (`1-demo/app/*`) remain untouched
79
79
  - New dev-server directory contains all preview infrastructure
80
- - Uses Vite's native MPA support for clean routing (no client-side router)
80
+ - Uses Rsbuild's native MPA support for clean routing (no client-side router)
81
81
  - TypeScript throughout for type safety
82
82
  - Programmatic server creation for flexibility
@@ -1,4 +1,4 @@
1
- /// <reference types="vite/client" />
1
+ /// <reference types="@rsbuild/core/types" />
2
2
 
3
3
  import type { LinkAppSettings } from '../src/types'
4
4
 
@@ -2,14 +2,16 @@ import Featured from "@/app/featured";
2
2
  import { StrictMode } from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
  import "@/app/globals.css";
5
+ import { THEME_PRESETS } from "../shared/theme-presets";
6
+ import { getThemeFromUrl, mergeThemeProps } from "../shared/theme-utils";
5
7
 
6
- // Conditionally import Layout if it exists
7
- const layoutModules = import.meta.glob("@/app/layout.{ts,tsx}", {
8
- eager: true,
9
- });
10
- const Layout = Object.values(layoutModules)[0]?.default as
11
- | React.ComponentType<{ children: React.ReactNode; theme?: any }>
12
- | undefined;
8
+ // Try to import FeaturedCarousel if it exists
9
+ let FeaturedCarousel: React.ComponentType<any> | null = null;
10
+ try {
11
+ FeaturedCarousel = require("@/app/featured-carousel").default;
12
+ } catch (e) {
13
+ // featured-carousel.tsx doesn't exist, that's ok
14
+ }
13
15
 
14
16
  // Declare global window property for theme application
15
17
  declare global {
@@ -21,307 +23,21 @@ declare global {
21
23
  // Preview props injected by dev server via Vite define
22
24
  declare const __PREVIEW_PROPS__: Record<string, unknown>;
23
25
 
24
- // Theme presets matching Preview.tsx
25
- const THEME_PRESETS: Record<string, Record<string, string>> = {
26
- default: {
27
- "--button-style-text": "#000000",
28
- "--button-style-background": "#ffffff",
29
- "--button-style-background-hover": "color-mix(in srgb, #ffffff 93%, #000000 7%)",
30
- "--button-style-border": "none",
31
- "--button-style-border-color": "transparent",
32
- "--button-style-shadow": "none",
33
- "--button-style-shadow-color": "#000000",
34
- "--button-style-contrast-color": "#000000",
35
- "--button-style-radius": "8px",
36
- "--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
37
- "--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
38
- "--link-gap": "14px",
39
- "--link-inner-padding": "7px",
40
- "--link-preview-thumbnail-width": "160px",
41
- "--linkRadius": "8px",
42
- "--profile-container-desktop-width": "580px",
43
- "--profileBackground": "#eceef1",
44
- "--background-contrast-color": "#000000",
45
- "--bodyText": "#000000",
46
- "--profileTitleText": "#000000",
47
- "--profileDescriptionText": "#000000",
48
- "--defaultAvatarBackground": "#000000",
49
- "--defaultAvatarText": "#ffffff",
50
- "--socialLinkFill": "#000000",
51
- "--linkBackground": "#ffffff",
52
- "--linkText": "#000000",
53
- "--linkHoverBackground": "color-mix(in srgb, #ffffff 93%, #000000 7%)",
54
- "--linkHoverText": "#000000",
55
- "--linkShadow": "#000000",
56
- "--bannerBackground": "#ffffff",
57
- "--bannerText": "#000000",
58
- "--desktop-frame-color": "color-mix(in srgb, #eceef1 88%, black 12%)",
59
- "--profileFontFamilyPrimary": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
60
- "--profileFontFamilySecondary": 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
61
- "--header-font-family": '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
- dark: {
82
- "--button-style-text": "#ffffff",
83
- "--button-style-background": "#1f2937",
84
- "--button-style-background-hover": "color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
85
- "--button-style-border": "none",
86
- "--button-style-border-color": "transparent",
87
- "--button-style-shadow": "none",
88
- "--button-style-shadow-color": "#000000",
89
- "--button-style-contrast-color": "#ffffff",
90
- "--button-style-radius": "8px",
91
- "--button-style-inner-radius": "min(8px, max(4px, calc(8px - 8px)))",
92
- "--button-style-skeleton-color": "rgba(255, 255, 255, 0.1)",
93
- "--link-gap": "14px",
94
- "--link-inner-padding": "7px",
95
- "--link-preview-thumbnail-width": "160px",
96
- "--linkRadius": "8px",
97
- "--profile-container-desktop-width": "580px",
98
- "--profileBackground": "#111827",
99
- "--background-contrast-color": "#ffffff",
100
- "--bodyText": "#ffffff",
101
- "--profileTitleText": "#ffffff",
102
- "--profileDescriptionText": "#ffffff",
103
- "--defaultAvatarBackground": "#ffffff",
104
- "--defaultAvatarText": "#000000",
105
- "--socialLinkFill": "#ffffff",
106
- "--linkBackground": "#1f2937",
107
- "--linkText": "#ffffff",
108
- "--linkHoverBackground": "color-mix(in srgb, #1f2937 93%, #ffffff 7%)",
109
- "--linkHoverText": "#ffffff",
110
- "--linkShadow": "#000000",
111
- "--bannerBackground": "#1f2937",
112
- "--bannerText": "#ffffff",
113
- "--desktop-frame-color": "color-mix(in srgb, #111827 88%, white 12%)",
114
- "--profileFontFamilyPrimary": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
115
- "--profileFontFamilySecondary": 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
116
- "--header-font-family": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
117
- "--profileFontWeightNormal": "500",
118
- "--profileFontWeightBold": "700",
119
- "--profileDescriptionFontWeight": "500",
120
- "--linkTextFontWeight": "500",
121
- "--headerFontWeight": "700",
122
- "--header-font-weight": "600",
123
- "--embedLinkTextFontWeight": "500",
124
- "--signupSubmitTextFontWeight": "700",
125
- "--bannerFontWeight": "700",
126
- "--headerFontSize": "normal",
127
- "--header-bio-font-size": "16px",
128
- "--embedLinkTextFontSize": "14px",
129
- "--signupSubmitTextFontSize": "14px",
130
- "--linkHeaderFontSize": "14px",
131
- "--bannerFontSize": "14px",
132
- "--profileDescriptionLineHeight": "1.5",
133
- "--headerLineHeight": "1.5",
134
- "--header-text-color": "#ffffff",
135
- },
136
- purple: {
137
- "--button-style-text": "#ffffff",
138
- "--button-style-background": "#7c3aed",
139
- "--button-style-background-hover": "color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
140
- "--button-style-border": "none",
141
- "--button-style-border-color": "transparent",
142
- "--button-style-shadow": "none",
143
- "--button-style-shadow-color": "#000000",
144
- "--button-style-contrast-color": "#ede9fe",
145
- "--button-style-radius": "16px",
146
- "--button-style-inner-radius": "min(16px, max(4px, calc(16px - 8px)))",
147
- "--button-style-skeleton-color": "rgba(124, 58, 237, 0.1)",
148
- "--link-gap": "14px",
149
- "--link-inner-padding": "7px",
150
- "--link-preview-thumbnail-width": "160px",
151
- "--linkRadius": "16px",
152
- "--profile-container-desktop-width": "580px",
153
- "--profileBackground": "#faf5ff",
154
- "--background-contrast-color": "#1f2937",
155
- "--bodyText": "#1f2937",
156
- "--profileTitleText": "#1f2937",
157
- "--profileDescriptionText": "#1f2937",
158
- "--defaultAvatarBackground": "#7c3aed",
159
- "--defaultAvatarText": "#ffffff",
160
- "--socialLinkFill": "#1f2937",
161
- "--linkBackground": "#7c3aed",
162
- "--linkText": "#ffffff",
163
- "--linkHoverBackground": "color-mix(in srgb, #7c3aed 93%, #ffffff 7%)",
164
- "--linkHoverText": "#ffffff",
165
- "--linkShadow": "#7c3aed",
166
- "--bannerBackground": "#7c3aed",
167
- "--bannerText": "#ffffff",
168
- "--desktop-frame-color": "color-mix(in srgb, #faf5ff 88%, black 12%)",
169
- "--profileFontFamilyPrimary": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
170
- "--profileFontFamilySecondary": 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
171
- "--header-font-family": '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
- outline: {
192
- "--button-style-text": "#000000",
193
- "--button-style-background": "transparent",
194
- "--button-style-background-hover": "rgba(0, 0, 0, 0.05)",
195
- "--button-style-border": "2px solid currentColor",
196
- "--button-style-border-color": "#000000",
197
- "--button-style-shadow": "none",
198
- "--button-style-shadow-color": "#000000",
199
- "--button-style-contrast-color": "#ffffff",
200
- "--button-style-radius": "24px",
201
- "--button-style-inner-radius": "min(24px, max(4px, calc(24px - 8px)))",
202
- "--button-style-skeleton-color": "rgba(0, 0, 0, 0.05)",
203
- "--link-gap": "14px",
204
- "--link-inner-padding": "7px",
205
- "--link-preview-thumbnail-width": "160px",
206
- "--linkRadius": "24px",
207
- "--profile-container-desktop-width": "580px",
208
- "--profileBackground": "#ffffff",
209
- "--background-contrast-color": "#000000",
210
- "--bodyText": "#000000",
211
- "--profileTitleText": "#000000",
212
- "--profileDescriptionText": "#000000",
213
- "--defaultAvatarBackground": "#000000",
214
- "--defaultAvatarText": "#ffffff",
215
- "--socialLinkFill": "#000000",
216
- "--linkBackground": "transparent",
217
- "--linkText": "#000000",
218
- "--linkHoverBackground": "rgba(0, 0, 0, 0.05)",
219
- "--linkHoverText": "#000000",
220
- "--linkShadow": "#000000",
221
- "--bannerBackground": "#ffffff",
222
- "--bannerText": "#000000",
223
- "--desktop-frame-color": "color-mix(in srgb, #ffffff 88%, black 12%)",
224
- "--profileFontFamilyPrimary": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
225
- "--profileFontFamilySecondary": 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
226
- "--header-font-family": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
227
- "--profileFontWeightNormal": "500",
228
- "--profileFontWeightBold": "700",
229
- "--profileDescriptionFontWeight": "500",
230
- "--linkTextFontWeight": "500",
231
- "--headerFontWeight": "700",
232
- "--header-font-weight": "600",
233
- "--embedLinkTextFontWeight": "500",
234
- "--signupSubmitTextFontWeight": "700",
235
- "--bannerFontWeight": "700",
236
- "--headerFontSize": "normal",
237
- "--header-bio-font-size": "16px",
238
- "--embedLinkTextFontSize": "14px",
239
- "--signupSubmitTextFontSize": "14px",
240
- "--linkHeaderFontSize": "14px",
241
- "--bannerFontSize": "14px",
242
- "--profileDescriptionLineHeight": "1.5",
243
- "--headerLineHeight": "1.5",
244
- "--header-text-color": "#000000",
245
- },
246
- rounded: {
247
- "--button-style-text": "#ffffff",
248
- "--button-style-background": "#059669",
249
- "--button-style-background-hover": "color-mix(in srgb, #059669 93%, #ffffff 7%)",
250
- "--button-style-border": "none",
251
- "--button-style-border-color": "transparent",
252
- "--button-style-shadow": "none",
253
- "--button-style-shadow-color": "#000000",
254
- "--button-style-contrast-color": "#d1fae5",
255
- "--button-style-radius": "28px",
256
- "--button-style-inner-radius": "28px",
257
- "--button-style-skeleton-color": "rgba(5, 150, 105, 0.1)",
258
- "--link-gap": "14px",
259
- "--link-inner-padding": "7px",
260
- "--link-preview-thumbnail-width": "160px",
261
- "--linkRadius": "28px",
262
- "--profile-container-desktop-width": "580px",
263
- "--profileBackground": "#ecfdf5",
264
- "--background-contrast-color": "#1f2937",
265
- "--bodyText": "#1f2937",
266
- "--profileTitleText": "#1f2937",
267
- "--profileDescriptionText": "#1f2937",
268
- "--defaultAvatarBackground": "#059669",
269
- "--defaultAvatarText": "#ffffff",
270
- "--socialLinkFill": "#1f2937",
271
- "--linkBackground": "#059669",
272
- "--linkText": "#ffffff",
273
- "--linkHoverBackground": "color-mix(in srgb, #059669 93%, #ffffff 7%)",
274
- "--linkHoverText": "#ffffff",
275
- "--linkShadow": "#059669",
276
- "--bannerBackground": "#059669",
277
- "--bannerText": "#ffffff",
278
- "--desktop-frame-color": "color-mix(in srgb, #ecfdf5 88%, black 12%)",
279
- "--profileFontFamilyPrimary": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
280
- "--profileFontFamilySecondary": 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
281
- "--header-font-family": 'Link Sans Product, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
282
- "--profileFontWeightNormal": "500",
283
- "--profileFontWeightBold": "700",
284
- "--profileDescriptionFontWeight": "500",
285
- "--linkTextFontWeight": "500",
286
- "--headerFontWeight": "700",
287
- "--header-font-weight": "600",
288
- "--embedLinkTextFontWeight": "500",
289
- "--signupSubmitTextFontWeight": "700",
290
- "--bannerFontWeight": "700",
291
- "--headerFontSize": "normal",
292
- "--header-bio-font-size": "16px",
293
- "--embedLinkTextFontSize": "14px",
294
- "--signupSubmitTextFontSize": "14px",
295
- "--linkHeaderFontSize": "14px",
296
- "--bannerFontSize": "14px",
297
- "--profileDescriptionLineHeight": "1.5",
298
- "--headerLineHeight": "1.5",
299
- "--header-text-color": "#1f2937",
300
- },
301
- };
26
+ // Extract just the variables from THEME_PRESETS for theme lookups
27
+ const THEME_VARS = Object.fromEntries(
28
+ Object.entries(THEME_PRESETS).map(([key, { variables }]) => [key, variables])
29
+ );
302
30
 
303
- // Get theme from URL parameter
31
+ // Get theme variables and groupLayoutOption from URL
304
32
  const params = new URLSearchParams(window.location.search);
305
- const themeParam = params.get('theme') || 'default';
306
- const themeVariables = THEME_PRESETS[themeParam] || THEME_PRESETS.default;
33
+ const groupLayoutOptionParam = params.get('groupLayoutOption');
34
+ const themeVariables = getThemeFromUrl(THEME_VARS);
307
35
 
36
+ // Merge with preview props and add groupLayoutOption
308
37
  const previewProps = __PREVIEW_PROPS__ || {};
309
-
310
- // Merge theme from URL with preview props
311
- const mergedProps = {
312
- ...previewProps,
313
- theme: {
314
- cssVariables: themeVariables,
315
- // Legacy properties (deprecated) - derived from cssVariables
316
- textColor: themeVariables["--button-style-text"] || "#000000",
317
- backgroundColor: themeVariables["--button-style-background"] || "#ffffff",
318
- borderRadius: themeVariables["--button-style-inner-radius"] || "12px",
319
- borderColor: themeVariables["--button-style-border-color"] || "#e5e7eb",
320
- backgroundHover: themeVariables["--button-style-background-hover"] || "#f3f4f6",
321
- contrastColor: themeVariables["--button-style-contrast-color"] || "#ffffff",
322
- textHoverColor: themeVariables["--linkHoverText"] || "#111827",
323
- },
324
- };
38
+ const mergedProps = mergeThemeProps(themeVariables, previewProps, {
39
+ groupLayoutOption: groupLayoutOptionParam || undefined,
40
+ });
325
41
 
326
42
  // Apply theme CSS variables on mount
327
43
  if (themeVariables && window.__linkapp_applyTheme) {
@@ -333,14 +49,19 @@ if (!rootElement) {
333
49
  throw new Error("Root element not found");
334
50
  }
335
51
 
52
+ // Select the appropriate component based on groupLayoutOption parameter
53
+ const LayoutComponent = (groupLayoutOptionParam === 'carousel' && FeaturedCarousel)
54
+ ? FeaturedCarousel
55
+ : Featured;
56
+
57
+ console.log('[Featured Dev Server] Rendering:', {
58
+ groupLayoutOption: groupLayoutOptionParam,
59
+ component: groupLayoutOptionParam === 'carousel' && FeaturedCarousel ? 'FeaturedCarousel' : 'Featured',
60
+ hasFeaturedCarousel: !!FeaturedCarousel,
61
+ });
62
+
336
63
  createRoot(rootElement).render(
337
64
  <StrictMode>
338
- {Layout ? (
339
- <Layout theme={mergedProps.theme}>
340
- <Featured {...mergedProps} />
341
- </Layout>
342
- ) : (
343
- <Featured {...mergedProps} />
344
- )}
65
+ <LayoutComponent {...mergedProps} />
345
66
  </StrictMode>,
346
67
  );
@@ -10,24 +10,23 @@
10
10
  "@radix-ui/react-dialog": "^1.1.15",
11
11
  "@radix-ui/react-portal": "^1.1.4",
12
12
  "@radix-ui/react-tabs": "^1.1.7",
13
- "@tailwindcss/vite": "^4.1.14",
13
+ "@tailwindcss/postcss": "^4.1.14",
14
14
  "class-variance-authority": "^0.7.1",
15
15
  "clsx": "^2.1.1",
16
16
  "iframe-resizer-react": "^1.1.0",
17
17
  "lucide-react": "^0.545.0",
18
+ "postcss": "^8.5.6",
18
19
  "react": "^19.1.0",
19
20
  "react-dom": "^19.1.0",
20
21
  "tailwind-merge": "^3.3.1"
21
22
  },
22
23
  "devDependencies": {
23
- "@tailwindcss/postcss": "^4.1.14",
24
+ "@rsbuild/core": "^1.1.14",
25
+ "@rsbuild/plugin-react": "^1.1.0",
24
26
  "@types/react": "^19.2.2",
25
27
  "@types/react-dom": "^19",
26
- "@vitejs/plugin-react": "^4.3.4",
27
- "postcss": "^8.5.6",
28
28
  "tailwindcss": "^4",
29
29
  "tw-animate-css": "^1.4.0",
30
- "typescript": "^5",
31
- "vite": "^6.0.3"
30
+ "typescript": "^5"
32
31
  }
33
32
  }
@@ -0,0 +1,94 @@
1
+ import { dirname, relative } from 'node:path'
2
+ import postcss from 'postcss'
3
+
4
+ const DEFAULT_GLOB = '**/*.{ts,tsx,js,jsx,mdx,html}'
5
+
6
+ function toPosixPath(value) {
7
+ return value.replace(/\\/g, '/')
8
+ }
9
+
10
+ export function createTailwindSourceFallback(options = {}) {
11
+ const { projectRoot, glob = DEFAULT_GLOB } = options
12
+
13
+ if (!projectRoot) {
14
+ const noop = () => {
15
+ const postcssPlugin = {
16
+ postcssPlugin: 'linkapp:tailwind-source-fallback:noop',
17
+ Once() {},
18
+ }
19
+
20
+ postcssPlugin.postcss = true
21
+ return postcssPlugin
22
+ }
23
+
24
+ noop.postcss = true
25
+ noop.__linkappTailwindSource = true
26
+ return noop
27
+ }
28
+
29
+ const plugin = () => {
30
+ const postcssPlugin = {
31
+ postcssPlugin: 'linkapp:tailwind-source-fallback',
32
+ Once(root, { result }) {
33
+ const sourceFile = typeof result.opts.from === 'string' ? result.opts.from : null
34
+ if (!sourceFile) {
35
+ return
36
+ }
37
+
38
+ const normalizedSourceFile = toPosixPath(sourceFile)
39
+ const normalizedProjectRoot = toPosixPath(
40
+ projectRoot.endsWith('/') ? projectRoot : `${projectRoot}/`
41
+ )
42
+
43
+ if (!normalizedSourceFile.startsWith(normalizedProjectRoot)) {
44
+ return
45
+ }
46
+
47
+ let hasSourceDirective = false
48
+ root.walkAtRules('source', () => {
49
+ hasSourceDirective = true
50
+ return false
51
+ })
52
+
53
+ if (hasSourceDirective) {
54
+ return
55
+ }
56
+
57
+ const cssDir = dirname(sourceFile)
58
+ const relativeToRoot = relative(cssDir, projectRoot)
59
+ const baseSegment = relativeToRoot === '' ? '.' : relativeToRoot
60
+ const normalizedBase = toPosixPath(baseSegment)
61
+ const trimmedBase = normalizedBase.replace(/\/$/, '')
62
+
63
+ const sourcePath =
64
+ trimmedBase === '.' || trimmedBase === ''
65
+ ? `./${glob}`
66
+ : `${trimmedBase}/${glob}`
67
+
68
+ const atRule = postcss.atRule({
69
+ name: 'source',
70
+ params: `"${sourcePath}"`,
71
+ })
72
+
73
+ let lastImport
74
+ root.walkAtRules('import', (node) => {
75
+ lastImport = node
76
+ })
77
+
78
+ if (lastImport) {
79
+ lastImport.after(atRule)
80
+ } else {
81
+ root.prepend(atRule)
82
+ }
83
+ },
84
+ }
85
+
86
+ postcssPlugin.postcss = true
87
+ return postcssPlugin
88
+ }
89
+
90
+ plugin.postcss = true
91
+ plugin.__linkappTailwindSource = true
92
+
93
+ return plugin
94
+ }
@@ -1,5 +1,30 @@
1
+ import { fileURLToPath } from 'url'
2
+ import { dirname, resolve } from 'path'
3
+ import tailwindcss from '@tailwindcss/postcss'
4
+ import { createTailwindSourceFallback } from './postcss/tailwind-source-fallback.js'
5
+
6
+ const __filename = fileURLToPath(import.meta.url)
7
+ const __dirname = dirname(__filename)
8
+
9
+ const userProjectRoot = process.env.LINKAPP_USER_PROJECT_PATH
10
+ const projectRoot = userProjectRoot ? resolve(userProjectRoot) : null
11
+
12
+ const plugins = []
13
+
14
+ if (projectRoot) {
15
+ plugins.push(
16
+ createTailwindSourceFallback({
17
+ projectRoot,
18
+ })
19
+ )
20
+ }
21
+
22
+ plugins.push(
23
+ tailwindcss({
24
+ base: __dirname,
25
+ })
26
+ )
27
+
1
28
  export default {
2
- plugins: {
3
- '@tailwindcss/postcss': {},
4
- },
29
+ plugins,
5
30
  }