@linktr.ee/linkapp 0.0.9 → 0.0.11

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 (82) hide show
  1. package/dev-server/classic/main.tsx +46 -8
  2. package/dev-server/classic.html +58 -0
  3. package/dev-server/components/ui/dialog.tsx +19 -42
  4. package/dev-server/components/ui/tabs.tsx +6 -6
  5. package/dev-server/featured/main.tsx +46 -8
  6. package/dev-server/featured.html +58 -0
  7. package/dev-server/lib/utils.ts +2 -2
  8. package/dev-server/preview/Preview.tsx +428 -15
  9. package/dev-server/vite.config.ts +11 -11
  10. package/dist/cli.js +5 -7
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/add.d.ts.map +1 -1
  13. package/dist/commands/add.js +3 -3
  14. package/dist/commands/add.js.map +1 -1
  15. package/dist/commands/deploy.d.ts.map +1 -1
  16. package/dist/commands/deploy.js +10 -4
  17. package/dist/commands/deploy.js.map +1 -1
  18. package/dist/commands/dev.d.ts.map +1 -1
  19. package/dist/commands/dev.js +15 -1
  20. package/dist/commands/dev.js.map +1 -1
  21. package/dist/commands/login.d.ts.map +1 -1
  22. package/dist/commands/login.js.map +1 -1
  23. package/dist/components/ThemeStyle.d.ts +30 -0
  24. package/dist/components/ThemeStyle.d.ts.map +1 -0
  25. package/dist/components/ThemeStyle.js +33 -0
  26. package/dist/components/ThemeStyle.js.map +1 -0
  27. package/dist/components/index.d.ts +2 -0
  28. package/dist/components/index.d.ts.map +1 -0
  29. package/dist/components/index.js +2 -0
  30. package/dist/components/index.js.map +1 -0
  31. package/dist/lib/build/detect-layouts.d.ts +2 -2
  32. package/dist/lib/build/detect-layouts.d.ts.map +1 -1
  33. package/dist/lib/build/detect-layouts.js +14 -25
  34. package/dist/lib/build/detect-layouts.js.map +1 -1
  35. package/dist/lib/config/load-config.d.ts +9 -0
  36. package/dist/lib/config/load-config.d.ts.map +1 -0
  37. package/dist/lib/config/load-config.js +31 -0
  38. package/dist/lib/config/load-config.js.map +1 -0
  39. package/dist/lib/deploy/generate-manifest-files.d.ts.map +1 -1
  40. package/dist/lib/deploy/generate-manifest-files.js +20 -35
  41. package/dist/lib/deploy/generate-manifest-files.js.map +1 -1
  42. package/dist/lib/deploy/pack-project.d.ts.map +1 -1
  43. package/dist/lib/deploy/pack-project.js +32 -5
  44. package/dist/lib/deploy/pack-project.js.map +1 -1
  45. package/dist/lib/deploy/upload.d.ts +1 -0
  46. package/dist/lib/deploy/upload.d.ts.map +1 -1
  47. package/dist/lib/deploy/upload.js +17 -7
  48. package/dist/lib/deploy/upload.js.map +1 -1
  49. package/dist/lib/deploy/validation.d.ts.map +1 -1
  50. package/dist/lib/deploy/validation.js +4 -61
  51. package/dist/lib/deploy/validation.js.map +1 -1
  52. package/dist/lib/utils/setup-runtime.d.ts.map +1 -1
  53. package/dist/lib/utils/setup-runtime.js +46 -19
  54. package/dist/lib/utils/setup-runtime.js.map +1 -1
  55. package/dist/lib/vite/config-factory.d.ts.map +1 -1
  56. package/dist/lib/vite/config-factory.js +2 -2
  57. package/dist/lib/vite/config-factory.js.map +1 -1
  58. package/dist/lib/vite/plugins/asset-versioning.d.ts.map +1 -1
  59. package/dist/lib/vite/plugins/asset-versioning.js +4 -2
  60. package/dist/lib/vite/plugins/asset-versioning.js.map +1 -1
  61. package/dist/schema/config.schema.d.ts +126 -99
  62. package/dist/schema/config.schema.d.ts.map +1 -1
  63. package/dist/schema/config.schema.js +140 -20
  64. package/dist/schema/config.schema.js.map +1 -1
  65. package/dist/sdk/index.d.ts +21 -0
  66. package/dist/sdk/index.d.ts.map +1 -0
  67. package/dist/sdk/index.js +21 -0
  68. package/dist/sdk/index.js.map +1 -0
  69. package/dist/sdk/send-message.d.ts +16 -0
  70. package/dist/sdk/send-message.d.ts.map +1 -0
  71. package/dist/sdk/send-message.js +34 -0
  72. package/dist/sdk/send-message.js.map +1 -0
  73. package/dist/sdk/use-open-popup.d.ts +23 -0
  74. package/dist/sdk/use-open-popup.d.ts.map +1 -0
  75. package/dist/sdk/use-open-popup.js +29 -0
  76. package/dist/sdk/use-open-popup.js.map +1 -0
  77. package/dist/types.d.ts +162 -30
  78. package/dist/types.d.ts.map +1 -1
  79. package/dist/types.js +41 -1
  80. package/dist/types.js.map +1 -1
  81. package/package.json +11 -3
  82. package/runtime/index.html +58 -0
