-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(ShaderGradientStateless) ---- StoreShaderGradient ---- fmt start StoreShaderGradient move other preset (object format) fmt restore include zustand (it is already dependecny of react-three-fiber) StoreShaderGradient restore tsup.framer.config.ts rename: ShaderGradientStateless (was StoreShaderGradient) fmt rm missing files config (need to be added)
- Loading branch information
Showing
14 changed files
with
554 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
'use client' | ||
|
||
import { ShaderGradientCanvas } from '@shadergradient/react' | ||
import { | ||
useQueryState, | ||
ShaderGradientStateless, | ||
} from '@shadergradient/react/stateless' | ||
|
||
export default function Page() { | ||
const [, setColor1] = useQueryState('color1') | ||
|
||
return ( | ||
<div className='flex'> | ||
<div className='flex-1 h-screen'> | ||
<ShaderGradientCanvas> | ||
{/* When control is 'query', the gradient props follows url query params */} | ||
<ShaderGradientStateless control='query' /> | ||
</ShaderGradientCanvas> | ||
</div> | ||
|
||
<button | ||
onClick={() => setColor1('#0D77E0')} | ||
className='fixed bottom-5 right-5 z-20' | ||
> | ||
Change Color | ||
</button> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
packages/shadergradient-v2/src/ShaderGradientStateless/ShaderGradientStateless.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { GradientT } from '@/types' | ||
import { ShaderGradient } from '../ShaderGradient/ShaderGradient' | ||
import { useSearchParamToStore } from './store/useSearchParamToStore' | ||
import { useControlValues } from './useControlValues' | ||
|
||
export function ShaderGradientStateless(passedProps: GradientT): JSX.Element { | ||
useSearchParamToStore() // init gradient state with url query | ||
const props = useControlValues(passedProps.control, passedProps) // make props using url query, control and passed props | ||
|
||
return <ShaderGradient {...props} /> | ||
} |
2 changes: 2 additions & 0 deletions
2
packages/shadergradient-v2/src/ShaderGradientStateless/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './store/useQueryState' | ||
export * from './ShaderGradientStateless' |
5 changes: 5 additions & 0 deletions
5
packages/shadergradient-v2/src/ShaderGradientStateless/store/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './store' | ||
export * from './useQueryState' | ||
|
||
export * from './presetURLs' | ||
export * from './usePresetToStore' |
30 changes: 30 additions & 0 deletions
30
packages/shadergradient-v2/src/ShaderGradientStateless/store/presetURLs.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { presets } from '@/presets' | ||
|
||
export const initialActivePreset = 0 | ||
|
||
export const PRESETS = convertPresets(presets) | ||
|
||
// export const DEFAUlT_PRESET = '?pixelDensity=1&fov=45' | ||
export const DEFAUlT_PRESET = PRESETS[0].url | ||
|
||
function convertPresets(presets: Record<string, any>) { | ||
const PRESETS = Object.entries(presets).map(([key, value]) => { | ||
const { title, color, props } = value | ||
|
||
const urlParams = new URLSearchParams( | ||
Object.entries(props).reduce((acc, [propKey, propValue]) => { | ||
acc[propKey] = | ||
typeof propValue === 'boolean' ? String(propValue) : String(propValue) | ||
return acc | ||
}, {} as Record<string, string>) | ||
).toString() | ||
|
||
return { | ||
title, | ||
color, | ||
url: `?${urlParams}`, | ||
} | ||
}) | ||
|
||
return PRESETS | ||
} |
77 changes: 77 additions & 0 deletions
77
packages/shadergradient-v2/src/ShaderGradientStateless/store/store.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import * as qs from 'query-string' | ||
import { create } from 'zustand' | ||
import { combine } from 'zustand/middleware' | ||
import { DEFAUlT_PRESET, initialActivePreset } from './presetURLs' | ||
|
||
// without embedMode | ||
// it renders without the dom & other gradient controls at first, and add it after the first updateGradientState() excuted. | ||
|
||
const defaultState = { ...parseState() } | ||
export const useQueryStore = create((set) => defaultState) | ||
|
||
export const updateGradientState = (querystate: object | string) => { | ||
const isString = typeof querystate === 'string' | ||
|
||
let state = querystate | ||
if (isString) state = parseState(querystate) | ||
|
||
useQueryStore.setState(state, isString) // replace true if it's a string | ||
} | ||
|
||
// defaultGradient could be replaced by window.location.search | ||
function parseState(search = DEFAUlT_PRESET) { | ||
return qs.parse(search, { | ||
parseNumbers: true, | ||
parseBooleans: true, | ||
arrayFormat: 'index', | ||
}) | ||
} | ||
|
||
export const useDomStore = create(() => { | ||
return { dom: null } | ||
}) | ||
|
||
// store for UI updates | ||
export const useCursorStore = create((set) => ({ | ||
hoverState: 0, | ||
hover: 'default', | ||
updateHoverState: (payload) => set({ hoverState: payload }), | ||
})) | ||
export const useUIStore = create( | ||
combine( | ||
{ activePreset: initialActivePreset, mode: 'full', loadingPercentage: 0 }, | ||
(set) => ({ | ||
setActivePreset: (by: number) => set((state) => ({ activePreset: by })), | ||
setMode: (data: any) => set((state) => ({ ...state, mode: data })), | ||
setLoadingPercentage: (data: any) => | ||
set((state) => ({ ...state, loadingPercentage: data })), | ||
}) | ||
) | ||
) | ||
|
||
// store for Figma Plugin | ||
const useFigmaStore = create((set) => ({ | ||
figma: { selection: 0, user: null }, | ||
setFigma: (payload) => | ||
set((prev) => ({ figma: { ...prev.figma, ...payload } })), | ||
})) | ||
export function useFigma() { | ||
const figma = useFigmaStore((state: any) => state.figma) | ||
const setFigma = useFigmaStore((state: any) => state.setFigma) | ||
return [figma, setFigma] | ||
} | ||
|
||
export const useBillingIntervalStore = create((set) => ({ | ||
billingInterval: 'year', | ||
setBillingInterval: (payload) => | ||
set((state) => ({ billingInterval: payload })), | ||
})) | ||
export function useBillingInterval() { | ||
const billingInterval = useBillingIntervalStore( | ||
(state: any) => state.billingInterval | ||
) | ||
const setBillingInterval = useBillingIntervalStore( | ||
(state: any) => state.setBillingInterval | ||
) | ||
return [billingInterval, setBillingInterval] | ||
} |
25 changes: 25 additions & 0 deletions
25
packages/shadergradient-v2/src/ShaderGradientStateless/store/usePresetToStore.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { useEffect } from 'react' | ||
import { PRESETS } from './presetURLs' | ||
import { useUIStore, updateGradientState } from './store' | ||
|
||
let pageLoaded = false | ||
export function usePresetToStore() { | ||
// ----------------------------- Preset to Custom Material --------------------------------- | ||
const activePreset = useUIStore((state: any) => state.activePreset) | ||
useEffect(() => { | ||
let gradientURL | ||
|
||
// CASE 1. use search params at the first load. | ||
if ( | ||
!pageLoaded && | ||
window.location.search?.includes('pixelDensity') // checking just window.location.search existing is not valid for the Framer Preview search (?target=preview-web) | ||
) | ||
gradientURL = window.location.search | ||
// CASE 2. When activePreset changes by UI buttons | ||
else gradientURL = PRESETS[activePreset].url | ||
|
||
updateGradientState(gradientURL) | ||
|
||
pageLoaded = true | ||
}, [activePreset]) | ||
} |
87 changes: 87 additions & 0 deletions
87
packages/shadergradient-v2/src/ShaderGradientStateless/store/useQueryState.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { useCallback } from 'react' | ||
import * as qs from 'query-string' | ||
import { useQueryStore } from './store' | ||
|
||
export const useQueryState = (propName: any, defaultValue: any = null) => { | ||
const selector = useCallback( | ||
(state) => | ||
typeof state[propName] !== 'undefined' ? state[propName] : defaultValue, | ||
[propName, defaultValue] | ||
) | ||
const globalValue = useQueryStore(selector) | ||
const _setGlobalValue = useCallback( | ||
(valueFun) => | ||
useQueryStore.setState({ | ||
[propName]: valueFun(useQueryStore.getState()[propName]), | ||
}), | ||
[propName] | ||
) | ||
|
||
const setQueryValue = useCallback( | ||
(newVal) => { | ||
_setGlobalValue((currentState: any) => { | ||
if (typeof newVal === 'function') { | ||
newVal = newVal(currentState || defaultValue) | ||
} | ||
if (Number.isFinite(newVal)) { | ||
newVal = parseFloat(newVal.toFixed(2)) | ||
} | ||
|
||
// defer update of URL | ||
setTimeout(() => { | ||
const query = useQueryStore.getState() | ||
updateHistory( | ||
qs.stringifyUrl( | ||
// @ts-ignore | ||
{ url: window.location.pathname, query }, | ||
{ skipNull: true, arrayFormat: 'index' } | ||
) | ||
) | ||
}, 0) | ||
|
||
return newVal | ||
}) | ||
}, | ||
[_setGlobalValue] | ||
) | ||
|
||
return [globalValue, setQueryValue] | ||
} | ||
|
||
export const useURLQueryState = () => { | ||
// it's weird, but need to wrap below func as a hook | ||
const setQueryValue = (search) => { | ||
// defer update of URL | ||
setTimeout(() => { | ||
const query: any = useQueryStore.getState() | ||
updateHistory( | ||
qs.stringifyUrl( | ||
{ url: window.location.pathname, query }, | ||
{ skipNull: true, arrayFormat: 'index' } | ||
) | ||
) | ||
}, 0) | ||
|
||
const state = qs.parse(search, { | ||
parseNumbers: true, | ||
parseBooleans: true, | ||
arrayFormat: 'index', | ||
}) | ||
|
||
useQueryStore.setState(state) | ||
} | ||
return setQueryValue | ||
} | ||
|
||
function updateHistory(path: string) { | ||
window.history.pushState( | ||
{ | ||
prevUrls: [ | ||
...(window.history.state?.prevUrls || []), | ||
window.location.origin + path, | ||
], | ||
}, | ||
document.title, | ||
path | ||
) | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/shadergradient-v2/src/ShaderGradientStateless/store/useSearchParamToStore.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { useEffect } from 'react' | ||
import { updateGradientState } from './store' | ||
|
||
export function useSearchParamToStore() { | ||
useEffect(() => { | ||
// if ( | ||
// window.location.search?.includes('pixelDensity') // checking just window.location.search existing is not valid for the Framer Preview search (?target=preview-web) | ||
// ) | ||
updateGradientState(window.location.search) | ||
}, []) | ||
} |
Oops, something went wrong.