sparkle-react 0.0.6 → 0.0.8

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.
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createContext, useState, useCallback, useEffect, useContext, useMemo } from 'react';
2
- import { jsx } from 'react/jsx-runtime';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
 
4
- function u(){let[s,a]=useState(null),[o,c]=useState(!0),e="u9lt242tz2pn5hl5x444ls2xllnvip",t=useCallback(async()=>{let r=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");if(r){localStorage.setItem("twitch_access_token",r);let n=(await fetch("https://api.twitch.tv/helix/users",{headers:{Authorization:`Bearer ${r}`,"Client-Id":e}}).then(b=>b.json())).data[0];a(n);}},[]),i=useCallback(async()=>{try{let r="http://localhost:3000/test",d=["user:read:email","channel:read:vips","user:read:follows","user:read:subscriptions"].join(" "),n=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");if(!n)window.location.replace(`https://id.twitch.tv/oauth2/authorize?client_id=${e}&redirect_uri=${r}&response_type=token&scope=${d}&force_verify=true`);else {localStorage.setItem("twitch_access_token",n);let v=(await fetch("https://api.twitch.tv/helix/users",{headers:{Authorization:`Bearer ${n}`,"Client-Id":e}}).then(x=>x.json())).data[0];a(v);}}catch(r){console.error("Erreur lors de l'authentification :",r);}finally{c(!1);}},[]),w=useCallback(()=>{localStorage.removeItem("twitch_access_token"),a(null);},[]),l=useCallback(async()=>{let r=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");await fetch("https://api.twitch.tv/helix/channels/vips?broadcaster_id=540958129",{method:"GET",headers:{Authorization:`Bearer ${r}`,"Client-Id":e}}).then(n=>n.json());},[]);return useEffect(()=>{t();},[]),{user:s,loading:o,fetchVips:l,authenticate:i,logout:w}}var p=createContext({socket:void 0}),L=({children:s})=>{let [a,o]=useState();u();return useEffect(()=>{let i=new WebSocket("ws://localhost:8000");return o(i),()=>{i.close();}},[]),jsx(p.Provider,{value:{socket:a},children:s})};function W(...s){let a=useContext(p),o=useMemo(()=>s,[s.join(",")]),[c,e]=useState(o.reduce((l,r)=>({...l,[r]:""}),{}));if(!a)throw new Error("You must use useDatabase inside a SparkleProvider");let{socket:t}=a,i=useCallback(()=>{t?.send(JSON.stringify({type:"subscribe",keys:o}));},[t,o]),w=useCallback(l=>{let r=JSON.parse(l.data.toString());console.log("Message re\xE7u : "+l.data),e(d=>({...d,[r.key]:JSON.parse(r.value)}));},[]);return useEffect(()=>{if(t)return t.readyState===WebSocket.OPEN&&i(),t.addEventListener("open",i),t.addEventListener("message",w),()=>{t.removeEventListener("open",i),t.removeEventListener("message",w);}},[t]),useEffect(()=>{console.log("update keys",o),i();},[o]),c}function D(...s){useContext(p);let o=useCallback(async(e,t)=>(t&&typeof t=="object"&&(t=JSON.stringify(t)),await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"set",key:e,value:t}),headers:{"Content-Type":"application/json"}})),[]),c=useCallback(async e=>{await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"get",key:e}),headers:{"Content-Type":"application/json"}});},[]);return {set:o,get:c,inctement:async(e,t)=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"inctement",key:e,value:t}),headers:{"Content-Type":"application/json"}}),decrement:async(e,t)=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"decrement",key:e,value:t}),headers:{"Content-Type":"application/json"}}),del:async e=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"del",key:e}),headers:{"Content-Type":"application/json"}})}}
4
+ function v(){let[o,a]=useState(null),[i,s]=useState(!0),e="u9lt242tz2pn5hl5x444ls2xllnvip",t=useCallback(async()=>{let r=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");if(r){localStorage.setItem("twitch_access_token",r);let c=(await fetch("https://api.twitch.tv/helix/users",{headers:{Authorization:`Bearer ${r}`,"Client-Id":e}}).then(y=>y.json())).data[0];a(c);}},[]),n=useCallback(async()=>{try{let r="http://localhost:3000/test",p=["user:read:email","channel:read:vips","user:read:follows","user:read:subscriptions"].join(" "),c=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");if(!c)window.location.replace(`https://id.twitch.tv/oauth2/authorize?client_id=${e}&redirect_uri=${r}&response_type=token&scope=${p}&force_verify=true`);else {localStorage.setItem("twitch_access_token",c);let _=(await fetch("https://api.twitch.tv/helix/users",{headers:{Authorization:`Bearer ${c}`,"Client-Id":e}}).then(T=>T.json())).data[0];a(_);}}catch(r){console.error("Erreur lors de l'authentification :",r);}finally{s(!1);}},[]),h=useCallback(()=>{localStorage.removeItem("twitch_access_token"),a(null);},[]),d=useCallback(async()=>{let r=new URLSearchParams(window.location.hash).get("#access_token")||localStorage.getItem("twitch_access_token");await fetch("https://api.twitch.tv/helix/channels/vips?broadcaster_id=540958129",{method:"GET",headers:{Authorization:`Bearer ${r}`,"Client-Id":e}}).then(c=>c.json());},[]);return useEffect(()=>{t();},[]),{user:o,loading:i,fetchVips:d,authenticate:n,logout:h}}function b({authenticate:o}){return jsx("div",{className:"absolute inset-0 bg-black/60 backdrop-blur-xl",children:jsxs("div",{className:"absolute top-1/2 left-1/2 -translate-x-full -translate-y-full bg-popover flex items-start rounded-md ring-1 ring-white/10 flex-col p-3 gap-3 cursor-pointer shadow-md bg-black text-white",children:[jsx("div",{children:"Salut"}),jsx("button",{className:"bg-white rounded-md p-2 text-xs whitespace-nowrap text-black",onClick:o,children:"Log In"}),jsx("span",{className:"text-xs",children:"Powered by Sparkle"})]})})}function f({user:o,logout:a}){return jsx("div",{className:"bg-popover flex items-start fixed right-3 bottom-3 rounded-md ring-1 ring-white/10 flex-col p-3 gap-3 hover:-translate-y-1 transition-all cursor-pointer shadow-md bg-black text-white duration-500",children:jsxs("div",{className:"flex w-full flex-row items-center gap-3",children:[jsx("div",{className:"flex h-[34px] w-[34px] flex-shrink-0 items-center justify-center overflow-hidden rounded-lg bg-[#313131] text-sm",children:jsx("img",{src:o?.profile_image_url||"",alt:o?.display_name+"'s profile picture",width:34,height:34})}),jsxs("div",{className:"flex w-full flex-col justify-center min-w-[124px]",children:[jsx("div",{className:"space-x-2",children:jsx("span",{className:"text-primary text-sm font-medium capitalize",children:o?.display_name})}),jsx("span",{className:"text-muted-foreground text-xs font-normal",children:"Broadcaster"})]}),jsx("button",{className:"bg-red-500 rounded-md p-2 text-xs whitespace-nowrap",onClick:a,children:"Log Out"})]})})}var w=createContext({socket:void 0}),K=({children:o})=>{let[a,i]=useState(),{user:s,authenticate:e,logout:t}=v();return useEffect(()=>{let n=new WebSocket("ws://localhost:8000");return i(n),()=>{n.close();}},[]),jsxs(w.Provider,{value:{socket:a},children:[!s&&jsx(b,{authenticate:e}),s&&jsx(Fragment,{children:jsx(f,{user:s,logout:t})}),o]})};function rt(...o){let a=useContext(w),i=useMemo(()=>o,[o.join(",")]),[s,e]=useState(i.reduce((d,r)=>({...d,[r]:""}),{}));if(!a)throw new Error("You must use useDatabase inside a SparkleProvider");let{socket:t}=a,n=useCallback(()=>{t?.send(JSON.stringify({type:"subscribe",keys:i}));},[t,i]),h=useCallback(d=>{let r=JSON.parse(d.data.toString());console.log("Message re\xE7u : "+d.data),e(p=>({...p,[r.key]:JSON.parse(r.value)}));},[]);return useEffect(()=>{if(t)return t.readyState===WebSocket.OPEN&&n(),t.addEventListener("open",n),t.addEventListener("message",h),()=>{t.removeEventListener("open",n),t.removeEventListener("message",h);}},[t]),useEffect(()=>{console.log("update keys",i),n();},[i]),s}function st(...o){useContext(w);let i=useCallback(async(e,t)=>(t&&typeof t=="object"&&(t=JSON.stringify(t)),await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"set",key:e,value:t}),headers:{"Content-Type":"application/json"}})),[]),s=useCallback(async e=>{await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"get",key:e}),headers:{"Content-Type":"application/json"}});},[]);return {set:i,get:s,inctement:async(e,t)=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"inctement",key:e,value:t}),headers:{"Content-Type":"application/json"}}),decrement:async(e,t)=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"decrement",key:e,value:t}),headers:{"Content-Type":"application/json"}}),del:async e=>await fetch("http://localhost:4005/actions",{method:"POST",body:JSON.stringify({action:"del",key:e}),headers:{"Content-Type":"application/json"}})}}
5
5
 
6
- export { p as SparkleContext, L as SparkleProvider, D as useData, W as useRealtime, u as useTwitch };
6
+ export { w as SparkleContext, K as SparkleProvider, st as useData, rt as useRealtime, v as useTwitch };
7
7
  //# sourceMappingURL=out.js.map
8
8
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.tsx","../src/hooks/useTwitch.ts","../src/hooks/useRealtime.ts","../src/hooks/useData.ts"],"names":["createContext","useEffect","useState","useCallback","useTwitch","user","setUser","loading","setLoading","clientId","tryAuthenticate","accessToken","res","authenticate","redirectUri","scope","error","logout","fetchVips","result","jsx","SparkleContext","SparkleProvider","children","socket","setSocket","ws","useContext","useMemo","useRealtime","keyInputs","context","keys","state","setState","acc","key","openOpen","openMessage","event","data","useData","set","value","get"],"mappings":"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","sourcesContent":["import { type ReactNode, createContext, useEffect, useState } from \"react\"\nimport { type TwitchUser, useTwitch } from \"./hooks/useTwitch\"\nimport LoginForm from \"./components/login-form\"\nimport UserInfo from \"./components/user-info\"\n\ninterface WebSocketContextType {\n socket: WebSocket | undefined\n}\n\nexport const SparkleContext = createContext<WebSocketContextType>({\n socket: undefined,\n})\n\ninterface SparkleProviderProps {\n children: ReactNode\n}\n\nexport const SparkleProvider = ({ children }: SparkleProviderProps) => {\n const [socket, setSocket] = useState<WebSocket>()\n const { user, authenticate, logout } = useTwitch()\n\n useEffect(() => {\n const ws = new WebSocket(\"ws://localhost:8000\")\n setSocket(ws)\n\n return () => {\n ws.close()\n }\n }, [])\n\n return (\n <SparkleContext.Provider\n value={{\n socket,\n }}\n >\n {/* {!user && <LoginForm authenticate={authenticate} />}\n {user && (\n <>\n <UserInfo user={user} logout={logout} />\n </>\n )} */}\n {children}\n </SparkleContext.Provider>\n )\n}\n","import { useState, useEffect, useCallback } from \"react\"\n\nexport interface TwitchUser {\n id: string\n login: string\n display_name: string\n type: string\n broadcaster_type: string\n description: string\n profile_image_url: string\n offline_image_url: string\n view_count: number\n email: string\n}\n\nexport function useTwitch() {\n const [user, setUser] = useState<TwitchUser | null>(null)\n const [loading, setLoading] = useState(true)\n\n const clientId = \"u9lt242tz2pn5hl5x444ls2xllnvip\"\n\n const tryAuthenticate = useCallback(async () => {\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n if (accessToken) {\n localStorage.setItem(\"twitch_access_token\", accessToken)\n\n const response = await fetch(\"https://api.twitch.tv/helix/users\", {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }).then((res) => res.json())\n\n const user = response.data[0]\n setUser(user)\n }\n }, [])\n\n const authenticate = useCallback(async () => {\n try {\n const redirectUri = \"http://localhost:3000/test\"\n const scope = [\n \"user:read:email\",\n \"channel:read:vips\",\n \"user:read:follows\",\n \"user:read:subscriptions\",\n ].join(\" \")\n\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n if (!accessToken) {\n // Redirigez pour l'authentification si aucun token n'est trouvé\n window.location.replace(\n `https://id.twitch.tv/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=token&scope=${scope}&force_verify=true`\n )\n } else {\n // Stockez le token dans le stockage local\n localStorage.setItem(\"twitch_access_token\", accessToken)\n\n const response = await fetch(\"https://api.twitch.tv/helix/users\", {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }).then((res) => res.json())\n\n const user = response.data[0]\n\n // Utilisez le token pour faire des requêtes à l'API Twitch\n // const [follow, subscription] = await Promise.all([\n // await fetch(\n // `https://api.twitch.tv/helix/subscriptions/user?broadcaster_id=540958129&user_id=${user.id}`,\n // {\n // headers: {\n // Authorization: `Bearer ${accessToken}`,\n // \"Client-Id\": clientId,\n // },\n // }\n // ).then((res) => res.json()),\n // await fetch(\n // `https://api.twitch.tv/helix/channels/followed?broadcaster_id=540958129&user_id=${user.id}`,\n // {\n // headers: {\n // Authorization: `Bearer ${accessToken}`,\n // \"Client-Id\": clientId,\n // },\n // }\n // ).then((res) => res.json()),\n // ])\n\n // console.log(follow, subscription)\n\n setUser(user)\n }\n } catch (error) {\n console.error(\"Erreur lors de l'authentification :\", error)\n } finally {\n setLoading(false)\n }\n }, [])\n\n const logout = useCallback(() => {\n localStorage.removeItem(\"twitch_access_token\")\n setUser(null)\n }, [])\n\n const fetchVips = useCallback(async () => {\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n const result = await fetch(\n \"https://api.twitch.tv/helix/channels/vips?broadcaster_id=540958129\",\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }\n ).then((res) => res.json())\n }, [])\n\n useEffect(() => {\n tryAuthenticate()\n }, [])\n\n return { user, loading, fetchVips, authenticate, logout }\n}\n","import { useCallback, useState, useContext, useEffect, useMemo } from \"react\"\nimport { SparkleContext } from \"../provider\"\n\nexport function useRealtime<T extends string>(...keyInputs: T[]) {\n type State = Record<T, any>\n\n const context = useContext(SparkleContext)\n\n const keys = useMemo(() => keyInputs, [keyInputs.join(\",\")])\n\n const [state, setState] = useState<State>(\n keys.reduce((acc, key) => ({ ...acc, [key]: \"\" }), {} as State)\n )\n\n if (!context) {\n throw new Error(\"You must use useDatabase inside a SparkleProvider\")\n }\n\n const { socket } = context\n\n const openOpen = useCallback(() => {\n socket?.send(JSON.stringify({ type: \"subscribe\", keys }))\n }, [socket, keys])\n\n const openMessage = useCallback((event: MessageEvent) => {\n const data = JSON.parse(event.data.toString())\n\n console.log(\"Message reçu : \" + event.data)\n\n setState((state) => ({\n ...state,\n [data.key]: JSON.parse(data.value),\n }))\n }, [])\n\n useEffect(() => {\n if (!socket) return\n\n if (socket.readyState === WebSocket.OPEN) {\n openOpen()\n }\n\n socket.addEventListener(\"open\", openOpen)\n socket.addEventListener(\"message\", openMessage)\n\n return () => {\n socket.removeEventListener(\"open\", openOpen)\n socket.removeEventListener(\"message\", openMessage)\n }\n }, [socket])\n\n useEffect(() => {\n console.log(\"update keys\", keys)\n openOpen()\n }, [keys])\n\n return state\n}\n","import { useCallback, useContext } from \"react\"\nimport { SparkleContext } from \"../provider\"\n\nexport function useData<T extends string>(...keys: T[]) {\n const context = useContext(SparkleContext)\n\n const set = useCallback(async (key: string, value: any) => {\n if (value && typeof value === \"object\") {\n value = JSON.stringify(value)\n }\n\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({\n action: \"set\",\n key,\n value,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n }, [])\n\n const get = useCallback(async (key: string) => {\n const value = await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"get\", key }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n\n // return JSON.parse(value.)\n }, [])\n\n return {\n set,\n get,\n inctement: async (key: string, value: number) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"inctement\", key, value }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n decrement: async (key: string, value: number) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"decrement\", key, value }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n del: async (key: string) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"del\", key }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/provider.tsx","../src/hooks/useTwitch.ts","../src/components/login-form.tsx","../src/components/user-info.tsx","../src/hooks/useRealtime.ts","../src/hooks/useData.ts"],"names":["createContext","useEffect","useState","useCallback","useTwitch","user","setUser","loading","setLoading","clientId","tryAuthenticate","accessToken","res","authenticate","redirectUri","scope","error","logout","fetchVips","result","jsx","jsxs","LoginForm","UserInfo","Fragment","SparkleContext","SparkleProvider","children","socket","setSocket","ws","useContext","useMemo","useRealtime","keyInputs","context","keys","state","setState","acc","key","openOpen","openMessage","event","data","useData","set","value","get"],"mappings":"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","sourcesContent":["import { type ReactNode, createContext, useEffect, useState } from \"react\"\nimport { type TwitchUser, useTwitch } from \"./hooks/useTwitch\"\nimport LoginForm from \"./components/login-form\"\nimport UserInfo from \"./components/user-info\"\n\ninterface WebSocketContextType {\n socket: WebSocket | undefined\n}\n\nexport const SparkleContext = createContext<WebSocketContextType>({\n socket: undefined,\n})\n\ninterface SparkleProviderProps {\n children: ReactNode\n}\n\nexport const SparkleProvider = ({ children }: SparkleProviderProps) => {\n const [socket, setSocket] = useState<WebSocket>()\n const { user, authenticate, logout } = useTwitch()\n\n useEffect(() => {\n const ws = new WebSocket(\"ws://localhost:8000\")\n setSocket(ws)\n\n return () => {\n ws.close()\n }\n }, [])\n\n return (\n <SparkleContext.Provider\n value={{\n socket,\n }}\n >\n {!user && <LoginForm authenticate={authenticate} />}\n {user && (\n <>\n <UserInfo user={user} logout={logout} />\n </>\n )}\n {children}\n </SparkleContext.Provider>\n )\n}\n","import { useState, useEffect, useCallback } from \"react\"\n\nexport interface TwitchUser {\n id: string\n login: string\n display_name: string\n type: string\n broadcaster_type: string\n description: string\n profile_image_url: string\n offline_image_url: string\n view_count: number\n email: string\n}\n\nexport function useTwitch() {\n const [user, setUser] = useState<TwitchUser | null>(null)\n const [loading, setLoading] = useState(true)\n\n const clientId = \"u9lt242tz2pn5hl5x444ls2xllnvip\"\n\n const tryAuthenticate = useCallback(async () => {\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n if (accessToken) {\n localStorage.setItem(\"twitch_access_token\", accessToken)\n\n const response = await fetch(\"https://api.twitch.tv/helix/users\", {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }).then((res) => res.json())\n\n const user = response.data[0]\n setUser(user)\n }\n }, [])\n\n const authenticate = useCallback(async () => {\n try {\n const redirectUri = \"http://localhost:3000/test\"\n const scope = [\n \"user:read:email\",\n \"channel:read:vips\",\n \"user:read:follows\",\n \"user:read:subscriptions\",\n ].join(\" \")\n\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n if (!accessToken) {\n // Redirigez pour l'authentification si aucun token n'est trouvé\n window.location.replace(\n `https://id.twitch.tv/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=token&scope=${scope}&force_verify=true`\n )\n } else {\n // Stockez le token dans le stockage local\n localStorage.setItem(\"twitch_access_token\", accessToken)\n\n const response = await fetch(\"https://api.twitch.tv/helix/users\", {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }).then((res) => res.json())\n\n const user = response.data[0]\n\n // Utilisez le token pour faire des requêtes à l'API Twitch\n // const [follow, subscription] = await Promise.all([\n // await fetch(\n // `https://api.twitch.tv/helix/subscriptions/user?broadcaster_id=540958129&user_id=${user.id}`,\n // {\n // headers: {\n // Authorization: `Bearer ${accessToken}`,\n // \"Client-Id\": clientId,\n // },\n // }\n // ).then((res) => res.json()),\n // await fetch(\n // `https://api.twitch.tv/helix/channels/followed?broadcaster_id=540958129&user_id=${user.id}`,\n // {\n // headers: {\n // Authorization: `Bearer ${accessToken}`,\n // \"Client-Id\": clientId,\n // },\n // }\n // ).then((res) => res.json()),\n // ])\n\n // console.log(follow, subscription)\n\n setUser(user)\n }\n } catch (error) {\n console.error(\"Erreur lors de l'authentification :\", error)\n } finally {\n setLoading(false)\n }\n }, [])\n\n const logout = useCallback(() => {\n localStorage.removeItem(\"twitch_access_token\")\n setUser(null)\n }, [])\n\n const fetchVips = useCallback(async () => {\n const accessToken =\n new URLSearchParams(window.location.hash).get(\"#access_token\") ||\n localStorage.getItem(\"twitch_access_token\")\n\n const result = await fetch(\n \"https://api.twitch.tv/helix/channels/vips?broadcaster_id=540958129\",\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Client-Id\": clientId,\n },\n }\n ).then((res) => res.json())\n }, [])\n\n useEffect(() => {\n tryAuthenticate()\n }, [])\n\n return { user, loading, fetchVips, authenticate, logout }\n}\n","interface LoginFormProps {\n authenticate: () => void\n}\n\nexport default function LoginForm({ authenticate }: LoginFormProps) {\n return (\n <div className=\"absolute inset-0 bg-black/60 backdrop-blur-xl\">\n <div className=\"absolute top-1/2 left-1/2 -translate-x-full -translate-y-full bg-popover flex items-start rounded-md ring-1 ring-white/10 flex-col p-3 gap-3 cursor-pointer shadow-md bg-black text-white\">\n <div>Salut</div>\n\n <button\n className=\"bg-white rounded-md p-2 text-xs whitespace-nowrap text-black\"\n onClick={authenticate}\n >\n Log In\n </button>\n\n <span className=\"text-xs\">Powered by Sparkle</span>\n </div>\n </div>\n )\n}\n","import { TwitchUser } from \"../hooks/useTwitch\"\n\ninterface UserInfoProps {\n user: TwitchUser\n logout: () => void\n}\n\nexport default function UserInfo({ user, logout }: UserInfoProps) {\n return (\n <div className=\"bg-popover flex items-start fixed right-3 bottom-3 rounded-md ring-1 ring-white/10 flex-col p-3 gap-3 hover:-translate-y-1 transition-all cursor-pointer shadow-md bg-black text-white duration-500\">\n {/* <div className=\"text-gray-400 text-xs\">Currently logged in as </div> */}\n <div className=\"flex w-full flex-row items-center gap-3\">\n <div className=\"flex h-[34px] w-[34px] flex-shrink-0 items-center justify-center overflow-hidden rounded-lg bg-[#313131] text-sm\">\n <img\n src={user?.profile_image_url || \"\"}\n alt={user?.display_name + \"'s profile picture\"}\n width={34}\n height={34}\n />\n </div>\n <div className=\"flex w-full flex-col justify-center min-w-[124px]\">\n <div className=\"space-x-2\">\n <span className=\"text-primary text-sm font-medium capitalize\">\n {user?.display_name}\n </span>\n </div>\n <span className=\"text-muted-foreground text-xs font-normal\">\n Broadcaster\n </span>\n </div>\n <button\n className=\"bg-red-500 rounded-md p-2 text-xs whitespace-nowrap\"\n onClick={logout}\n >\n Log Out\n </button>\n </div>\n </div>\n )\n}\n","import { useCallback, useState, useContext, useEffect, useMemo } from \"react\"\nimport { SparkleContext } from \"../provider\"\n\nexport function useRealtime<T extends string>(...keyInputs: T[]) {\n type State = Record<T, any>\n\n const context = useContext(SparkleContext)\n\n const keys = useMemo(() => keyInputs, [keyInputs.join(\",\")])\n\n const [state, setState] = useState<State>(\n keys.reduce((acc, key) => ({ ...acc, [key]: \"\" }), {} as State)\n )\n\n if (!context) {\n throw new Error(\"You must use useDatabase inside a SparkleProvider\")\n }\n\n const { socket } = context\n\n const openOpen = useCallback(() => {\n socket?.send(JSON.stringify({ type: \"subscribe\", keys }))\n }, [socket, keys])\n\n const openMessage = useCallback((event: MessageEvent) => {\n const data = JSON.parse(event.data.toString())\n\n console.log(\"Message reçu : \" + event.data)\n\n setState((state) => ({\n ...state,\n [data.key]: JSON.parse(data.value),\n }))\n }, [])\n\n useEffect(() => {\n if (!socket) return\n\n if (socket.readyState === WebSocket.OPEN) {\n openOpen()\n }\n\n socket.addEventListener(\"open\", openOpen)\n socket.addEventListener(\"message\", openMessage)\n\n return () => {\n socket.removeEventListener(\"open\", openOpen)\n socket.removeEventListener(\"message\", openMessage)\n }\n }, [socket])\n\n useEffect(() => {\n console.log(\"update keys\", keys)\n openOpen()\n }, [keys])\n\n return state\n}\n","import { useCallback, useContext } from \"react\"\nimport { SparkleContext } from \"../provider\"\n\nexport function useData<T extends string>(...keys: T[]) {\n const context = useContext(SparkleContext)\n\n const set = useCallback(async (key: string, value: any) => {\n if (value && typeof value === \"object\") {\n value = JSON.stringify(value)\n }\n\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({\n action: \"set\",\n key,\n value,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n }, [])\n\n const get = useCallback(async (key: string) => {\n const value = await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"get\", key }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n\n // return JSON.parse(value.)\n }, [])\n\n return {\n set,\n get,\n inctement: async (key: string, value: number) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"inctement\", key, value }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n decrement: async (key: string, value: number) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"decrement\", key, value }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n del: async (key: string) => {\n return await fetch(\"http://localhost:4005/actions\", {\n method: \"POST\",\n body: JSON.stringify({ action: \"del\", key }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n })\n },\n }\n}\n"]}
package/package.json CHANGED
@@ -1,14 +1,9 @@
1
1
  {
2
2
  "name": "sparkle-react",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
7
- "main": "./dist/index.mjs",
8
- "exports": {
9
- ".": "./dist/index.mjs",
10
- "./styles.css": "./dist/index.css"
11
- },
12
7
  "types": "./dist/index.d.mts",
13
8
  "license": "MIT",
14
9
  "devDependencies": {