@srcroot/ui 0.0.55 → 0.0.56

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 (107) hide show
  1. package/README.md +151 -151
  2. package/dist/index.d.ts +0 -0
  3. package/dist/index.js +33 -17
  4. package/package.json +7 -2
  5. package/src/registry/analytics/google-analytics.tsx +36 -39
  6. package/src/registry/analytics/google-tag-manager.tsx +62 -65
  7. package/src/registry/analytics/meta-pixel.tsx +44 -47
  8. package/src/registry/analytics/microsoft-clarity.tsx +31 -34
  9. package/src/registry/analytics/tiktok-pixel.tsx +34 -37
  10. package/src/registry/lib/utils.ts +0 -0
  11. package/src/registry/themes/v3/blue.css +157 -157
  12. package/src/registry/themes/v3/glass.css +153 -153
  13. package/src/registry/themes/v3/gray.css +157 -157
  14. package/src/registry/themes/v3/green.css +157 -157
  15. package/src/registry/themes/v3/neutral.css +157 -157
  16. package/src/registry/themes/v3/orange.css +157 -157
  17. package/src/registry/themes/v3/rose.css +157 -157
  18. package/src/registry/themes/v3/slate.css +157 -157
  19. package/src/registry/themes/v3/stone.css +157 -157
  20. package/src/registry/themes/v3/violet.css +186 -186
  21. package/src/registry/themes/v3/zinc.css +157 -157
  22. package/src/registry/themes/v4/blue.css +184 -184
  23. package/src/registry/themes/v4/glass.css +180 -180
  24. package/src/registry/themes/v4/gray.css +184 -184
  25. package/src/registry/themes/v4/green.css +184 -184
  26. package/src/registry/themes/v4/neutral.css +184 -184
  27. package/src/registry/themes/v4/orange.css +184 -184
  28. package/src/registry/themes/v4/rose.css +184 -184
  29. package/src/registry/themes/v4/slate.css +184 -184
  30. package/src/registry/themes/v4/stone.css +184 -184
  31. package/src/registry/themes/v4/violet.css +184 -184
  32. package/src/registry/themes/v4/zinc.css +184 -184
  33. package/src/registry/ui/accordion.tsx +164 -165
  34. package/src/registry/ui/alert-dialog.tsx +213 -214
  35. package/src/registry/ui/alert.tsx +73 -76
  36. package/src/registry/ui/aspect-ratio.tsx +44 -47
  37. package/src/registry/ui/avatar.tsx +96 -97
  38. package/src/registry/ui/badge.tsx +52 -55
  39. package/src/registry/ui/breadcrumb.tsx +147 -150
  40. package/src/registry/ui/button-group.tsx +64 -67
  41. package/src/registry/ui/button.tsx +71 -72
  42. package/src/registry/ui/calendar.tsx +514 -515
  43. package/src/registry/ui/card.tsx +88 -91
  44. package/src/registry/ui/carousel.tsx +214 -214
  45. package/src/registry/ui/chart.tsx +373 -373
  46. package/src/registry/ui/chatbot.tsx +86 -13
  47. package/src/registry/ui/checkbox.tsx +93 -94
  48. package/src/registry/ui/collapsible.tsx +107 -108
  49. package/src/registry/ui/combobox.tsx +171 -171
  50. package/src/registry/ui/command.tsx +300 -300
  51. package/src/registry/ui/container.tsx +44 -47
  52. package/src/registry/ui/context-menu.tsx +221 -221
  53. package/src/registry/ui/date-picker.tsx +228 -228
  54. package/src/registry/ui/dialog.tsx +269 -270
  55. package/src/registry/ui/drawer.tsx +10 -4
  56. package/src/registry/ui/dropdown-menu.tsx +529 -530
  57. package/src/registry/ui/empty-state.tsx +0 -2
  58. package/src/registry/ui/file-upload.tsx +0 -0
  59. package/src/registry/ui/floating-dock.tsx +0 -0
  60. package/src/registry/ui/form-field.tsx +91 -94
  61. package/src/registry/ui/google-analytics.tsx +38 -0
  62. package/src/registry/ui/google-tag-manager.tsx +64 -0
  63. package/src/registry/ui/hover-card.tsx +223 -223
  64. package/src/registry/ui/image.tsx +144 -147
  65. package/src/registry/ui/input-group.tsx +82 -85
  66. package/src/registry/ui/input.tsx +125 -125
  67. package/src/registry/ui/kbd.tsx +60 -63
  68. package/src/registry/ui/label.tsx +36 -37
  69. package/src/registry/ui/loading-spinner.tsx +108 -111
  70. package/src/registry/ui/map.tsx +0 -0
  71. package/src/registry/ui/marquee.tsx +2 -0
  72. package/src/registry/ui/menubar.tsx +246 -246
  73. package/src/registry/ui/meta-pixel.tsx +46 -0
  74. package/src/registry/ui/microsoft-clarity.tsx +33 -0
  75. package/src/registry/ui/native-select.tsx +49 -52
  76. package/src/registry/ui/otp-input.tsx +152 -155
  77. package/src/registry/ui/pagination.tsx +149 -152
  78. package/src/registry/ui/patterns.tsx +28 -0
  79. package/src/registry/ui/popover.tsx +226 -227
  80. package/src/registry/ui/progress.tsx +51 -52
  81. package/src/registry/ui/radio.tsx +99 -102
  82. package/src/registry/ui/resizable.tsx +314 -314
  83. package/src/registry/ui/scroll-animation.tsx +45 -0
  84. package/src/registry/ui/scroll-area.tsx +121 -122
  85. package/src/registry/ui/scroll-to-top.tsx +0 -0
  86. package/src/registry/ui/search.tsx +147 -150
  87. package/src/registry/ui/select.tsx +292 -293
  88. package/src/registry/ui/separator.tsx +46 -47
  89. package/src/registry/ui/sheet.tsx +6 -3
  90. package/src/registry/ui/sidebar.tsx +628 -628
  91. package/src/registry/ui/skeleton.tsx +26 -29
  92. package/src/registry/ui/slider.tsx +196 -197
  93. package/src/registry/ui/slot.tsx +69 -72
  94. package/src/registry/ui/star-rating.tsx +131 -134
  95. package/src/registry/ui/switch.tsx +72 -73
  96. package/src/registry/ui/table-of-contents.tsx +96 -96
  97. package/src/registry/ui/table.tsx +138 -139
  98. package/src/registry/ui/tabs.tsx +124 -125
  99. package/src/registry/ui/text.tsx +61 -64
  100. package/src/registry/ui/textarea.tsx +41 -42
  101. package/src/registry/ui/theme-switcher.tsx +66 -66
  102. package/src/registry/ui/tiktok-pixel.tsx +36 -0
  103. package/src/registry/ui/toast.tsx +97 -98
  104. package/src/registry/ui/toggle-group.tsx +129 -129
  105. package/src/registry/ui/toggle.tsx +72 -72
  106. package/src/registry/ui/tooltip.tsx +143 -144
  107. package/src/registry/ui/whatsapp.tsx +0 -0
