feat(admin-sdk,admin-bundler,admin-shared,medusa): Restructure admin packages (#8988)
**What** - Renames /admin-next -> /admin - Renames @medusajs/admin-sdk -> @medusajs/admin-bundler - Creates a new package called @medusajs/admin-sdk that will hold all tooling relevant to creating admin extensions. This is currently `defineRouteConfig` and `defineWidgetConfig`, but will eventually also export methods for adding custom fields, register translation, etc. - cc: @shahednasser we should update the examples in the docs so these functions are imported from `@medusajs/admin-sdk`. People will also need to install the package in their project, as it's no longer a transient dependency. - cc: @olivermrbl we might want to publish a changelog when this is merged, as it is a breaking change, and will require people to import the `defineXConfig` from the new package instead of `@medusajs/admin-shared`. - Updates CODEOWNERS so /admin packages does not require a review from the UI team.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export type { ThemeOption as Theme } from "./theme-context"
|
||||
export * from "./theme-provider"
|
||||
export * from "./use-theme"
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createContext } from "react"
|
||||
|
||||
export type ThemeOption = "light" | "dark" | "system"
|
||||
export type ThemeValue = "light" | "dark"
|
||||
|
||||
type ThemeContextValue = {
|
||||
theme: ThemeOption
|
||||
setTheme: (theme: ThemeOption) => void
|
||||
}
|
||||
|
||||
export const ThemeContext = createContext<ThemeContextValue | null>(null)
|
||||
@@ -0,0 +1,82 @@
|
||||
import { PropsWithChildren, useEffect, useState } from "react"
|
||||
import { ThemeContext, ThemeOption, ThemeValue } from "./theme-context"
|
||||
|
||||
const THEME_KEY = "medusa_admin_theme"
|
||||
|
||||
function getDefaultValue(): ThemeOption {
|
||||
const persisted = localStorage?.getItem(THEME_KEY) as ThemeOption
|
||||
|
||||
if (persisted) {
|
||||
return persisted
|
||||
}
|
||||
|
||||
return "system"
|
||||
}
|
||||
|
||||
function getThemeValue(selected: ThemeOption): ThemeValue {
|
||||
if (selected === "system") {
|
||||
if (window !== undefined) {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light"
|
||||
}
|
||||
|
||||
// Default to light theme if we can't detect the system preference
|
||||
return "light"
|
||||
}
|
||||
|
||||
return selected
|
||||
}
|
||||
|
||||
export const ThemeProvider = ({ children }: PropsWithChildren) => {
|
||||
const [state, setState] = useState<ThemeOption>(getDefaultValue())
|
||||
const [value, setValue] = useState<ThemeValue>(getThemeValue(state))
|
||||
|
||||
const setTheme = (theme: ThemeOption) => {
|
||||
localStorage.setItem(THEME_KEY, theme)
|
||||
|
||||
const themeValue = getThemeValue(theme)
|
||||
|
||||
setState(theme)
|
||||
setValue(themeValue)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const html = document.querySelector("html")
|
||||
if (html) {
|
||||
/**
|
||||
* Temporarily disable transitions to prevent
|
||||
* the theme change from flashing.
|
||||
*/
|
||||
const css = document.createElement("style")
|
||||
css.appendChild(
|
||||
document.createTextNode(
|
||||
`* {
|
||||
-webkit-transition: none !important;
|
||||
-moz-transition: none !important;
|
||||
-o-transition: none !important;
|
||||
-ms-transition: none !important;
|
||||
transition: none !important;
|
||||
}`
|
||||
)
|
||||
)
|
||||
document.head.appendChild(css)
|
||||
|
||||
html.classList.remove(value === "light" ? "dark" : "light")
|
||||
html.classList.add(value)
|
||||
|
||||
/**
|
||||
* Re-enable transitions after the theme has been set,
|
||||
* and force the browser to repaint.
|
||||
*/
|
||||
window.getComputedStyle(css).opacity
|
||||
document.head.removeChild(css)
|
||||
}
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme: state, setTheme }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useContext } from "react"
|
||||
import { ThemeContext } from "./theme-context"
|
||||
|
||||
export const useTheme = () => {
|
||||
const context = useContext(ThemeContext)
|
||||
if (!context) {
|
||||
throw new Error("useTheme must be used within a ThemeProvider")
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user