@jbpark/ui-kit 7.1.0 → 8.1.0
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/Button.d.mts +7 -2
- package/dist/Button.d.mts.map +1 -1
- package/dist/Button.mjs.map +1 -1
- package/dist/CodeEditor.d.mts +51 -0
- package/dist/CodeEditor.d.mts.map +1 -0
- package/dist/CodeEditor.mjs +87 -0
- package/dist/CodeEditor.mjs.map +1 -0
- package/dist/Tag.d.mts +8 -3
- package/dist/Tag.d.mts.map +1 -1
- package/dist/Tag.mjs.map +1 -1
- package/dist/components/atoms/float-button/float-button.d.mts.map +1 -1
- package/dist/components/atoms/float-button/float-button.mjs +2 -1
- package/dist/components/atoms/float-button/float-button.mjs.map +1 -1
- package/dist/components/molecules/dropdown.d.mts.map +1 -1
- package/dist/components/molecules/dropdown.mjs +2 -1
- package/dist/components/molecules/dropdown.mjs.map +1 -1
- package/dist/components/molecules/marquees/item.d.mts +2 -1
- package/dist/components/molecules/marquees/item.d.mts.map +1 -1
- package/dist/components/molecules/marquees/item.mjs +20 -5
- package/dist/components/molecules/marquees/item.mjs.map +1 -1
- package/dist/components/molecules/marquees/marquees.d.mts +2 -1
- package/dist/components/molecules/marquees/marquees.d.mts.map +1 -1
- package/dist/components/molecules/marquees/marquees.mjs +3 -2
- package/dist/components/molecules/marquees/marquees.mjs.map +1 -1
- package/dist/components/organisms/drawer.mjs +7 -7
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/components/templates/layout/header.d.mts.map +1 -1
- package/dist/components/templates/layout/header.mjs +2 -1
- package/dist/components/templates/layout/header.mjs.map +1 -1
- package/dist/components/templates/layout/sider.mjs.map +1 -1
- package/dist/components/templates/page-header.mjs +4 -4
- package/dist/components/templates/page-header.mjs.map +1 -1
- package/dist/core/dialog.mjs +5 -5
- package/dist/core/dialog.mjs.map +1 -1
- package/dist/core/drawer.mjs +3 -2
- package/dist/core/drawer.mjs.map +1 -1
- package/dist/core/popover.mjs +3 -2
- package/dist/core/popover.mjs.map +1 -1
- package/dist/core/select.d.mts.map +1 -1
- package/dist/core/select.mjs +3 -2
- package/dist/core/select.mjs.map +1 -1
- package/dist/lib/colors.d.mts +36 -3
- package/dist/lib/colors.d.mts.map +1 -1
- package/dist/lib/z-layers.mjs +33 -0
- package/dist/lib/z-layers.mjs.map +1 -0
- package/dist/providers/config/config.d.mts.map +1 -1
- package/dist/providers/config/config.mjs +5 -32
- package/dist/providers/config/config.mjs.map +1 -1
- package/dist/providers/config/dark-mode.mjs +39 -0
- package/dist/providers/config/dark-mode.mjs.map +1 -0
- package/dist/providers/config/types.d.mts +25 -18
- package/dist/providers/config/types.d.mts.map +1 -1
- package/dist/style.css +90 -90
- package/dist/utils.d.mts +12 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +12 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +33 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.mjs","names":[],"sources":["../../../src/providers/config/config.tsx"],"sourcesContent":["'use client';\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from 'react';\n\nimport { DirectionProvider } from '@radix-ui/react-direction';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { Context, DEFAULT_LOCALE, useConfig } from './context';\nimport { registerRootConfig } from './registry';\nimport type {\n ComponentSize,\n DefaultProps,\n Locale,\n ThemeConfig,\n ThemeToken,\n} from './types';\n\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)';\n\nconst subscribeToSystemColorScheme = (callback: () => void) => {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const mql = window.matchMedia(DARK_MEDIA_QUERY);\n mql.addEventListener('change', callback);\n return () => mql.removeEventListener('change', callback);\n};\n\nconst getSystemPrefersDark = () =>\n typeof window !== 'undefined' && window.matchMedia(DARK_MEDIA_QUERY).matches;\n\n// No `window` during SSR, so there's no way to know the visitor's actual\n// preference before hydration — assume light (the conservative default)\n// and let useSyncExternalStore correct it client-side once matchMedia is\n// available, same flash-of-incorrect-guess tradeoff already accepted for\n// Sider's breakpoint prop elsewhere in this library.\nconst getServerSnapshot = () => false;\n\nconst useSystemPrefersDark = () =>\n useSyncExternalStore(\n subscribeToSystemColorScheme,\n getSystemPrefersDark,\n getServerSnapshot,\n );\n\nconst tokenToCssVar: Record<keyof ThemeToken, string> = {\n colorPrimary: '--primary',\n colorPrimaryForeground: '--primary-foreground',\n colorBackground: '--background',\n colorForeground: '--foreground',\n colorCard: '--card',\n colorCardForeground: '--card-foreground',\n colorPopover: '--popover',\n colorPopoverForeground: '--popover-foreground',\n colorSecondary: '--secondary',\n colorSecondaryForeground: '--secondary-foreground',\n colorMuted: '--muted',\n colorMutedForeground: '--muted-foreground',\n colorAccent: '--accent',\n colorAccentForeground: '--accent-foreground',\n colorDestructive: '--destructive',\n colorBorder: '--border',\n colorInput: '--input',\n colorRing: '--ring',\n borderRadius: '--radius',\n\n btnBackground: '--btn-bg',\n btnBackgroundHover: '--btn-bg-hover',\n btnBackgroundActive: '--btn-bg-active',\n btnBorder: '--btn-border',\n btnForeground: '--btn-fg',\n\n sidebar: '--sidebar',\n sidebarForeground: '--sidebar-foreground',\n sidebarPrimary: '--sidebar-primary',\n sidebarPrimaryForeground: '--sidebar-primary-foreground',\n sidebarAccent: '--sidebar-accent',\n sidebarAccentForeground: '--sidebar-accent-foreground',\n sidebarBorder: '--sidebar-border',\n sidebarRing: '--sidebar-ring',\n\n chart1: '--chart-1',\n chart2: '--chart-2',\n chart3: '--chart-3',\n chart4: '--chart-4',\n chart5: '--chart-5',\n\n fontSans: '--font-sans',\n fontMono: '--font-mono',\n};\n\nconst buildCssVars = (token?: ThemeToken): React.CSSProperties => {\n if (!token) {\n return {};\n }\n\n const vars: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(token)) {\n if (value === undefined) {\n continue;\n }\n const cssVar = tokenToCssVar[key as keyof ThemeToken];\n if (cssVar) {\n vars[cssVar] = value;\n }\n }\n\n return vars as React.CSSProperties;\n};\n\ninterface Props {\n theme?: ThemeConfig;\n locale?: Locale;\n getContainer?: () => HTMLElement;\n componentSize?: ComponentSize;\n direction?: 'ltr' | 'rtl';\n defaultProps?: DefaultProps;\n className?: string;\n style?: React.CSSProperties;\n children: React.ReactNode;\n}\n\nconst Config = ({\n theme = {},\n locale = {},\n getContainer,\n componentSize,\n direction,\n defaultProps,\n className,\n style,\n children,\n}: Props) => {\n const parent = useConfig();\n const [wrapperEl, setWrapperEl] = useState<HTMLDivElement | null>(null);\n\n // Only a Config with no Config ancestor of its own registers for the\n // imperative stack (Modal.*/Toast.*) to inherit — see registry.tsx.\n const isRoot = !parent.isConfigured;\n\n // `theme` is typically a fresh inline object literal at the call site\n // (and `parent.theme` inherits the same problem from its own Config\n // ancestor), so depending on them directly meant mergedTheme/contextValue\n // got a new identity on every render regardless of whether the actual\n // values changed — every useConfig() consumer in the tree re-rendered on\n // every render of whatever's above this Config, which for the common\n // app-root usage is everything. Depend on a serialized key instead so\n // the memo only invalidates when the content actually changes; these\n // are small, string/boolean-only objects, so JSON.stringify is cheap.\n const themeKey = JSON.stringify(theme);\n const parentThemeKey = JSON.stringify(parent.theme);\n const localeKey = JSON.stringify(locale);\n const parentLocaleKey = JSON.stringify(parent.locale);\n\n const mergedTheme = useMemo<ThemeConfig>(\n () => ({\n ...parent.theme,\n ...theme,\n token: {\n ...parent.theme.token,\n ...theme.token,\n },\n darkToken: {\n ...parent.theme.darkToken,\n ...theme.darkToken,\n },\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentThemeKey, themeKey],\n );\n\n const mergedLocale = useMemo<Locale>(\n () => ({\n ...parent.locale,\n ...locale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentLocaleKey, localeKey],\n );\n\n const systemPrefersDark = useSystemPrefersDark();\n const isDarkActive =\n mergedTheme.dark === 'system'\n ? systemPrefersDark\n : mergedTheme.dark === 'dark';\n\n // `darkToken` overrides individual keys of `token` (not a full swap)\n // only while dark mode is actually active.\n const cssVars = useMemo(\n () =>\n buildCssVars(\n isDarkActive\n ? { ...mergedTheme.token, ...mergedTheme.darkToken }\n : mergedTheme.token,\n ),\n [mergedTheme.token, mergedTheme.darkToken, isDarkActive],\n );\n\n const hasCssVars = Object.keys(cssVars).length > 0;\n const hasDarkMode = mergedTheme.dark !== undefined;\n const needsWrapper =\n hasCssVars || hasDarkMode || !!className || !!style || !!direction;\n\n // Resolution order: an explicit `getContainer` prop on this Config wins;\n // otherwise, if this Config renders its own themed wrapper below, that's\n // the default (portaled content appended into it still inherits its CSS\n // custom properties and matches the `.dark` selector — `display:\n // contents` only removes the element from the layout box tree, not from\n // the DOM/cascade); otherwise defer to the parent Config's resolution,\n // so an inner Config that only sets e.g. `locale` doesn't shadow an\n // outer one's theme container.\n const resolvedGetContainer = useCallback((): HTMLElement | undefined => {\n if (getContainer) {\n return getContainer();\n }\n if (needsWrapper && wrapperEl) {\n return wrapperEl;\n }\n return parent.getContainer();\n }, [getContainer, needsWrapper, wrapperEl, parent]);\n\n const resolvedComponentSize = componentSize ?? parent.componentSize;\n const resolvedDirection = direction ?? parent.direction;\n\n const defaultPropsKey = JSON.stringify(defaultProps);\n const parentDefaultPropsKey = JSON.stringify(parent.defaultProps);\n\n const mergedDefaultProps = useMemo<DefaultProps | undefined>(\n () =>\n parent.defaultProps || defaultProps\n ? { ...parent.defaultProps, ...defaultProps }\n : undefined,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentDefaultPropsKey, defaultPropsKey],\n );\n\n const contextValue = useMemo(\n () => ({\n theme: mergedTheme,\n locale: mergedLocale,\n getContainer: resolvedGetContainer,\n componentSize: resolvedComponentSize,\n direction: resolvedDirection,\n defaultProps: mergedDefaultProps,\n isConfigured: true,\n }),\n [\n mergedTheme,\n mergedLocale,\n resolvedGetContainer,\n resolvedComponentSize,\n resolvedDirection,\n mergedDefaultProps,\n ],\n );\n\n useEffect(() => {\n if (!isRoot) {\n return;\n }\n return registerRootConfig(contextValue);\n }, [isRoot, contextValue]);\n\n const content = (\n <Context.Provider value={contextValue}>\n {needsWrapper ? (\n <div\n ref={setWrapperEl}\n dir={direction}\n className={cn(isDarkActive && 'dark', className)}\n style={{\n ...(hasCssVars ? cssVars : undefined),\n ...style,\n // Keeps this element out of the layout box tree — so it\n // doesn't intercept flex/grid child relationships or break\n // height chains like min-h-screen — while custom properties\n // and the `dark` class selector still cascade to children\n // normally (inheritance and box generation are separate\n // mechanisms in CSS). Note this means className/style\n // shouldn't be used here for anything that needs a real box\n // (padding, background, borders); Config's className/style are\n // meant for theming hooks (the `dark` class, arbitrary\n // selector hooks, custom properties), not layout — spread\n // after the caller's `style` so it can't be overridden into\n // something that reintroduces the layout-breaking wrapper this\n // was added to fix in the first place.\n display: 'contents',\n }}\n >\n {children}\n </div>\n ) : (\n children\n )}\n </Context.Provider>\n );\n\n // DirectionProvider is Radix's own mechanism (@radix-ui/react-direction)\n // for propagating `dir` to every primitive that calls its useDirection()\n // internally — Select, Menu (Dropdown/Menu), Accordion (Collapse),\n // RadioGroup, ScrollArea all pick up RTL automatically this way, no\n // per-component wiring needed. Only wraps when this Config's own\n // `direction` prop is set (not the merely-inherited resolved value) —\n // context already cascades on its own, so re-wrapping at every nested\n // Config that doesn't override direction would just be redundant.\n // Components with hardcoded LTR-only layout logic that Radix's Direction\n // context doesn't reach (Popover placement, Splitter, Sider, Drawer)\n // aren't covered by this and would need dedicated follow-up work.\n return direction ? (\n <DirectionProvider dir={direction}>{content}</DirectionProvider>\n ) : (\n content\n );\n};\n\nexport default Config;\nexport { useConfig, DEFAULT_LOCALE };\nexport type {\n Props,\n ComponentSize,\n DefaultProps,\n Locale,\n ThemeConfig,\n ThemeToken,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.mjs","names":[],"sources":["../../../src/providers/config/config.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { DirectionProvider } from '@radix-ui/react-direction';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { Context, DEFAULT_LOCALE, useConfig } from './context';\nimport { resolveDark, useSystemPrefersDark } from './dark-mode';\nimport { registerRootConfig } from './registry';\nimport type {\n ComponentSize,\n DefaultProps,\n Locale,\n ThemeConfig,\n ThemeToken,\n} from './types';\n\nconst tokenToCssVar: Record<keyof ThemeToken, string> = {\n colorPrimary: '--primary',\n colorPrimaryForeground: '--primary-foreground',\n colorBackground: '--background',\n colorForeground: '--foreground',\n colorCard: '--card',\n colorCardForeground: '--card-foreground',\n colorPopover: '--popover',\n colorPopoverForeground: '--popover-foreground',\n colorSecondary: '--secondary',\n colorSecondaryForeground: '--secondary-foreground',\n colorMuted: '--muted',\n colorMutedForeground: '--muted-foreground',\n colorAccent: '--accent',\n colorAccentForeground: '--accent-foreground',\n colorDestructive: '--destructive',\n colorBorder: '--border',\n colorInput: '--input',\n colorRing: '--ring',\n borderRadius: '--radius',\n\n // Not `--font-sans`/`--font-mono`: those are `@theme inline` entries, so\n // Tailwind substitutes their value into each utility rather than referencing\n // them, and a wrapper-level override never applied. `globals.css` reads these\n // hooks ahead of the app's own font variable instead (#343).\n fontSans: '--ui-font-sans',\n fontMono: '--ui-font-mono',\n};\n\nconst buildCssVars = (token?: ThemeToken): React.CSSProperties => {\n if (!token) {\n return {};\n }\n\n const vars: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(token)) {\n if (value === undefined) {\n continue;\n }\n const cssVar = tokenToCssVar[key as keyof ThemeToken];\n if (cssVar) {\n vars[cssVar] = value;\n }\n }\n\n return vars as React.CSSProperties;\n};\n\ninterface Props {\n theme?: ThemeConfig;\n locale?: Locale;\n getContainer?: () => HTMLElement;\n componentSize?: ComponentSize;\n direction?: 'ltr' | 'rtl';\n defaultProps?: DefaultProps;\n className?: string;\n style?: React.CSSProperties;\n children: React.ReactNode;\n}\n\nconst Config = ({\n theme = {},\n locale = {},\n getContainer,\n componentSize,\n direction,\n defaultProps,\n className,\n style,\n children,\n}: Props) => {\n const parent = useConfig();\n const [wrapperEl, setWrapperEl] = useState<HTMLDivElement | null>(null);\n\n // Only a Config with no Config ancestor of its own registers for the\n // imperative stack (Modal.*/Toast.*) to inherit — see registry.tsx.\n const isRoot = !parent.isConfigured;\n\n // `theme` is typically a fresh inline object literal at the call site\n // (and `parent.theme` inherits the same problem from its own Config\n // ancestor), so depending on them directly meant mergedTheme/contextValue\n // got a new identity on every render regardless of whether the actual\n // values changed — every useConfig() consumer in the tree re-rendered on\n // every render of whatever's above this Config, which for the common\n // app-root usage is everything. Depend on a serialized key instead so\n // the memo only invalidates when the content actually changes; these\n // are small, string/boolean-only objects, so JSON.stringify is cheap.\n const themeKey = JSON.stringify(theme);\n const parentThemeKey = JSON.stringify(parent.theme);\n const localeKey = JSON.stringify(locale);\n const parentLocaleKey = JSON.stringify(parent.locale);\n\n const mergedTheme = useMemo<ThemeConfig>(\n () => ({\n ...parent.theme,\n ...theme,\n token: {\n ...parent.theme.token,\n ...theme.token,\n },\n darkToken: {\n ...parent.theme.darkToken,\n ...theme.darkToken,\n },\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentThemeKey, themeKey],\n );\n\n const mergedLocale = useMemo<Locale>(\n () => ({\n ...parent.locale,\n ...locale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentLocaleKey, localeKey],\n );\n\n const systemPrefersDark = useSystemPrefersDark();\n const isDarkActive = resolveDark(mergedTheme.dark, systemPrefersDark);\n\n // `darkToken` overrides individual keys of `token` (not a full swap)\n // only while dark mode is actually active.\n const cssVars = useMemo(\n () =>\n buildCssVars(\n isDarkActive\n ? { ...mergedTheme.token, ...mergedTheme.darkToken }\n : mergedTheme.token,\n ),\n [mergedTheme.token, mergedTheme.darkToken, isDarkActive],\n );\n\n const hasCssVars = Object.keys(cssVars).length > 0;\n const hasDarkMode = mergedTheme.dark !== undefined;\n const needsWrapper =\n hasCssVars || hasDarkMode || !!className || !!style || !!direction;\n\n // Resolution order: an explicit `getContainer` prop on this Config wins;\n // otherwise, if this Config renders its own themed wrapper below, that's\n // the default (portaled content appended into it still inherits its CSS\n // custom properties and matches the `.dark` selector — `display:\n // contents` only removes the element from the layout box tree, not from\n // the DOM/cascade); otherwise defer to the parent Config's resolution,\n // so an inner Config that only sets e.g. `locale` doesn't shadow an\n // outer one's theme container.\n const resolvedGetContainer = useCallback((): HTMLElement | undefined => {\n if (getContainer) {\n return getContainer();\n }\n if (needsWrapper && wrapperEl) {\n return wrapperEl;\n }\n return parent.getContainer();\n }, [getContainer, needsWrapper, wrapperEl, parent]);\n\n const resolvedComponentSize = componentSize ?? parent.componentSize;\n const resolvedDirection = direction ?? parent.direction;\n\n const defaultPropsKey = JSON.stringify(defaultProps);\n const parentDefaultPropsKey = JSON.stringify(parent.defaultProps);\n\n const mergedDefaultProps = useMemo<DefaultProps | undefined>(\n () =>\n parent.defaultProps || defaultProps\n ? { ...parent.defaultProps, ...defaultProps }\n : undefined,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentDefaultPropsKey, defaultPropsKey],\n );\n\n const contextValue = useMemo(\n () => ({\n theme: mergedTheme,\n locale: mergedLocale,\n getContainer: resolvedGetContainer,\n componentSize: resolvedComponentSize,\n direction: resolvedDirection,\n defaultProps: mergedDefaultProps,\n isConfigured: true,\n }),\n [\n mergedTheme,\n mergedLocale,\n resolvedGetContainer,\n resolvedComponentSize,\n resolvedDirection,\n mergedDefaultProps,\n ],\n );\n\n useEffect(() => {\n if (!isRoot) {\n return;\n }\n return registerRootConfig(contextValue);\n }, [isRoot, contextValue]);\n\n const content = (\n <Context.Provider value={contextValue}>\n {needsWrapper ? (\n <div\n ref={setWrapperEl}\n dir={direction}\n className={cn(isDarkActive && 'dark', className)}\n style={{\n ...(hasCssVars ? cssVars : undefined),\n ...style,\n // Keeps this element out of the layout box tree — so it\n // doesn't intercept flex/grid child relationships or break\n // height chains like min-h-screen — while custom properties\n // and the `dark` class selector still cascade to children\n // normally (inheritance and box generation are separate\n // mechanisms in CSS). Note this means className/style\n // shouldn't be used here for anything that needs a real box\n // (padding, background, borders); Config's className/style are\n // meant for theming hooks (the `dark` class, arbitrary\n // selector hooks, custom properties), not layout — spread\n // after the caller's `style` so it can't be overridden into\n // something that reintroduces the layout-breaking wrapper this\n // was added to fix in the first place.\n display: 'contents',\n }}\n >\n {children}\n </div>\n ) : (\n children\n )}\n </Context.Provider>\n );\n\n // DirectionProvider is Radix's own mechanism (@radix-ui/react-direction)\n // for propagating `dir` to every primitive that calls its useDirection()\n // internally — Select, Menu (Dropdown/Menu), Accordion (Collapse),\n // RadioGroup, ScrollArea all pick up RTL automatically this way, no\n // per-component wiring needed. Only wraps when this Config's own\n // `direction` prop is set (not the merely-inherited resolved value) —\n // context already cascades on its own, so re-wrapping at every nested\n // Config that doesn't override direction would just be redundant.\n // Components with hardcoded LTR-only layout logic that Radix's Direction\n // context doesn't reach (Popover placement, Splitter, Sider, Drawer)\n // aren't covered by this and would need dedicated follow-up work.\n return direction ? (\n <DirectionProvider dir={direction}>{content}</DirectionProvider>\n ) : (\n content\n );\n};\n\nexport default Config;\nexport { useConfig, DEFAULT_LOCALE };\nexport type {\n Props,\n ComponentSize,\n DefaultProps,\n Locale,\n ThemeConfig,\n ThemeToken,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useConfig } from "./context.mjs";
|
|
3
|
+
import { useSyncExternalStore } from "react";
|
|
4
|
+
//#region src/providers/config/dark-mode.ts
|
|
5
|
+
const DARK_MEDIA_QUERY = "(prefers-color-scheme: dark)";
|
|
6
|
+
const subscribeToSystemColorScheme = (callback) => {
|
|
7
|
+
if (typeof window === "undefined") return () => {};
|
|
8
|
+
const mql = window.matchMedia(DARK_MEDIA_QUERY);
|
|
9
|
+
mql.addEventListener("change", callback);
|
|
10
|
+
return () => mql.removeEventListener("change", callback);
|
|
11
|
+
};
|
|
12
|
+
const getSystemPrefersDark = () => typeof window !== "undefined" && window.matchMedia(DARK_MEDIA_QUERY).matches;
|
|
13
|
+
const getServerSnapshot = () => false;
|
|
14
|
+
const useSystemPrefersDark = () => useSyncExternalStore(subscribeToSystemColorScheme, getSystemPrefersDark, getServerSnapshot);
|
|
15
|
+
/**
|
|
16
|
+
* Turns the three-valued `theme.dark` setting into the boolean that decides
|
|
17
|
+
* whether dark treatments actually apply. Kept as a pure function so `Config`
|
|
18
|
+
* can resolve the theme it is about to publish (its merged value isn't in
|
|
19
|
+
* context yet) while consumers resolve the one already in context, without the
|
|
20
|
+
* two drifting apart.
|
|
21
|
+
*/
|
|
22
|
+
const resolveDark = (dark, systemPrefersDark) => dark === "system" ? systemPrefersDark : dark === "dark";
|
|
23
|
+
/**
|
|
24
|
+
* Whether dark mode is active for the nearest `Config`, with `'system'`
|
|
25
|
+
* resolved against `prefers-color-scheme`.
|
|
26
|
+
*
|
|
27
|
+
* Internal to the package: components that render *CSS* can just use Tailwind's
|
|
28
|
+
* `dark:` variants against the `.dark` class `Config` puts on its wrapper. This
|
|
29
|
+
* exists for the ones that have to hand a light/dark choice to a third party in
|
|
30
|
+
* JS instead — `CodeEditor` picking a CodeMirror theme extension.
|
|
31
|
+
*/
|
|
32
|
+
const useIsDarkActive = () => {
|
|
33
|
+
const { theme } = useConfig();
|
|
34
|
+
return resolveDark(theme.dark, useSystemPrefersDark());
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { resolveDark, useIsDarkActive, useSystemPrefersDark };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=dark-mode.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dark-mode.mjs","names":[],"sources":["../../../src/providers/config/dark-mode.ts"],"sourcesContent":["'use client';\n\nimport { useSyncExternalStore } from 'react';\n\nimport { useConfig } from './context';\nimport type { ThemeConfig } from './types';\n\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)';\n\nconst subscribeToSystemColorScheme = (callback: () => void) => {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const mql = window.matchMedia(DARK_MEDIA_QUERY);\n mql.addEventListener('change', callback);\n return () => mql.removeEventListener('change', callback);\n};\n\nconst getSystemPrefersDark = () =>\n typeof window !== 'undefined' && window.matchMedia(DARK_MEDIA_QUERY).matches;\n\n// No `window` during SSR, so there's no way to know the visitor's actual\n// preference before hydration — assume light (the conservative default)\n// and let useSyncExternalStore correct it client-side once matchMedia is\n// available, same flash-of-incorrect-guess tradeoff already accepted for\n// Sider's breakpoint prop elsewhere in this library.\nconst getServerSnapshot = () => false;\n\nexport const useSystemPrefersDark = () =>\n useSyncExternalStore(\n subscribeToSystemColorScheme,\n getSystemPrefersDark,\n getServerSnapshot,\n );\n\n/**\n * Turns the three-valued `theme.dark` setting into the boolean that decides\n * whether dark treatments actually apply. Kept as a pure function so `Config`\n * can resolve the theme it is about to publish (its merged value isn't in\n * context yet) while consumers resolve the one already in context, without the\n * two drifting apart.\n */\nexport const resolveDark = (\n dark: ThemeConfig['dark'],\n systemPrefersDark: boolean,\n) => (dark === 'system' ? systemPrefersDark : dark === 'dark');\n\n/**\n * Whether dark mode is active for the nearest `Config`, with `'system'`\n * resolved against `prefers-color-scheme`.\n *\n * Internal to the package: components that render *CSS* can just use Tailwind's\n * `dark:` variants against the `.dark` class `Config` puts on its wrapper. This\n * exists for the ones that have to hand a light/dark choice to a third party in\n * JS instead — `CodeEditor` picking a CodeMirror theme extension.\n */\nexport const useIsDarkActive = () => {\n const { theme } = useConfig();\n\n return resolveDark(theme.dark, useSystemPrefersDark());\n};\n"],"mappings":";;;;AAOA,MAAM,mBAAmB;AAEzB,MAAM,gCAAgC,aAAyB;CAC7D,IAAI,OAAO,WAAW,aACpB,aAAa,CAAC;CAGhB,MAAM,MAAM,OAAO,WAAW,gBAAgB;CAC9C,IAAI,iBAAiB,UAAU,QAAQ;CACvC,aAAa,IAAI,oBAAoB,UAAU,QAAQ;AACzD;AAEA,MAAM,6BACJ,OAAO,WAAW,eAAe,OAAO,WAAW,gBAAgB,CAAC,CAAC;AAOvE,MAAM,0BAA0B;AAEhC,MAAa,6BACX,qBACE,8BACA,sBACA,iBACF;;;;;;;;AASF,MAAa,eACX,MACA,sBACI,SAAS,WAAW,oBAAoB,SAAS;;;;;;;;;;AAWvD,MAAa,wBAAwB;CACnC,MAAM,EAAE,UAAU,UAAU;CAE5B,OAAO,YAAY,MAAM,MAAM,qBAAqB,CAAC;AACvD"}
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
//#region src/providers/config/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Theme overrides applied as CSS custom properties on `Config`'s wrapper
|
|
4
|
+
* element, inherited by everything inside it.
|
|
5
|
+
*
|
|
6
|
+
* Every token here is verified to actually reach a component. That is worth
|
|
7
|
+
* stating because it did not use to be true: 19 of the previous 40 tokens were
|
|
8
|
+
* inert (#343). Three groups were dropped in 8.0 —
|
|
9
|
+
*
|
|
10
|
+
* - `btnBackground`/`btnBackgroundHover`/`btnBackgroundActive`/`btnBorder`/
|
|
11
|
+
* `btnForeground` — `globals.css` declares `--btn-*` on the button element
|
|
12
|
+
* itself (keyed off `data-color`), and an element's own declaration always
|
|
13
|
+
* beats an inherited one, so a wrapper value could never win. Re-theming a
|
|
14
|
+
* button is done through `colorPrimary`/`colorDestructive` for the semantic
|
|
15
|
+
* colours, or by overriding `--preset-color` in CSS for the preset hues.
|
|
16
|
+
* - `sidebar*` and `chart*` — no component in the library reads them, and the
|
|
17
|
+
* matching utilities (`bg-sidebar`, `bg-chart-1`) are never generated into
|
|
18
|
+
* the published stylesheet, so nothing consumed them. The underlying
|
|
19
|
+
* `--sidebar-*`/`--chart-*` custom properties are still declared in
|
|
20
|
+
* `globals.css` and remain overridable in plain CSS; only the inert token
|
|
21
|
+
* API is gone. They should come back alongside an actual Sidebar/Chart
|
|
22
|
+
* component.
|
|
23
|
+
*
|
|
24
|
+
* `fontSans`/`fontMono` were inert for a different reason and were fixed
|
|
25
|
+
* rather than removed — see below.
|
|
26
|
+
*/
|
|
2
27
|
interface ThemeToken {
|
|
3
28
|
colorPrimary?: string;
|
|
4
29
|
colorPrimaryForeground?: string;
|
|
@@ -19,24 +44,6 @@ interface ThemeToken {
|
|
|
19
44
|
colorInput?: string;
|
|
20
45
|
colorRing?: string;
|
|
21
46
|
borderRadius?: string;
|
|
22
|
-
btnBackground?: string;
|
|
23
|
-
btnBackgroundHover?: string;
|
|
24
|
-
btnBackgroundActive?: string;
|
|
25
|
-
btnBorder?: string;
|
|
26
|
-
btnForeground?: string;
|
|
27
|
-
sidebar?: string;
|
|
28
|
-
sidebarForeground?: string;
|
|
29
|
-
sidebarPrimary?: string;
|
|
30
|
-
sidebarPrimaryForeground?: string;
|
|
31
|
-
sidebarAccent?: string;
|
|
32
|
-
sidebarAccentForeground?: string;
|
|
33
|
-
sidebarBorder?: string;
|
|
34
|
-
sidebarRing?: string;
|
|
35
|
-
chart1?: string;
|
|
36
|
-
chart2?: string;
|
|
37
|
-
chart3?: string;
|
|
38
|
-
chart4?: string;
|
|
39
|
-
chart5?: string;
|
|
40
47
|
fontSans?: string;
|
|
41
48
|
fontMono?: string;
|
|
42
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/providers/config/types.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/providers/config/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;UAyBiB;EAEf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EASA;EAMA;EACA;;UAGe;EACf,QAAQ;EAKR,YAAY;EASZ;;UAQe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAMU;KAYA,eAAe,eAAe;UAEzB;EACf,OAAO;EACP,QAAQ;EACR;EAUA,oBAAoB;EACpB,gBAAgB;EAChB,eAAe;EAKf"}
|
package/dist/style.css
CHANGED
|
@@ -2,13 +2,28 @@
|
|
|
2
2
|
@layer properties;
|
|
3
3
|
@layer theme {
|
|
4
4
|
:root, :host {
|
|
5
|
-
--font-sans: var(--font-geist-sans);
|
|
6
|
-
--font-mono: var(--font-geist-mono);
|
|
5
|
+
--font-sans: var(--ui-font-sans, var(--font-geist-sans));
|
|
6
|
+
--font-mono: var(--ui-font-mono, var(--font-geist-mono));
|
|
7
7
|
--color-red-400: oklch(70.4% .191 22.216);
|
|
8
|
+
--color-red-500: oklch(63.7% .237 25.331);
|
|
9
|
+
--color-orange-500: oklch(70.5% .213 47.604);
|
|
10
|
+
--color-orange-600: oklch(64.6% .222 41.116);
|
|
11
|
+
--color-amber-500: oklch(76.9% .188 70.08);
|
|
8
12
|
--color-yellow-400: oklch(85.2% .199 91.936);
|
|
13
|
+
--color-yellow-500: oklch(79.5% .184 86.047);
|
|
14
|
+
--color-yellow-600: oklch(68.1% .162 75.834);
|
|
15
|
+
--color-lime-500: oklch(76.8% .233 130.85);
|
|
9
16
|
--color-green-400: oklch(79.2% .209 151.711);
|
|
17
|
+
--color-green-500: oklch(72.3% .219 149.579);
|
|
18
|
+
--color-green-600: oklch(62.7% .194 149.214);
|
|
19
|
+
--color-cyan-500: oklch(71.5% .143 215.221);
|
|
10
20
|
--color-blue-400: oklch(70.7% .165 254.624);
|
|
21
|
+
--color-blue-500: oklch(62.3% .214 259.815);
|
|
11
22
|
--color-blue-600: oklch(54.6% .245 262.881);
|
|
23
|
+
--color-indigo-500: oklch(58.5% .233 277.117);
|
|
24
|
+
--color-purple-500: oklch(62.7% .265 303.9);
|
|
25
|
+
--color-fuchsia-500: oklch(66.7% .295 322.15);
|
|
26
|
+
--color-pink-500: oklch(65.6% .241 354.308);
|
|
12
27
|
--color-gray-100: oklch(96.7% .003 264.542);
|
|
13
28
|
--color-gray-200: oklch(92.8% .006 264.531);
|
|
14
29
|
--color-gray-300: oklch(87.2% .01 258.338);
|
|
@@ -88,7 +103,56 @@
|
|
|
88
103
|
}
|
|
89
104
|
}
|
|
90
105
|
@layer components {
|
|
106
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="blue"] {
|
|
107
|
+
--preset-color: var(--color-blue-500);
|
|
108
|
+
}
|
|
109
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="purple"] {
|
|
110
|
+
--preset-color: var(--color-purple-500);
|
|
111
|
+
}
|
|
112
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="cyan"] {
|
|
113
|
+
--preset-color: var(--color-cyan-500);
|
|
114
|
+
}
|
|
115
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="green"] {
|
|
116
|
+
--preset-color: var(--color-green-500);
|
|
117
|
+
}
|
|
118
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="fuchsia"] {
|
|
119
|
+
--preset-color: var(--color-fuchsia-500);
|
|
120
|
+
}
|
|
121
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="pink"] {
|
|
122
|
+
--preset-color: var(--color-pink-500);
|
|
123
|
+
}
|
|
124
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="red"] {
|
|
125
|
+
--preset-color: var(--color-red-500);
|
|
126
|
+
}
|
|
127
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="orange"] {
|
|
128
|
+
--preset-color: var(--color-orange-500);
|
|
129
|
+
}
|
|
130
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="yellow"] {
|
|
131
|
+
--preset-color: var(--color-yellow-500);
|
|
132
|
+
}
|
|
133
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="indigo"] {
|
|
134
|
+
--preset-color: var(--color-indigo-500);
|
|
135
|
+
}
|
|
136
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="lime"] {
|
|
137
|
+
--preset-color: var(--color-lime-500);
|
|
138
|
+
}
|
|
139
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="amber"] {
|
|
140
|
+
--preset-color: var(--color-amber-500);
|
|
141
|
+
}
|
|
142
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="magenta"] {
|
|
143
|
+
--preset-color: var(--color-fuchsia-500);
|
|
144
|
+
}
|
|
145
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="geekblue"] {
|
|
146
|
+
--preset-color: var(--color-indigo-500);
|
|
147
|
+
}
|
|
148
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="gold"] {
|
|
149
|
+
--preset-color: var(--color-amber-500);
|
|
150
|
+
}
|
|
151
|
+
:is([data-slot="button"], [data-slot="badge"])[data-color="volcano"] {
|
|
152
|
+
--preset-color: var(--color-orange-600);
|
|
153
|
+
}
|
|
91
154
|
[data-slot="button"][data-color] {
|
|
155
|
+
--btn-bg: var(--preset-color);
|
|
92
156
|
--btn-fg: white;
|
|
93
157
|
--btn-border: var(--btn-bg);
|
|
94
158
|
--btn-bg-hover: var(--btn-bg);
|
|
@@ -100,7 +164,7 @@
|
|
|
100
164
|
--btn-bg-active: color-mix(in oklch, var(--btn-bg), black 22%);
|
|
101
165
|
}
|
|
102
166
|
}
|
|
103
|
-
[data-slot="button"][data-color="yellow"], [data-slot="button"][data-color="lime"], [data-slot="button"][data-color="gold"] {
|
|
167
|
+
[data-slot="button"][data-color="yellow"], [data-slot="button"][data-color="lime"], [data-slot="button"][data-color="amber"], [data-slot="button"][data-color="gold"] {
|
|
104
168
|
--btn-fg: black;
|
|
105
169
|
}
|
|
106
170
|
[data-slot="button"][data-color="default"] {
|
|
@@ -114,46 +178,8 @@
|
|
|
114
178
|
[data-slot="button"][data-color="danger"] {
|
|
115
179
|
--btn-bg: var(--destructive);
|
|
116
180
|
}
|
|
117
|
-
[data-slot="button"][data-color="blue"] {
|
|
118
|
-
--btn-bg: #3b82f6;
|
|
119
|
-
}
|
|
120
|
-
[data-slot="button"][data-color="purple"] {
|
|
121
|
-
--btn-bg: #a855f7;
|
|
122
|
-
}
|
|
123
|
-
[data-slot="button"][data-color="cyan"] {
|
|
124
|
-
--btn-bg: #06b6d4;
|
|
125
|
-
}
|
|
126
|
-
[data-slot="button"][data-color="green"] {
|
|
127
|
-
--btn-bg: #22c55e;
|
|
128
|
-
}
|
|
129
|
-
[data-slot="button"][data-color="magenta"] {
|
|
130
|
-
--btn-bg: #d946ef;
|
|
131
|
-
}
|
|
132
|
-
[data-slot="button"][data-color="pink"] {
|
|
133
|
-
--btn-bg: #ec4899;
|
|
134
|
-
}
|
|
135
|
-
[data-slot="button"][data-color="red"] {
|
|
136
|
-
--btn-bg: #ef4444;
|
|
137
|
-
}
|
|
138
|
-
[data-slot="button"][data-color="orange"] {
|
|
139
|
-
--btn-bg: #f97316;
|
|
140
|
-
}
|
|
141
|
-
[data-slot="button"][data-color="yellow"] {
|
|
142
|
-
--btn-bg: #eab308;
|
|
143
|
-
}
|
|
144
|
-
[data-slot="button"][data-color="volcano"] {
|
|
145
|
-
--btn-bg: #ea580c;
|
|
146
|
-
}
|
|
147
|
-
[data-slot="button"][data-color="geekblue"] {
|
|
148
|
-
--btn-bg: #6366f1;
|
|
149
|
-
}
|
|
150
|
-
[data-slot="button"][data-color="lime"] {
|
|
151
|
-
--btn-bg: #84cc16;
|
|
152
|
-
}
|
|
153
|
-
[data-slot="button"][data-color="gold"] {
|
|
154
|
-
--btn-bg: #f59e0b;
|
|
155
|
-
}
|
|
156
181
|
[data-slot="badge"][data-color] {
|
|
182
|
+
--tag-bg: var(--preset-color);
|
|
157
183
|
--tag-fg: var(--tag-bg);
|
|
158
184
|
--tag-tint: var(--tag-bg);
|
|
159
185
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -175,57 +201,18 @@
|
|
|
175
201
|
--tag-bg: var(--destructive);
|
|
176
202
|
}
|
|
177
203
|
[data-slot="badge"][data-color="success"] {
|
|
178
|
-
--tag-bg:
|
|
179
|
-
--tag-fg:
|
|
204
|
+
--tag-bg: var(--color-green-500);
|
|
205
|
+
--tag-fg: var(--color-green-600);
|
|
180
206
|
}
|
|
181
207
|
[data-slot="badge"][data-color="warning"] {
|
|
182
|
-
--tag-bg:
|
|
183
|
-
--tag-fg:
|
|
208
|
+
--tag-bg: var(--color-yellow-500);
|
|
209
|
+
--tag-fg: var(--color-yellow-600);
|
|
184
210
|
}
|
|
185
211
|
:is(.dark, [data-theme="dark"]) [data-slot="badge"][data-color="success"] {
|
|
186
|
-
--tag-fg:
|
|
212
|
+
--tag-fg: var(--color-green-400);
|
|
187
213
|
}
|
|
188
214
|
:is(.dark, [data-theme="dark"]) [data-slot="badge"][data-color="warning"] {
|
|
189
|
-
--tag-fg:
|
|
190
|
-
}
|
|
191
|
-
[data-slot="badge"][data-color="blue"] {
|
|
192
|
-
--tag-bg: #3b82f6;
|
|
193
|
-
}
|
|
194
|
-
[data-slot="badge"][data-color="purple"] {
|
|
195
|
-
--tag-bg: #a855f7;
|
|
196
|
-
}
|
|
197
|
-
[data-slot="badge"][data-color="cyan"] {
|
|
198
|
-
--tag-bg: #06b6d4;
|
|
199
|
-
}
|
|
200
|
-
[data-slot="badge"][data-color="green"] {
|
|
201
|
-
--tag-bg: #22c55e;
|
|
202
|
-
}
|
|
203
|
-
[data-slot="badge"][data-color="magenta"] {
|
|
204
|
-
--tag-bg: #d946ef;
|
|
205
|
-
}
|
|
206
|
-
[data-slot="badge"][data-color="pink"] {
|
|
207
|
-
--tag-bg: #ec4899;
|
|
208
|
-
}
|
|
209
|
-
[data-slot="badge"][data-color="red"] {
|
|
210
|
-
--tag-bg: #ef4444;
|
|
211
|
-
}
|
|
212
|
-
[data-slot="badge"][data-color="orange"] {
|
|
213
|
-
--tag-bg: #f97316;
|
|
214
|
-
}
|
|
215
|
-
[data-slot="badge"][data-color="yellow"] {
|
|
216
|
-
--tag-bg: #eab308;
|
|
217
|
-
}
|
|
218
|
-
[data-slot="badge"][data-color="volcano"] {
|
|
219
|
-
--tag-bg: #ea580c;
|
|
220
|
-
}
|
|
221
|
-
[data-slot="badge"][data-color="geekblue"] {
|
|
222
|
-
--tag-bg: #6366f1;
|
|
223
|
-
}
|
|
224
|
-
[data-slot="badge"][data-color="lime"] {
|
|
225
|
-
--tag-bg: #84cc16;
|
|
226
|
-
}
|
|
227
|
-
[data-slot="badge"][data-color="gold"] {
|
|
228
|
-
--tag-bg: #f59e0b;
|
|
215
|
+
--tag-fg: var(--color-yellow-400);
|
|
229
216
|
}
|
|
230
217
|
[data-slot="col"] {
|
|
231
218
|
flex-basis: calc(var(--col-span-xs) / 24 * 100%);
|
|
@@ -380,6 +367,9 @@
|
|
|
380
367
|
.z-50 {
|
|
381
368
|
z-index: 50;
|
|
382
369
|
}
|
|
370
|
+
.z-1000 {
|
|
371
|
+
z-index: 1000;
|
|
372
|
+
}
|
|
383
373
|
.z-10000 {
|
|
384
374
|
z-index: 10000;
|
|
385
375
|
}
|
|
@@ -1192,6 +1182,9 @@
|
|
|
1192
1182
|
.bg-card {
|
|
1193
1183
|
background-color: var(--card);
|
|
1194
1184
|
}
|
|
1185
|
+
.bg-chart-1 {
|
|
1186
|
+
background-color: var(--chart-1);
|
|
1187
|
+
}
|
|
1195
1188
|
.bg-destructive {
|
|
1196
1189
|
background-color: var(--destructive);
|
|
1197
1190
|
}
|
|
@@ -1219,6 +1212,9 @@
|
|
|
1219
1212
|
.bg-secondary {
|
|
1220
1213
|
background-color: var(--secondary);
|
|
1221
1214
|
}
|
|
1215
|
+
.bg-sidebar {
|
|
1216
|
+
background-color: var(--sidebar);
|
|
1217
|
+
}
|
|
1222
1218
|
.bg-transparent {
|
|
1223
1219
|
background-color: transparent;
|
|
1224
1220
|
}
|
|
@@ -1346,7 +1342,7 @@
|
|
|
1346
1342
|
text-align: start;
|
|
1347
1343
|
}
|
|
1348
1344
|
.font-mono {
|
|
1349
|
-
font-family: var(--font-geist-mono);
|
|
1345
|
+
font-family: var(--ui-font-mono, var(--font-geist-mono));
|
|
1350
1346
|
}
|
|
1351
1347
|
.text-2xl {
|
|
1352
1348
|
font-size: var(--text-2xl);
|
|
@@ -1567,6 +1563,10 @@
|
|
|
1567
1563
|
--tw-blur: blur(8px);
|
|
1568
1564
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1569
1565
|
}
|
|
1566
|
+
.invert {
|
|
1567
|
+
--tw-invert: invert(100%);
|
|
1568
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1569
|
+
}
|
|
1570
1570
|
.filter {
|
|
1571
1571
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1572
1572
|
}
|
|
@@ -2722,7 +2722,7 @@
|
|
|
2722
2722
|
padding-block: calc(var(--spacing) * 0.5);
|
|
2723
2723
|
}
|
|
2724
2724
|
.\[\&_\.tiptap_code\]\:font-mono .tiptap code {
|
|
2725
|
-
font-family: var(--font-geist-mono);
|
|
2725
|
+
font-family: var(--ui-font-mono, var(--font-geist-mono));
|
|
2726
2726
|
}
|
|
2727
2727
|
.\[\&_\.tiptap_code\]\:text-\[0\.85em\] .tiptap code {
|
|
2728
2728
|
font-size: 0.85em;
|
|
@@ -2833,7 +2833,7 @@
|
|
|
2833
2833
|
padding: calc(var(--spacing) * 3);
|
|
2834
2834
|
}
|
|
2835
2835
|
.\[\&_\.tiptap_pre\]\:font-mono .tiptap pre {
|
|
2836
|
-
font-family: var(--font-geist-mono);
|
|
2836
|
+
font-family: var(--ui-font-mono, var(--font-geist-mono));
|
|
2837
2837
|
}
|
|
2838
2838
|
.\[\&_\.tiptap_pre\]\:text-sm .tiptap pre {
|
|
2839
2839
|
font-size: var(--text-sm);
|
package/dist/utils.d.mts
CHANGED
|
@@ -2,6 +2,18 @@ import * as React$1 from "react";
|
|
|
2
2
|
import { ClassValue } from "clsx";
|
|
3
3
|
//#region src/lib/utils/index.d.ts
|
|
4
4
|
declare const cn: (...inputs: ClassValue[]) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Renders a slot value, applying `wrapper` only to values that aren't already
|
|
7
|
+
* a React element. Passing an element opts out of the wrapper entirely.
|
|
8
|
+
*
|
|
9
|
+
* **Only use this for content slots where that opt-out is the point** — a
|
|
10
|
+
* `title` the caller may want to supply as their own heading, so we don't end
|
|
11
|
+
* up nesting `<h6><h3>`. Do *not* use it for a wrapper that carries layout the
|
|
12
|
+
* component owns (padding, `shrink-0`, a footer bar): the common case is an
|
|
13
|
+
* element, so the wrapper would be skipped exactly when it's needed, and any
|
|
14
|
+
* `classNames.*` threaded through it would silently do nothing. Write those as
|
|
15
|
+
* a plain `{value != null && <Wrapper>{value}</Wrapper>}`.
|
|
16
|
+
*/
|
|
5
17
|
declare const renderConditional: <T extends React$1.ReactNode>(value: T, wrapper?: (value: NonNullable<T>) => React$1.ReactNode) => React$1.ReactNode;
|
|
6
18
|
//#endregion
|
|
7
19
|
export { cn, renderConditional };
|
package/dist/utils.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.mts","names":[],"sources":["../src/lib/utils/index.ts"],"mappings":";;;cAKa,QAAS,QAAQ
|
|
1
|
+
{"version":3,"file":"utils.d.mts","names":[],"sources":["../src/lib/utils/index.ts"],"mappings":";;;cAKa,QAAS,QAAQ;;;;;;;;;;;;;cAgBjB,oBAAqB,UAAU,QAAM,WAChD,OAAO,GACP,WAAW,OAAO,YAAY,OAAO,QAAM,cAC1C,QAAM"}
|
package/dist/utils.mjs
CHANGED
|
@@ -5,6 +5,18 @@ import { twMerge } from "tailwind-merge";
|
|
|
5
5
|
const cn = (...inputs) => {
|
|
6
6
|
return twMerge(clsx(inputs));
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Renders a slot value, applying `wrapper` only to values that aren't already
|
|
10
|
+
* a React element. Passing an element opts out of the wrapper entirely.
|
|
11
|
+
*
|
|
12
|
+
* **Only use this for content slots where that opt-out is the point** — a
|
|
13
|
+
* `title` the caller may want to supply as their own heading, so we don't end
|
|
14
|
+
* up nesting `<h6><h3>`. Do *not* use it for a wrapper that carries layout the
|
|
15
|
+
* component owns (padding, `shrink-0`, a footer bar): the common case is an
|
|
16
|
+
* element, so the wrapper would be skipped exactly when it's needed, and any
|
|
17
|
+
* `classNames.*` threaded through it would silently do nothing. Write those as
|
|
18
|
+
* a plain `{value != null && <Wrapper>{value}</Wrapper>}`.
|
|
19
|
+
*/
|
|
8
20
|
const renderConditional = (value, wrapper) => {
|
|
9
21
|
if (value === null || value === void 0) return null;
|
|
10
22
|
if (React$1.isValidElement(value)) return value;
|
package/dist/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","names":["React"],"sources":["../src/lib/utils/index.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport const cn = (...inputs: ClassValue[]) => {\n return twMerge(clsx(inputs));\n};\n\nexport const renderConditional = <T extends React.ReactNode>(\n value: T,\n wrapper?: (value: NonNullable<T>) => React.ReactNode,\n): React.ReactNode => {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (React.isValidElement(value)) {\n return value;\n }\n\n return wrapper ? wrapper(value as NonNullable<T>) : value;\n};\n"],"mappings":";;;;AAKA,MAAa,MAAM,GAAG,WAAyB;CAC7C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":["React"],"sources":["../src/lib/utils/index.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport const cn = (...inputs: ClassValue[]) => {\n return twMerge(clsx(inputs));\n};\n\n/**\n * Renders a slot value, applying `wrapper` only to values that aren't already\n * a React element. Passing an element opts out of the wrapper entirely.\n *\n * **Only use this for content slots where that opt-out is the point** — a\n * `title` the caller may want to supply as their own heading, so we don't end\n * up nesting `<h6><h3>`. Do *not* use it for a wrapper that carries layout the\n * component owns (padding, `shrink-0`, a footer bar): the common case is an\n * element, so the wrapper would be skipped exactly when it's needed, and any\n * `classNames.*` threaded through it would silently do nothing. Write those as\n * a plain `{value != null && <Wrapper>{value}</Wrapper>}`.\n */\nexport const renderConditional = <T extends React.ReactNode>(\n value: T,\n wrapper?: (value: NonNullable<T>) => React.ReactNode,\n): React.ReactNode => {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (React.isValidElement(value)) {\n return value;\n }\n\n return wrapper ? wrapper(value as NonNullable<T>) : value;\n};\n"],"mappings":";;;;AAKA,MAAa,MAAM,GAAG,WAAyB;CAC7C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;;;;;;;;;;;AAcA,MAAa,qBACX,OACA,YACoB;CACpB,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,OAAO;CAGT,IAAIA,QAAM,eAAe,KAAK,GAC5B,OAAO;CAGT,OAAO,UAAU,QAAQ,KAAuB,IAAI;AACtD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbpark/ui-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Modern React UI component library built with TypeScript, Tailwind CSS, and Radix UI. Featuring atoms, molecules, organisms and layout templates for building beautiful interfaces.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -54,6 +54,11 @@
|
|
|
54
54
|
"import": "./dist/Button.mjs",
|
|
55
55
|
"default": "./dist/Button.mjs"
|
|
56
56
|
},
|
|
57
|
+
"./CodeEditor": {
|
|
58
|
+
"types": "./dist/CodeEditor.d.mts",
|
|
59
|
+
"import": "./dist/CodeEditor.mjs",
|
|
60
|
+
"default": "./dist/CodeEditor.mjs"
|
|
61
|
+
},
|
|
57
62
|
"./Tag": {
|
|
58
63
|
"types": "./dist/Tag.d.mts",
|
|
59
64
|
"import": "./dist/Tag.mjs",
|
|
@@ -113,6 +118,8 @@
|
|
|
113
118
|
"postpublish": "node scripts/restore-package.mjs"
|
|
114
119
|
},
|
|
115
120
|
"devDependencies": {
|
|
121
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
122
|
+
"@codemirror/merge": "^6.12.2",
|
|
116
123
|
"@repo/eslint-config": "workspace:*",
|
|
117
124
|
"@repo/typescript-config": "workspace:*",
|
|
118
125
|
"@tailwindcss/postcss": "^4.3.3",
|
|
@@ -120,6 +127,9 @@
|
|
|
120
127
|
"@types/node": "^26.2.0",
|
|
121
128
|
"@types/react": "19.2.18",
|
|
122
129
|
"@types/react-dom": "19.2.4",
|
|
130
|
+
"@uiw/codemirror-theme-vscode": "^4.25.11",
|
|
131
|
+
"@uiw/react-codemirror": "^4.25.11",
|
|
132
|
+
"codemirror": "^6.0.0",
|
|
123
133
|
"eslint": "^9.39.5",
|
|
124
134
|
"postcss": "^8.5.26",
|
|
125
135
|
"rollup-plugin-postcss": "^4.0.2",
|
|
@@ -162,7 +172,29 @@
|
|
|
162
172
|
"vaul": "^1.1.2"
|
|
163
173
|
},
|
|
164
174
|
"peerDependencies": {
|
|
175
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
176
|
+
"@codemirror/merge": "^6.12.2",
|
|
177
|
+
"@uiw/codemirror-theme-vscode": "^4.25.11",
|
|
178
|
+
"@uiw/react-codemirror": "^4.25.11",
|
|
179
|
+
"codemirror": "^6.0.0",
|
|
165
180
|
"react": "^19.0.0",
|
|
166
181
|
"react-dom": "^19.0.0"
|
|
182
|
+
},
|
|
183
|
+
"peerDependenciesMeta": {
|
|
184
|
+
"@codemirror/lang-javascript": {
|
|
185
|
+
"optional": true
|
|
186
|
+
},
|
|
187
|
+
"@codemirror/merge": {
|
|
188
|
+
"optional": true
|
|
189
|
+
},
|
|
190
|
+
"@uiw/codemirror-theme-vscode": {
|
|
191
|
+
"optional": true
|
|
192
|
+
},
|
|
193
|
+
"@uiw/react-codemirror": {
|
|
194
|
+
"optional": true
|
|
195
|
+
},
|
|
196
|
+
"codemirror": {
|
|
197
|
+
"optional": true
|
|
198
|
+
}
|
|
167
199
|
}
|
|
168
200
|
}
|