package/README.md CHANGED
@@ -1,151 +1,151 @@
1
- # @srcroot/ui
2
-
3
- A UI library with polymorphic, accessible React components.
4
- This library provides a collection of re-usable components that you can copy and paste into your apps.
5
-
6
- ## Features
7
-
8
- - **Polymorphic**: Most components support an `as` prop (e.g., render a `Button` as an `a` tag).
9
- - **Accessible**: Built on standard HTML elements and WAI-ARIA patterns.
10
- - **Copy/Paste**: Not a dependency you install, but code you own.
11
- - **Styled**: Beautiful defaults using Tailwind CSS and `class-variance-authority`.
12
-
13
- ## Installation
14
-
15
- This library is distributed via a CLI that initializes your project and adds components directly to your source code.
16
-
17
- ### 1. Initialize
18
-
19
- Run the `init` command to set up the necessary dependencies and structural files (like `cn` utility) in your project.
20
-
21
- ```bash
22
- npx @srcroot/ui init
23
- ```
24
-
25
- This will ask a few questions to configure your project structure (e.g., where to put components).
26
-
27
- ### 2. Add Components
28
-
29
- Use the `add` command to install components. You can do this in three ways:
30
-
31
- **Interactive Mode:**
32
- Run without arguments to select components from a list.
33
- ```bash
34
- npx @srcroot/ui add
35
- ```
36
-
37
- **Specific Components:**
38
- Add one or more components by name.
39
- ```bash
40
- npx @srcroot/ui add button card input
41
- ```
42
-
43
- **Add All:**
44
- Install every available component at once.
45
- ```bash
46
- npx @srcroot/ui add --all
47
- ```
48
-
49
- This will copy the component files to your `components/ui` directory and install any necessary peer dependencies (like `react-icons` or `clsx`).
50
-
51
- ### 3. Usage
52
-
53
- Import components directly from your project folder:
54
-
55
- ```tsx
56
- import { Button } from "@/components/ui/button"
57
-
58
- export default function Home() {
59
- return (
60
- <Button variant="destructive" onClick={() => alert("Clicked!")}>
61
- Click Me
62
- </Button>
63
- )
64
- }
65
- ```
66
-
67
- ## Available Components
68
-
69
- run `npx @srcroot/ui list` to see all available components.
70
-
71
- ### Core
72
- - `button` - Polymorphic button with variants.
73
- - `badge` - Status indicators.
74
- - `avatar` - User profile images with fallbacks.
75
- - `separator` - Visual divider.
76
- - `button-group` - Attached or spaced button sets.
77
-
78
- ### Forms
79
- - `input` - Basic text input.
80
- - `textarea` - Multi-line text input.
81
- - `checkbox` - Toggle selection.
82
- - `radio` - Single selection from list.
83
- - `switch` - Toggle switch.
84
- - `select` - Dropdown selection.
85
- - `slider` - Range input.
86
- - `otp-input` - One-time password verification.
87
- - `search` - Search input with debounce support.
88
- - `calendar` - Date and range picker.
89
-
90
- ### Layout
91
- - `card` - Content container with header/content/footer.
92
- - `container` - Centered layout wrapper.
93
- - `aspect-ratio` - Maintain element proportions.
94
-
95
- ### Data Display
96
- - `text` - Polymorphic typography component.
97
- - `label` - Accessible form label.
98
- - `table` - Responsive data table.
99
- - `accordion` - Collapsible content sections.
100
- - `collapsible` - Expandable panel.
101
- - `tabs` - Tabbed content switcher.
102
- - `progress` - Progress bar.
103
- - `skeleton` - Loading placeholder state.
104
- - `image` - Enhanced img with fallback and loading state.
105
- - `carousel` - Content slider with autoplay.
106
-
107
- ### Feedback
108
- - `loading-spinner` - SVG spinner with variants.
109
- - `star-rating` - Interactive rating component.
110
- - `toast` - Transient notifications.
111
- - `alert` - Critical information banner.
112
-
113
- ### Overlays
114
- - `dialog` - Modal dialog.
115
- - `alert-dialog` - Modal for confirming actions.
116
- - `sheet` - Side-panel overlay.
117
- - `popover` - Content appearing over trigger.
118
- - `tooltip` - Hover information.
119
- - `dropdown-menu` - Menu for actions/navigation.
120
-
121
- ### Navigation
122
- - `breadcrumb` - Navigation trail.
123
- - `pagination` - Page navigation controls.
124
-
125
- ## Polymorphism
126
-
127
- Our components accept an `as` prop to change the underlying HTML element while maintaining styles and behavior.
128
-
129
- ```tsx
130
- // Renders as an <a> tag but looks like a button
131
- <Button as="a" href="/login">
132
- Login
133
- </Button>
134
-
135
- // Renders as a specialized text variant
136
- <Text as="h1" variant="h1">
137
- Page Title
138
- </Text>
139
- ```
140
-
141
- ## Local Development
142
-
143
- To run the documentation/playground locally:
144
-
145
- ```bash
146
- cd examples/playground
147
- npm install
148
- npm run dev
149
- ```
150
-
151
- Visit `http://localhost:3001` to view the component showcase.
1
+ # @srcroot/ui
2
+
3
+ A UI library with polymorphic, accessible React components.
4
+ This library provides a collection of re-usable components that you can copy and paste into your apps.
5
+
6
+ ## Features
7
+
8
+ - **Polymorphic**: Most components support an `as` prop (e.g., render a `Button` as an `a` tag).
9
+ - **Accessible**: Built on standard HTML elements and WAI-ARIA patterns.
10
+ - **Copy/Paste**: Not a dependency you install, but code you own.
11
+ - **Styled**: Beautiful defaults using Tailwind CSS and `class-variance-authority`.
12
+
13
+ ## Installation
14
+
15
+ This library is distributed via a CLI that initializes your project and adds components directly to your source code.
16
+
17
+ ### 1. Initialize
18
+
19
+ Run the `init` command to set up the necessary dependencies and structural files (like `cn` utility) in your project.
20
+
21
+ ```bash
22
+ npx @srcroot/ui init
23
+ ```
24
+
25
+ This will ask a few questions to configure your project structure (e.g., where to put components).
26
+
27
+ ### 2. Add Components
28
+
29
+ Use the `add` command to install components. You can do this in three ways:
30
+
31
+ **Interactive Mode:**
32
+ Run without arguments to select components from a list.
33
+ ```bash
34
+ npx @srcroot/ui add
35
+ ```
36
+
37
+ **Specific Components:**
38
+ Add one or more components by name.
39
+ ```bash
40
+ npx @srcroot/ui add button card input
41
+ ```
42
+
43
+ **Add All:**
44
+ Install every available component at once.
45
+ ```bash
46
+ npx @srcroot/ui add --all
47
+ ```
48
+
49
+ This will copy the component files to your `components/ui` directory and install any necessary peer dependencies (like `react-icons` or `clsx`).
50
+
51
+ ### 3. Usage
52
+
53
+ Import components directly from your project folder:
54
+
55
+ ```tsx
56
+ import { Button } from "@/components/ui/button"
57
+
58
+ export default function Home() {
59
+ return (
60
+ <Button variant="destructive" onClick={() => alert("Clicked!")}>
61
+ Click Me
62
+ </Button>
63
+ )
64
+ }
65
+ ```
66
+
67
+ ## Available Components
68
+
69
+ run `npx @srcroot/ui list` to see all available components.
70
+
71
+ ### Core
72
+ - `button` - Polymorphic button with variants.
73
+ - `badge` - Status indicators.
74
+ - `avatar` - User profile images with fallbacks.
75
+ - `separator` - Visual divider.
76
+ - `button-group` - Attached or spaced button sets.
77
+
78
+ ### Forms
79
+ - `input` - Basic text input.
80
+ - `textarea` - Multi-line text input.
81
+ - `checkbox` - Toggle selection.
82
+ - `radio` - Single selection from list.
83
+ - `switch` - Toggle switch.
84
+ - `select` - Dropdown selection.
85
+ - `slider` - Range input.
86
+ - `otp-input` - One-time password verification.
87
+ - `search` - Search input with debounce support.
88
+ - `calendar` - Date and range picker.
89
+
90
+ ### Layout
91
+ - `card` - Content container with header/content/footer.
92
+ - `container` - Centered layout wrapper.
93
+ - `aspect-ratio` - Maintain element proportions.
94
+
95
+ ### Data Display
96
+ - `text` - Polymorphic typography component.
97
+ - `label` - Accessible form label.
98
+ - `table` - Responsive data table.
99
+ - `accordion` - Collapsible content sections.
100
+ - `collapsible` - Expandable panel.
101
+ - `tabs` - Tabbed content switcher.
102
+ - `progress` - Progress bar.
103
+ - `skeleton` - Loading placeholder state.
104
+ - `image` - Enhanced img with fallback and loading state.
105
+ - `carousel` - Content slider with autoplay.
106
+
107
+ ### Feedback
108
+ - `loading-spinner` - SVG spinner with variants.
109
+ - `star-rating` - Interactive rating component.
110
+ - `toast` - Transient notifications.
111
+ - `alert` - Critical information banner.
112
+
113
+ ### Overlays
114
+ - `dialog` - Modal dialog.
115
+ - `alert-dialog` - Modal for confirming actions.
116
+ - `sheet` - Side-panel overlay.
117
+ - `popover` - Content appearing over trigger.
118
+ - `tooltip` - Hover information.
119
+ - `dropdown-menu` - Menu for actions/navigation.
120
+
121
+ ### Navigation
122
+ - `breadcrumb` - Navigation trail.
123
+ - `pagination` - Page navigation controls.
124
+
125
+ ## Polymorphism
126
+
127
+ Our components accept an `as` prop to change the underlying HTML element while maintaining styles and behavior.
128
+
129
+ ```tsx
130
+ // Renders as an <a> tag but looks like a button
131
+ <Button as="a" href="/login">
132
+ Login
133
+ </Button>
134
+
135
+ // Renders as a specialized text variant
136
+ <Text as="h1" variant="h1">
137
+ Page Title
138
+ </Text>
139
+ ```
140
+
141
+ ## Local Development
142
+
143
+ To run the documentation/playground locally:
144
+
145
+ ```bash
146
+ cd examples/playground
147
+ npm install
148
+ npm run dev
149
+ ```
150
+
151
+ Visit `http://localhost:3001` to view the component showcase.
package/dist/index.d.ts CHANGED
File without changes
package/dist/index.js CHANGED
@@ -696,7 +696,8 @@ var REGISTRY = {
696
696
  file: "ui/file-upload.tsx",
697
697
  description: "Drag-and-drop file upload",
698
698
  category: "Forms",
699
- dependencies: ["button"]
699
+ dependencies: ["button"],
700
+ registryDependencies: ["react-dropzone", "react-icons"]
700
701
  },