@@ -1,13 +1,47 @@
1
+ import Classic from "@/app/classic";
1
2
  import { StrictMode } from "react";
2
3
  import { createRoot } from "react-dom/client";
3
- import Layout from "@/app/layout";
4
- import Classic from "@/app/classic";
5
4
  import "@/app/globals.css";
6
5
 
7
- // Mock Linktree context for development
8
- const mockContext = {
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;
13
+
14
+ // Preview props injected by dev server via Vite define
15
+ declare const __PREVIEW_PROPS__: Record<string, unknown>;
16
+
17
+ const previewProps = __PREVIEW_PROPS__ || {
9
18
  linkUrl: "https://example.com/demo",
10
- showTitle: true,
19
+ theme: {
20
+ cssVariables: {
21
+ "--button-style-text": "#000000",
22
+ "--button-style-background": "#ffffff",
23
+ "--button-style-inner-radius": "12px",
24
+ "--button-style-border-color": "#e5e7eb",
25
+ "--button-style-background-hover": "#f3f4f6",
26
+ "--button-style-contrast-color": "#ffffff",
27
+ "--profileBackground": "#ffffff",
28
+ },
29
+ // Legacy properties (deprecated)
30
+ textColor: "#000000",
31
+ backgroundColor: "#ffffff",
32
+ borderRadius: "12px",
33
+ borderColor: "#e5e7eb",
34
+ backgroundHover: "#f3f4f6",
35
+ contrastColor: "#ffffff",
36
+ textHoverColor: "#111827",
37
+ },
38
+ locale: "en-US",
39
+ currency: "USD",
40
+ username: "demo-user",
41
+ viewport: {
42
+ width: 680,
43
+ height: 800,
44
+ },
11
45
  };
12
46
 
13
47
  const rootElement = document.getElementById("root");
@@ -17,8 +51,12 @@ if (!rootElement) {
17
51
 
18
52
  createRoot(rootElement).render(
19
53
  <StrictMode>
20
- <Layout>
21
- <Classic {...mockContext} />
22
- </Layout>
54
+ {Layout ? (
55
+ <Layout theme={previewProps.theme}>
56
+ <Classic {...previewProps} />
57
+ </Layout>
58
+ ) : (
59
+ <Classic {...previewProps} />
60
+ )}
23
61
  </StrictMode>,
24
62
  );
@@ -4,6 +4,64 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Classic - LinkApp</title>
7
+
8
+ <!-- Linktree theme variables will be injected here -->
9
+ <style id="linktree-theme"></style>
10
+
11
+ <script>
12
+ /**
13
+ * Helper function to convert CSS variables object to CSS string
14
+ * @param {Record<string, string>} vars - Object with CSS variable names as keys
15
+ * @returns {string} CSS string like "--var1: value1; --var2: value2;"
16
+ */
17
+ function renderCssVariables(vars) {
18
+ return Object.entries(vars)
19
+ .map((entry) => entry.join(': '))
20
+ .join('; ') + ';'
21
+ }
22
+
23
+ /**
24
+ * Listen for theme updates from parent window
25
+ * Applies CSS variables to the document root
26
+ */
27
+ window.addEventListener('message', function(event) {
28
+ // Only process messages with the correct structure
29
+ if (
30
+ event.data &&
31
+ typeof event.data === 'object' &&
32
+ event.data.type === 'THEME_UPDATE'
33
+ ) {
34
+ const themeUpdate = event.data
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(themeUpdate.payload.variables) + ' }'
46
+
47
+ // Remove any existing theme classes
48
+ const classesToRemove = []
49
+ document.documentElement.classList.forEach((className) => {
50
+ if (className.startsWith('linktree-theme-')) {
51
+ classesToRemove.push(className)
52
+ }
53
+ })
54
+ classesToRemove.forEach((className) => {
55
+ document.documentElement.classList.remove(className)
56
+ })
57
+
58
+ // Add theme class for additional styling hooks
59
+ if (themeUpdate.payload.name && themeUpdate.payload.name !== 'legacy') {
60
+ document.documentElement.classList.add('linktree-theme-' + themeUpdate.payload.name)
61
+ }
62
+ }
63
+ }, false)
64
+ </script>
7
65
  </head>
8
66
  <body>
9
67
  <div id="root"></div>
@@ -1,45 +1,31 @@
1
- "use client"
1
+ 'use client'
2
2
 
3
- import * as DialogPrimitive from "@radix-ui/react-dialog"
4
- import { XIcon } from "lucide-react"
3
+ import * as DialogPrimitive from '@radix-ui/react-dialog'
4
+ import { XIcon } from 'lucide-react'
5
5
 
6
- import { cn } from "../../lib/utils"
6
+ import { cn } from '../../lib/utils'
7
7
 
8
- function Dialog({
9
- ...props
10
- }: React.ComponentProps<typeof DialogPrimitive.Root>) {
8
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
11
9
  return <DialogPrimitive.Root data-slot="dialog" {...props} />
12
10
  }
13
11
 
14
- function DialogTrigger({
15
- ...props
16
- }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
12
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
17
13
  return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
18
14
  }
19
15
 
20
- function DialogPortal({
21
- ...props
22
- }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
16
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
23
17
  return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
24
18
  }
25
19
 
26
- function DialogClose({
27
- ...props
28
- }: React.ComponentProps<typeof DialogPrimitive.Close>) {
20
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
29
21
  return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
30
22
  }
31
23
 
32
- function DialogOverlay({
33
- className,
34
- ...props
35
- }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
24
+ function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
36
25
  return (
37
26
  <DialogPrimitive.Overlay
38
27
  data-slot="dialog-overlay"
39
- className={cn(
40
- "fixed inset-0 z-50 bg-black/50",
41
- className
42
- )}
28
+ className={cn('fixed inset-0 z-50 bg-black/50', className)}
43
29
  {...props}
44
30
  />
45
31
  )
@@ -59,7 +45,7 @@ function DialogContent({
59
45
  <DialogPrimitive.Content
60
46
  data-slot="dialog-content"
61
47
  className={cn(
62
- "bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
48
+ 'bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
63
49
  className
64
50
  )}
65
51
  {...props}
@@ -79,50 +65,41 @@ function DialogContent({
79
65
  )
80
66
  }
81
67
 
82
- function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
68
+ function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
83
69
  return (
84
70
  <div
85
71
  data-slot="dialog-header"
86
- className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
72
+ className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
87
73
  {...props}
88
74
  />
89
75
  )
90
76
  }
91
77
 
92
- function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
78
+ function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
93
79
  return (
94
80
  <div
95
81
  data-slot="dialog-footer"
96
- className={cn(
97
- "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
98
- className
99
- )}
82
+ className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
100
83
  {...props}
101
84
  />
102
85
  )
103
86
  }
104
87
 
105
- function DialogTitle({
106
- className,
107
- ...props
108
- }: React.ComponentProps<typeof DialogPrimitive.Title>) {
88
+ function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
109
89
  return (
110
90
  <DialogPrimitive.Title
111
91
  data-slot="dialog-title"
112
- className={cn("text-lg leading-none font-semibold", className)}
92
+ className={cn('text-lg leading-none font-semibold', className)}
113
93
  {...props}
114
94
  />
115
95
  )
116
96
  }
117
97
 
118
- function DialogDescription({
119
- className,
120
- ...props
121
- }: React.ComponentProps<typeof DialogPrimitive.Description>) {
98
+ function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {
122
99
  return (
123
100
  <DialogPrimitive.Description
124
101
  data-slot="dialog-description"
125
- className={cn("text-muted-foreground text-sm", className)}
102
+ className={cn('text-muted-foreground text-sm', className)}
126
103
  {...props}
127
104
  />
128
105
  )
@@ -1,6 +1,6 @@
1
- import * as React from "react"
2
- import * as TabsPrimitive from "@radix-ui/react-tabs"
3
- import { cn } from "../../lib/utils"
1
+ import * as React from 'react'
2
+ import * as TabsPrimitive from '@radix-ui/react-tabs'
3
+ import { cn } from '../../lib/utils'
4
4
 
5
5
  const Tabs = TabsPrimitive.Root
6
6
 
@@ -11,7 +11,7 @@ const TabsList = React.forwardRef<
11
11
  <TabsPrimitive.List
12
12
  ref={ref}
13
13
  className={cn(
14
- "inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
14
+ 'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
15
15
  className
16
16
  )}
17
17
  {...props}
@@ -26,7 +26,7 @@ const TabsTrigger = React.forwardRef<
26
26
  <TabsPrimitive.Trigger
27
27
  ref={ref}
28
28
  className={cn(
29
- "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
29
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',
30
30
  className
31
31
  )}
32
32
  {...props}
@@ -41,7 +41,7 @@ const TabsContent = React.forwardRef<
41
41
  <TabsPrimitive.Content
42
42
  ref={ref}
43
43
  className={cn(
44
- "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
44
+ 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
45
45
  className
46
46
  )}
47
47
  {...props}
@@ -1,13 +1,47 @@
1
+ import Featured from "@/app/featured";
1
2
  import { StrictMode } from "react";
2
3
  import { createRoot } from "react-dom/client";
3
- import Layout from "@/app/layout";
4
- import Featured from "@/app/featured";
5
4
  import "@/app/globals.css";
6
5
 
7
- // Mock Linktree context for development
8
- const mockContext = {
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;
13
+
14
+ // Preview props injected by dev server via Vite define
15
+ declare const __PREVIEW_PROPS__: Record<string, unknown>;
16
+
17
+ const previewProps = __PREVIEW_PROPS__ || {
9
18
  linkUrl: "https://example.com/demo",
10
- showTitle: true,
19
+ theme: {
20
+ cssVariables: {
21
+ "--button-style-text": "#000000",
22
+ "--button-style-background": "#ffffff",
23
+ "--button-style-inner-radius": "12px",
24
+ "--button-style-border-color": "#e5e7eb",
25
+ "--button-style-background-hover": "#f3f4f6",
26
+ "--button-style-contrast-color": "#ffffff",
27
+ "--profileBackground": "#ffffff",
28
+ },
29
+ // Legacy properties (deprecated)
30
+ textColor: "#000000",
31
+ backgroundColor: "#ffffff",
32
+ borderRadius: "12px",
33
+ borderColor: "#e5e7eb",
34
+ backgroundHover: "#f3f4f6",
35
+ contrastColor: "#ffffff",
36
+ textHoverColor: "#111827",
37
+ },
38
+ locale: "en-US",
39
+ currency: "USD",
40
+ username: "demo-user",
41
+ viewport: {
42
+ width: 680,
43
+ height: 800,
44
+ },
11
45
  };
12
46
 
13
47
  const rootElement = document.getElementById("root");
@@ -17,8 +51,12 @@ if (!rootElement) {
17
51
 
18
52
  createRoot(rootElement).render(
19
53
  <StrictMode>
20
- <Layout>
21
- <Featured {...mockContext} />
22
- </Layout>
54
+ {Layout ? (
55
+ <Layout theme={previewProps.theme}>
56
+ <Featured {...previewProps} />
57
+ </Layout>
58
+ ) : (
59
+ <Featured {...previewProps} />
60
+ )}
23
61
  </StrictMode>,
24
62
  );
@@ -4,6 +4,64 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Featured - LinkApp</title>
7
+
8
+ <!-- Linktree theme variables will be injected here -->
9
+ <style id="linktree-theme"></style>
10
+
11
+ <script>
12
+ /**
13
+ * Helper function to convert CSS variables object to CSS string
14
+ * @param {Record<string, string>} vars - Object with CSS variable names as keys
15
+ * @returns {string} CSS string like "--var1: value1; --var2: value2;"
16
+ */
17
+ function renderCssVariables(vars) {
18
+ return Object.entries(vars)
19
+ .map((entry) => entry.join(': '))
20
+ .join('; ') + ';'
21
+ }
22
+
23
+ /**
24
+ * Listen for theme updates from parent window
25
+ * Applies CSS variables to the document root
26
+ */
27
+ window.addEventListener('message', function(event) {
28
+ // Only process messages with the correct structure
29
+ if (
30
+ event.data &&
31
+ typeof event.data === 'object' &&
32
+ event.data.type === 'THEME_UPDATE'
33
+ ) {
34
+ const themeUpdate = event.data
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(themeUpdate.payload.variables) + ' }'
46
+
47
+ // Remove any existing theme classes
48
+ const classesToRemove = []
49
+ document.documentElement.classList.forEach((className) => {
50
+ if (className.startsWith('linktree-theme-')) {
51
+ classesToRemove.push(className)
52
+ }
53
+ })
54
+ classesToRemove.forEach((className) => {
55
+ document.documentElement.classList.remove(className)
56
+ })
57
+
58
+ // Add theme class for additional styling hooks
59
+ if (themeUpdate.payload.name && themeUpdate.payload.name !== 'legacy') {
60
+ document.documentElement.classList.add('linktree-theme-' + themeUpdate.payload.name)
61
+ }
62
+ }
63
+ }, false)
64
+ </script>
7
65
  </head>
8
66
  <body>
9
67
  <div id="root"></div>
@@ -1,5 +1,5 @@
1
- import { clsx, type ClassValue } from "clsx"
2
- import { twMerge } from "tailwind-merge"
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
3
 
4
4
  export function cn(...inputs: ClassValue[]) {
5
5
  return twMerge(clsx(inputs))