From 80539188ef6814b4202d677d62b761bd5b670574 Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Tue, 24 Jun 2025 19:04:01 +0700 Subject: Dynamic height adjustment for widget size. CSS inject by JS for single file --- package.json | 9 +++- postcss.config.js | 9 ++++ src/Widget.tsx | 52 ++++++++++++++++------- src/components/app-sidebar.tsx | 82 ++++++++++++++++++++++++++++++++---- src/components/nav-main.tsx | 94 ------------------------------------------ src/components/site-header.tsx | 9 +--- src/index.css | 19 ++++++--- src/main.tsx | 8 ++-- src/pages/Demographics.tsx | 2 +- vite.config.mts | 44 ++++++++++++++++++-- 10 files changed, 188 insertions(+), 140 deletions(-) create mode 100644 postcss.config.js delete mode 100644 src/components/nav-main.tsx diff --git a/package.json b/package.json index 3acfdad..8b704ab 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "lucide-react": "^0.503.0", "motion": "^12.12.1", "next-themes": "^0.4.6", + "postcss-cli": "^11.0.1", "querystring": "^0.2.1", "react": "^18.3.1", "react-day-picker": "^8.10.1", @@ -66,22 +67,28 @@ "recharts": "^2.15.3", "sonner": "^2.0.3", "tailwind-merge": "^3.2.0", - "tailwindcss": "^4.1.4", "tw-animate-css": "^1.2.8", "vaul": "^1.1.2", + "vite-plugin-css-injected-by-js": "^3.5.2", "zod": "^3.24.3" }, "devDependencies": { "@eslint/js": "^9.17.0", + "@tailwindcss/postcss": "^4.1.10", "@types/node": "^22.14.1", "@types/react": "^18.3.20", "@types/react-dom": "^18.3.6", "@vitejs/plugin-react": "^4.4.1", + "autoprefixer": "^10.4.21", + "cssnano": "^7.0.7", "eslint": "^9.29.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^15.15.0", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.10", + "terser": "^5.43.1", "typescript": "~5.6.2", "typescript-eslint": "^8.31.0", "vite": "^6.3.2", diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2d47f24 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,9 @@ +module.exports = { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + cssnano: { + preset: ['default', {discardComments: {removeAll: true}}], + }, + }, +} diff --git a/src/Widget.tsx b/src/Widget.tsx index 192e4e0..4f4556b 100644 --- a/src/Widget.tsx +++ b/src/Widget.tsx @@ -1,5 +1,5 @@ -import {useEffect} from 'react' -import {AppSidebar} from "@/components/app-sidebar" +import { useEffect, useState, useRef } from "react" + import {SiteHeader} from "@/components/site-header" import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar" import {Offerwall} from "@/pages/Offerwall.tsx" @@ -8,6 +8,7 @@ import {Demographics} from "@/pages/Demographics.tsx" import {CashoutMethodsPage} from "@/pages/CashoutMethods.tsx"; import {TransactionHistoryPage} from "@/pages/TransactionHistory.tsx" import {TaskAttemptHistoryPage} from "@/pages/TaskAttemptHistory.tsx"; +import {AppSidebar} from "@/components/app-sidebar" import {useAppDispatch, useAppSelector} from "@/hooks.ts"; import { @@ -33,11 +34,34 @@ import {setMarketplaceAnswers} from "@/models/userMarketplaceAnswerSlice.ts"; import {setUserProfile} from "@/models/userProfileSlice.ts"; import {setTaskStatuses} from "@/models/taskStatusSlice.ts" import {App} from "@/models/app.ts" +import {ScrollArea} from "@/components/ui/scroll-area" import './index.css'; +export function useParentHeight() { + const ref = useRef(null) + const [height, setHeight] = useState(null) + + useEffect(() => { + if (!ref.current) return + + const observer = new ResizeObserver(() => { + if (ref.current?.parentElement) { + const h = ref.current.parentElement.getBoundingClientRect().height + setHeight(h) + } + }) + + observer.observe(ref.current.parentElement!) + + return () => observer.disconnect() + }, []) + + return { ref, height } +} const Widget = () => { + const { ref, height } = useParentHeight() const dispatch = useAppDispatch() const app: App = useAppSelector(state => state.app) @@ -103,31 +127,29 @@ const Widget = () => { }, []); // ← empty array means "run once" - return ( - - - - +
+ + -
-
+ + +
-
+
{app.currentPage === 'offerwall' && } {app.currentPage === 'questions' && } {app.currentPage === 'cashout_methods' && } {app.currentPage === 'task_attempts' && } - {app.currentPage === 'demographics' && } {app.currentPage === 'transaction_history' && }
-
-
+ - - + + +
) } diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index c60bf17..b61a716 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -1,9 +1,7 @@ "use client" import React from "react" -import {CircleDollarSign, SquareStack} from "lucide-react" - -import {NavMain} from "@/components/nav-main" +import {Activity, CircleDollarSign, ListIcon, NotebookText, SquareStack, User} from "lucide-react" import { Sidebar, SidebarContent, @@ -22,6 +20,8 @@ import {Badge} from "@/components/ui/badge.tsx"; import {useSelector} from "react-redux"; import {selectCashoutMethods} from "@/models/cashoutMethodSlice.ts"; import {selectTransactionHistory} from "@/models/transactionHistorySlice.ts"; +import {selectQuestions} from "../models/questionSlice"; +import {selectUserUpkAnswers} from "../models/userUpkAnswerSlice"; export function AppSidebar({...props}: React.ComponentProps) { const app: App = useAppSelector(state => state.app) @@ -29,8 +29,12 @@ export function AppSidebar({...props}: React.ComponentProps) { const cashoutMethods = useSelector(selectCashoutMethods) const transactionHistory = useSelector(selectTransactionHistory) + const questions = useSelector(selectQuestions) + const upkAnswers = useSelector(selectUserUpkAnswers) + const taskAttempts = useAppSelector(state => state.taskStatus) + return ( - + @@ -38,7 +42,6 @@ export function AppSidebar({...props}: React.ComponentProps) { asChild className="data-[slot=sidebar-menu-button]:!p-1.5" > - {app.panelName} @@ -46,10 +49,73 @@ export function AppSidebar({...props}: React.ComponentProps) { - - + + + + + dispatch(setPage("offerwall"))} + > + + + + Surveys {(app.availability_count ?? 0).toLocaleString()} + + + + + + dispatch(setPage("questions"))} + > + + + + Questions {questions.length.toLocaleString()} + + + + + dispatch(setPage("demographics"))} + > + + + + Demographics {upkAnswers.length.toLocaleString()} + + + + + dispatch(setPage("task_attempts"))} + > + + + + Survey History {taskAttempts.length.toLocaleString()} + + + + + + + - Redemption diff --git a/src/components/nav-main.tsx b/src/components/nav-main.tsx deleted file mode 100644 index 9ed1b24..0000000 --- a/src/components/nav-main.tsx +++ /dev/null @@ -1,94 +0,0 @@ -"use client" - -import {ListIcon, NotebookText, Users, User, Activity} from "lucide-react" -import { - SidebarGroup, - SidebarGroupContent, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/components/ui/sidebar" -import {setPage} from "@/models/appSlice.ts"; -import {useAppDispatch, useAppSelector} from "@/hooks.ts"; -import {useSelector} from "react-redux"; -import {selectQuestions} from "@/models/questionSlice.ts"; -import {Badge} from "@/components/ui/badge" -import {selectUserUpkAnswers} from "@/models/userUpkAnswerSlice.ts"; - -export function NavMain() { - const dispatch = useAppDispatch() - - const app = useAppSelector(state => state.app) - const questions = useSelector(selectQuestions) - const upkAnswers = useSelector(selectUserUpkAnswers) - const taskAttempts = useAppSelector(state => state.taskStatus) - - return ( - - - - - dispatch(setPage("offerwall"))} - > - - - - Surveys {(app.availability_count ?? 0).toLocaleString()} - - - - - - dispatch(setPage("questions"))} - > - - - - Questions {questions.length.toLocaleString()} - - - - - dispatch(setPage("demographics"))} - > - - - - Demographics {upkAnswers.length.toLocaleString()} - - - - - dispatch(setPage("task_attempts"))} - > - - - - Survey History {taskAttempts.length.toLocaleString()} - - - - - - - - ) -} diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx index dca4996..70a2068 100644 --- a/src/components/site-header.tsx +++ b/src/components/site-header.tsx @@ -1,8 +1,6 @@ import {Separator} from "@/components/ui/separator" -import {SidebarTrigger} from "@/components/ui/sidebar" import {useAppSelector} from "@/hooks.ts"; import {App} from "@/models/app.ts" -import {Offerwall} from "@/pages/Offerwall.tsx"; const SiteHeader = () => { const app: App = useAppSelector(state => state.app) @@ -10,13 +8,8 @@ const SiteHeader = () => { return (
-
- +
-

{app.currentPage === 'offerwall' && "Offerwall"} {app.currentPage === 'questions' && "Profiling Questions"} diff --git a/src/index.css b/src/index.css index e3beb23..39f436b 100644 --- a/src/index.css +++ b/src/index.css @@ -4,11 +4,6 @@ @tailwind components; @tailwind utilities; -#testD4rN { - max-width: 800px; - max-height: 400px !important; -} - @custom-variant dark (&:is(.dark *)); @theme inline { @@ -145,4 +140,16 @@ body { @apply bg-background text-foreground; } -} \ No newline at end of file +} + +#testD4rN { + /*max-width: 800px;*/ + /*max-height: 400px !important;*/ + + height: 500px; + width: 800px; + border: 1px solid red; + position: absolute; + top: 80px; + left: 80px; +} diff --git a/src/main.tsx b/src/main.tsx index 3dfd07a..c944cdd 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -6,6 +6,8 @@ import {Provider} from 'react-redux' import {store} from './store' import {setApp} from "@/models/appSlice.ts"; +import "@/index.css" + (function () { // Finding the script tag on the page.. @@ -42,9 +44,9 @@ import {setApp} from "@/models/appSlice.ts"; const root = createRoot(container) root.render( // - - - + + + // ); diff --git a/src/pages/Demographics.tsx b/src/pages/Demographics.tsx index 2031511..f7f6efa 100644 --- a/src/pages/Demographics.tsx +++ b/src/pages/Demographics.tsx @@ -101,7 +101,7 @@ export const ContactCard = () => {
- {titleCase(gender as string) ?? " - "} + {titleCase(gender ?? " - " as string)}
diff --git a/vite.config.mts b/vite.config.mts index cf45ffb..7752a18 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -1,12 +1,18 @@ import path from "path" -import tailwindcss from "@tailwindcss/vite" +// import tailwindcss from "@tailwindcss/vite" import react from "@vitejs/plugin-react" import {defineConfig} from "vite" -import {viteSingleFile} from "vite-plugin-singlefile" +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' + +// ESM-compatible imports +// const tailwindcss = (await import('tailwindcss')).default +const tailwindcss = (await import('@tailwindcss/postcss')).default +const autoprefixer = (await import('autoprefixer')).default +const cssnano = (await import('cssnano')).default export default defineConfig({ - plugins: [react(), tailwindcss(), viteSingleFile()], + plugins: [cssInjectedByJsPlugin(), react()], resolve: { alias: { "@": path.resolve(__dirname, "./src"), @@ -17,16 +23,46 @@ export default defineConfig({ port: 8080, }, + css: { + postcss: { + plugins: [ + tailwindcss, + autoprefixer, + cssnano({ + preset: ['default', { + discardComments: { removeAll: true }, + }], + }), + ], + } + }, + + define: { + 'process.env.NODE_ENV': JSON.stringify('production') + }, + build: { target: "es2015", + minify: 'terser', + cssCodeSplit: false, + terserOptions: { + format: { + comments: false, + }, + compress: { + drop_console: true, + drop_debugger: true + } + }, lib: { entry: 'src/main.tsx', name: 'GRLWidget', formats: ['iife'], - fileName: 'my-widget.js' + fileName: 'my-widget' }, rollupOptions: { output: { + entryFileNames: 'grl-panel.js', globals: { react: 'React', 'react-dom': 'ReactDOM' -- cgit v1.2.3