701
702
  "hover-card": {
702
703
  file: "ui/hover-card.tsx",
@@ -801,43 +802,58 @@ var REGISTRY = {
801
802
  category: "Navigation",
802
803
  dependencies: []
803
804
  },
805
+ map: {
806
+ file: "ui/map.tsx",
807
+ description: "Interactive map with Leaflet/Google",
808
+ category: "Data Display",
809
+ dependencies: [],
810
+ registryDependencies: ["leaflet", "react-leaflet"]
811
+ },
804
812
  "empty-state": {
805
813
  file: "ui/empty-state.tsx",
806
- description: "Placeholder for empty states",
807
- category: "Feedback",
814
+ description: "Placeholder for empty data",
815
+ category: "Data Display",
808
816
  dependencies: []
809
817
  },
810
818
  "floating-dock": {
811
819
  file: "ui/floating-dock.tsx",
812
- description: "Floating action container",
813
- category: "Layout",
814
- dependencies: []
815
- },
816
- "map": {
817
- file: "ui/map.tsx",
818
- description: "Leaflet/Google map integration",
819
- category: "Data Display",
820
+ description: "Mac-style floating dock",
821
+ category: "Navigation",
820
822
  dependencies: [],
821
- registryDependencies: ["react-leaflet", "leaflet"]
823
+ registryDependencies: ["framer-motion"]
822
824
  },
823
825
  marquee: {
824
826
  file: "ui/marquee.tsx",
825
- description: "Scrolling marquee text",
827
+ description: "Infinite scrolling marquee",
826
828
  category: "Data Display",
827
829
  dependencies: []
828
830
  },
829
831
  "scroll-to-top": {
830
832
  file: "ui/scroll-to-top.tsx",
831
- description: "Scroll to top button",
833
+ description: "Button to scroll to top",
832
834
  category: "Navigation",
833
- dependencies: ["button"]
835
+ dependencies: ["button"],
836
+ registryDependencies: ["framer-motion"]
837
+ },
838
+ "scroll-animation": {
839
+ file: "ui/scroll-animation.tsx",
840
+ description: "Scroll-triggered animations",
841
+ category: "Layout",
842
+ dependencies: [],
843
+ registryDependencies: ["framer-motion"]
834
844
  },
835
845
  whatsapp: {
836
846
  file: "ui/whatsapp.tsx",
837
- description: "WhatsApp floating button",
838
- category: "Feedback",
847
+ description: "WhatsApp chat button",
848
+ category: "Data Display",
839
849
  dependencies: ["button"],
840
850
  registryDependencies: ["react-icons"]
851
+ },
852
+ patterns: {
853
+ file: "ui/patterns.tsx",
854
+ description: "Background patterns",
855
+ category: "Layout",
856
+ dependencies: []
841
857
  }
842
858
  };
843
859
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srcroot/ui",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "description": "A UI library with polymorphic, accessible React components",
5
5
  "author": "Shifaul Islam",
6
6
  "license": "MIT",
@@ -34,15 +34,18 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/fs-extra": "^11.0.4",
37
+ "@types/leaflet": "^1.9.21",
37
38
  "@types/node": "^22.10.1",
38
39
  "@types/prompts": "^2.4.9",
39
40
  "@types/react": "^19.2.7",
40
41
  "class-variance-authority": "^0.7.1",
41
42
  "clsx": "^2.1.1",
42
43
  "cmdk": "^1.0.0",
44
+ "leaflet": "^1.9.4",
43
45
  "react": "^18.0.0 || ^19.0.0",
44
46
  "react-dom": "^18.0.0 || ^19.0.0",
45
47
  "react-icons": "^5.5.0",
48
+ "react-leaflet": "^5.0.0",
46
49
  "tailwind-merge": "^3.4.0",
47
50
  "tailwindcss": "^3.0.0 || ^4.0.0",
48
51
  "tailwindcss-animate": "^1.0.7",
@@ -54,9 +57,11 @@
54
57
  "class-variance-authority": "^0.7.1",
55
58
  "clsx": "^2.1.1",
56
59
  "cmdk": "^1.0.0",
60
+ "leaflet": "^1.9.4",
57
61
  "react": "^18.0.0 || ^19.0.0",
58
62
  "react-dom": "^18.0.0 || ^19.0.0",
59
63
  "react-icons": "^5.5.0",
64
+ "react-leaflet": "^4.2.1",
60
65
  "tailwind-merge": "^3.4.0",
61
66
  "tailwindcss": "^3.0.0 || ^4.0.0",
62
67
  "tailwindcss-animate": "^1.0.7"
@@ -66,4 +71,4 @@
66
71
  "optional": true
67
72
  }
68
73
  }
69
- }
74
+ }
@@ -1,39 +1,36 @@
1
- "use client"
2
-
3
- import Script from 'next/script';
4
- import type { FC } from 'react';
5
-
6
- interface GoogleAnalyticsProps {
7
- gaIds: string[];
8
- }
9
-
10
- const GoogleAnalytics: FC<GoogleAnalyticsProps> = ({ gaIds }) => {
11
- if (gaIds.length === 0) {
12
- return null;
13
- }
14
-
15
- return (
16
- <>
17
- <Script
18
- id="ga4-script"
19
- strategy="afterInteractive"
20
- src={`https://www.googletagmanager.com/gtag/js?id=${gaIds[0]}`}
21
- />
22
- <Script
23
- id="ga4-init"
24
- strategy="afterInteractive"
25
- dangerouslySetInnerHTML={{
26
- __html: `
27
- window.dataLayer = window.dataLayer || [];
28
- function gtag(){dataLayer.push(arguments);}
29
- gtag('js', new Date());
30
- ${gaIds.map((id) => `gtag('config', '${id}', { page_path: window.location.pathname });`).join('\n')}
31
- `,
32
- }}
33
- />
34
- </>
35
- );
36
- };
37
-
38
- export default GoogleAnalytics;
39
-
1
+ import Script from 'next/script';
2
+ import type { FC } from 'react';
3
+
4
+ interface GoogleAnalyticsProps {
5
+ gaIds: string[];
6
+ }
7
+
8
+ const GoogleAnalytics: FC<GoogleAnalyticsProps> = ({ gaIds }) => {
9
+ if (gaIds.length === 0) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <>
15
+ <Script
16
+ id="ga4-script"
17
+ strategy="afterInteractive"
18
+ src={`https://www.googletagmanager.com/gtag/js?id=${gaIds[0]}`}
19
+ />
20
+ <Script
21
+ id="ga4-init"
22
+ strategy="afterInteractive"
23
+ dangerouslySetInnerHTML={{
24
+ __html: `
25
+ window.dataLayer = window.dataLayer || [];
26
+ function gtag(){dataLayer.push(arguments);}
27
+ gtag('js', new Date());
28
+ ${gaIds.map((id) => `gtag('config', '${id}', { page_path: window.location.pathname });`).join('\n')}
29
+ `,
30
+ }}
31
+ />
32
+ </>
33
+ );
34
+ };
35
+
36
+ export default GoogleAnalytics;
@@ -1,65 +1,62 @@
1
- "use client"
2
-
3
- import Script from 'next/script';
4
- import type { FC, ReactNode } from 'react';
5
-
6
- interface GTMContainer {
7
- gtmId: string;
8
- tagServerUrl?: string;
9
- }
10
-
11
- interface GoogleTagManagerProps {
12
- containers: GTMContainer[];
13
- }
14
-
15
- const GoogleTagManager: FC<GoogleTagManagerProps> = ({ containers }) => {
16
- const defaultServer = 'https://www.googletagmanager.com';
17
-
18
- // Group containers by tagServer to avoid duplicate script loads
19
- const scriptsMap = containers.reduce((map, container) => {
20
- const server = container.tagServerUrl || defaultServer;
21
- if (!map.has(server)) {
22
- map.set(server, []);
23
- }
24
- map.get(server)!.push(container.gtmId);
25
- return map;
26
- }, new Map<string, string[]>());
27
-
28
- const scriptElements: ReactNode[] = Array.from(scriptsMap.entries()).map(([server, ids]) => (
29
- <Script
30
- key={server}
31
- id={`gtm-script-${server}`}
32
- strategy="afterInteractive"
33
- dangerouslySetInnerHTML={{
34
- __html: `
35
- ${ids
36
- .map(
37
- id => `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s);j.async=true;j.src="${server}/gtm.js?"+i;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`
38
- )
39
- .join('')}
40
- `,
41
- }}
42
- />
43
- ));
44
-
45
- return (
46
- <>
47
- {scriptElements}
48
-
49
- <noscript>
50
- {containers.map(({ gtmId, tagServerUrl = defaultServer }) => (
51
- <iframe
52
- key={gtmId}
53
- src={`${tagServerUrl}/ns.html?id=${gtmId}`}
54
- height="0"
55
- width="0"
56
- style={{ display: 'none', visibility: 'hidden' }}
57
- />
58
- ))}
59
- </noscript>
60
- </>
61
- );
62
- };
63
-
64
- export default GoogleTagManager;
65
-
1
+ import Script from 'next/script';
2
+ import type { FC, ReactNode } from 'react';
3
+
4
+ interface GTMContainer {
5
+ gtmId: string;
6
+ tagServerUrl?: string;
7
+ }
8
+
9
+ interface GoogleTagManagerProps {
10
+ containers: GTMContainer[];
11
+ }
12
+
13
+ const GoogleTagManager: FC<GoogleTagManagerProps> = ({ containers }) => {
14
+ const defaultServer = 'https://www.googletagmanager.com';
15
+
16
+ // Group containers by tagServer to avoid duplicate script loads
17
+ const scriptsMap = containers.reduce((map, container) => {
18
+ const server = container.tagServerUrl || defaultServer;
19
+ if (!map.has(server)) {
20
+ map.set(server, []);
21
+ }
22
+ map.get(server)!.push(container.gtmId);
23
+ return map;
24
+ }, new Map<string, string[]>());
25
+
26
+ const scriptElements: ReactNode[] = Array.from(scriptsMap.entries()).map(([server, ids]) => (
27
+ <Script
28
+ key={server}
29
+ id={`gtm-script-${server}`}
30
+ strategy="afterInteractive"
31
+ dangerouslySetInnerHTML={{
32
+ __html: `
33
+ ${ids
34
+ .map(
35
+ id => `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s);j.async=true;j.src="${server}/gtm.js?"+i;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`
36
+ )
37
+ .join('')}
38
+ `,
39
+ }}
40
+ />
41
+ ));
42
+
43
+ return (
44
+ <>
45
+ {scriptElements}
46
+
47
+ <noscript>
48
+ {containers.map(({ gtmId, tagServerUrl = defaultServer }) => (
49
+ <iframe
50
+ key={gtmId}
51
+ src={`${tagServerUrl}/ns.html?id=${gtmId}`}
52
+ height="0"
53
+ width="0"
54
+ style={{ display: 'none', visibility: 'hidden' }}
55
+ />
56
+ ))}
57
+ </noscript>
58
+ </>
59
+ );
60
+ };
61
+
62
+ export default GoogleTagManager;