@splenddev/kreativ-core 0.1.14 → 0.1.16
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/chunk-QP6G3F24.js +48 -0
- package/dist/chunk-QP6G3F24.js.map +1 -0
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5CYSF7C3.js +0 -24
- package/dist/chunk-5CYSF7C3.js.map +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createContext, useContext, useRef, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/provider/ThemeContext.tsx
|
|
4
|
+
var ThemeContext = createContext(null);
|
|
5
|
+
|
|
6
|
+
// src/utils/assertProviderContext.ts
|
|
7
|
+
function assertProviderContext(ctx, hookName, providerName, packageName = "kreativ-core") {
|
|
8
|
+
if (ctx == null) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`[${packageName}] ${hookName}() must be used within a <${providerName}>. Did you forget to wrap your app with <${providerName}>? import { ${providerName} } from '${packageName}';`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/provider/useTheme.ts
|
|
16
|
+
function useTheme() {
|
|
17
|
+
const ctx = useContext(ThemeContext);
|
|
18
|
+
assertProviderContext(ctx, "useTheme", "ThemeProvider");
|
|
19
|
+
return ctx;
|
|
20
|
+
}
|
|
21
|
+
var VALID_MODES = ["light", "dark", "system"];
|
|
22
|
+
function useThemeModePersistence(storageKey = "kui-theme-mode") {
|
|
23
|
+
const { mode, setMode } = useTheme();
|
|
24
|
+
const hasHydrated = useRef(false);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
try {
|
|
27
|
+
const stored = window.localStorage.getItem(storageKey);
|
|
28
|
+
if (stored && VALID_MODES.includes(stored)) {
|
|
29
|
+
setMode(stored);
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
} finally {
|
|
33
|
+
hasHydrated.current = true;
|
|
34
|
+
}
|
|
35
|
+
}, [storageKey]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!hasHydrated.current) return;
|
|
38
|
+
try {
|
|
39
|
+
useThemeModePersistence;
|
|
40
|
+
window.localStorage.setItem(storageKey, mode);
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
}, [storageKey, mode]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { ThemeContext, useTheme, useThemeModePersistence };
|
|
47
|
+
//# sourceMappingURL=chunk-QP6G3F24.js.map
|
|
48
|
+
//# sourceMappingURL=chunk-QP6G3F24.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider/ThemeContext.tsx","../src/utils/assertProviderContext.ts","../src/provider/useTheme.ts","../src/hooks/useThemeModePersistence.ts"],"names":[],"mappings":";;;AAcO,IAAM,YAAA,GAAe,cAAwC,IAAI;;;ACRjE,SAAS,qBAAA,CACd,GAAA,EACA,QAAA,EACA,YAAA,EACA,cAAc,cAAA,EACI;AAClB,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,CAAA,EAAI,WAAW,CAAA,EAAA,EAAK,QAAQ,CAAA,0BAAA,EAA6B,YAAY,CAAA,yCAAA,EAC1B,YAAY,CAAA,YAAA,EACzC,YAAY,CAAA,SAAA,EAAY,WAAW,CAAA,EAAA;AAAA,KACnD;AAAA,EACF;AACF;;;ACbO,SAAS,QAAA,GAAW;AACzB,EAAA,MAAM,GAAA,GAAM,WAAW,YAAY,CAAA;AACnC,EAAA,qBAAA,CAAsB,GAAA,EAAK,YAAY,eAAe,CAAA;AACtD,EAAA,OAAO,GAAA;AACT;ACNA,IAAM,WAAA,GAA2B,CAAC,OAAA,EAAS,MAAA,EAAQ,QAAQ,CAAA;AAEpD,SAAS,uBAAA,CAAwB,aAAa,gBAAA,EAAwB;AAC3E,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,QAAA,EAAS;AACnC,EAAA,MAAM,WAAA,GAAc,OAAO,KAAK,CAAA;AAEhC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA;AACrD,MAAA,IAAI,MAAA,IAAW,WAAA,CAAyB,QAAA,CAAS,MAAM,CAAA,EAAG;AACxD,QAAA,OAAA,CAAQ,MAAmB,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AAAA,IACxB;AAAA,EAEF,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,YAAY,OAAA,EAAS;AAE1B,IAAA,IAAI;AACF,MAAA,uBAAA;AACA,MAAA,MAAA,CAAO,YAAA,CAAa,OAAA,CAAQ,UAAA,EAAY,IAAI,CAAA;AAAA,IAC9C,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA,EAAG,CAAC,UAAA,EAAY,IAAI,CAAC,CAAA;AACvB","file":"chunk-QP6G3F24.js","sourcesContent":["\"use client\";\r\n\r\nimport { createContext } from \"react\";\r\nimport type { ColorMode, Theme, ResolvedTokens } from \"@/types/theme\";\r\n\r\nexport interface ThemeContextValue {\r\n theme: Theme;\r\n mode: ColorMode;\r\n resolvedMode: \"light\" | \"dark\";\r\n setMode: (mode: ColorMode) => void;\r\n fallbackSize: string;\r\n tokens: ResolvedTokens;\r\n}\r\n\r\nexport const ThemeContext = createContext<ThemeContextValue | null>(null);\r\n","\"use client\";\r\n\r\n/**\r\n * Throws a standardized \"used outside provider\" error.\r\n * Shared across all kreativ-core hooks so the message stays consistent.\r\n */\r\nexport function assertProviderContext<T>(\r\n ctx: T | null | undefined,\r\n hookName: string,\r\n providerName: string,\r\n packageName = \"kreativ-core\",\r\n): asserts ctx is T {\r\n if (ctx == null) {\r\n throw new Error(\r\n `[${packageName}] ${hookName}() must be used within a <${providerName}>. ` +\r\n `Did you forget to wrap your app with <${providerName}>? ` +\r\n `import { ${providerName} } from '${packageName}';`,\r\n );\r\n }\r\n}\r\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { ThemeContext } from \"@/provider/ThemeContext\";\nimport { assertProviderContext } from \"@/utils/assertProviderContext\";\n\nexport function useTheme() {\n const ctx = useContext(ThemeContext);\n assertProviderContext(ctx, \"useTheme\", \"ThemeProvider\");\n return ctx;\n}\n","import { useEffect, useRef } from \"react\";\r\nimport type { ColorMode } from \"../types\";\r\nimport { useTheme } from \"@/provider\";\r\n\r\nconst VALID_MODES: ColorMode[] = [\"light\", \"dark\", \"system\"];\r\n\r\nexport function useThemeModePersistence(storageKey = \"kui-theme-mode\"): void {\r\n const { mode, setMode } = useTheme();\r\n const hasHydrated = useRef(false);\r\n\r\n useEffect(() => {\r\n try {\r\n const stored = window.localStorage.getItem(storageKey);\r\n if (stored && (VALID_MODES as string[]).includes(stored)) {\r\n setMode(stored as ColorMode);\r\n }\r\n } catch {\r\n // localStorage unavailable (SSR, privacy mode, etc.) — no-op\r\n } finally {\r\n hasHydrated.current = true;\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [storageKey]);\r\n\r\n useEffect(() => {\r\n if (!hasHydrated.current) return;\r\n\r\n try {\r\n useThemeModePersistence;\r\n window.localStorage.setItem(storageKey, mode);\r\n } catch {\r\n // no-op\r\n }\r\n }, [storageKey, mode]);\r\n}\r\n"]}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -239,4 +239,6 @@ declare function useUndoRedo<T>(initialValue: T, options?: UseUndoRedoOptions &
|
|
|
239
239
|
currentIndex: number;
|
|
240
240
|
};
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
declare function useThemeModePersistence(storageKey?: string): void;
|
|
243
|
+
|
|
244
|
+
export { type ResolvedSize, type ResponsivePropEntry, type UseColorModeReturn, type UseControllableStateOptions, type UseSizeStyleOptions, getSizes, useBreakpoint, useColorMode, useControllableState, useMergedResponsiveStyles, useResponsiveStyles, useSizeStyle, useSizeToken, useSizes, useThemeModePersistence, useTypography, useUndoRedo };
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ThemeContext, useTheme } from '../chunk-
|
|
1
|
+
import { ThemeContext, useTheme } from '../chunk-QP6G3F24.js';
|
|
2
|
+
export { useThemeModePersistence } from '../chunk-QP6G3F24.js';
|
|
2
3
|
import { isResponsiveValue, resolveTypography, resolveTokenReference, resolveFontSize, resolveResponsiveValue } from '../chunk-O4WVNYS5.js';
|
|
3
4
|
import * as React from 'react';
|
|
4
5
|
import { useState, useEffect, useContext, useMemo, useId, useRef, useCallback } from 'react';
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useBreakpoint.ts","../../src/hooks/useColorMode.ts","../../src/hooks/useControllableState.ts","../../src/hooks/useMergedResponsiveStyles.ts","../../src/hooks/useResponsiveStyles.ts","../../src/hooks/useSizeStyle.ts","../../src/hooks/useSizeToken.ts","../../src/hooks/useSizes.ts","../../src/hooks/useTypography.ts","../../src/hooks/useUndoRedo.ts"],"names":["useMemo","token","useState","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\r\n\r\nimport { BaseBreakpoint } from \"@/types\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nconst BREAKPOINTS: Record<BaseBreakpoint, number> = {\r\n sm: 640,\r\n md: 768,\r\n lg: 1024,\r\n xl: 1280,\r\n \"2xl\": 1536,\r\n};\r\n\r\nexport function useBreakpoint(breakpoint: BaseBreakpoint): boolean {\r\n const query = `(min-width: ${BREAKPOINTS[breakpoint]}px)`;\r\n const [matches, setMatches] = useState(\r\n () => typeof window !== \"undefined\" && window.matchMedia(query).matches,\r\n );\r\n\r\n useEffect(() => {\r\n const mql = window.matchMedia(query);\r\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\r\n mql.addEventListener(\"change\", listener);\r\n setMatches(mql.matches);\r\n return () => mql.removeEventListener(\"change\", listener);\r\n }, [query]);\r\n\r\n return matches;\r\n}\r\n","import { useContext } from \"react\";\nimport { ThemeContext } from \"../provider/ThemeContext\";\nimport { ColorMode } from \"@/types/theme\";\n\nexport interface UseColorModeReturn {\n mode: ColorMode;\n setMode: (mode: ColorMode) => void;\n toggleColorMode: () => void;\n}\n\nexport function useColorMode(): UseColorModeReturn {\n const ctx = useContext(ThemeContext);\n\n if (!ctx) {\n throw new Error(\"useColorMode must be used within a ThemeProvider\");\n }\n\n return {\n mode: ctx.mode,\n setMode: ctx.setMode,\n toggleColorMode: () => {\n throw new Error(\"not implemented\");\n },\n };\n}\n","import * as React from \"react\";\n\nexport interface UseControllableStateOptions<T> {\n value?: T;\n defaultValue: T;\n onChange?: (next: T) => void;\n}\n\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: UseControllableStateOptions<T>): [T, (next: T) => void] {\n const [internal, setInternal] = React.useState<T>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? (value as T) : internal;\n const currentRef = React.useRef(current);\n currentRef.current = current;\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n\n const set = React.useCallback(\n (next: T) => {\n if (Object.is(next, currentRef.current)) return;\n if (!isControlled) setInternal(next);\n onChangeRef.current?.(next);\n },\n [isControlled],\n );\n return [current, set];\n}\n","\"use client\";\r\n\r\nimport { useMemo } from \"react\";\r\nimport type { CSSProperties } from \"react\";\r\nimport type { ResponsiveValue, ResponsiveStyles } from \"@/types\";\r\nimport { resolveResponsiveValue } from \"@/utils/responsive\";\r\n\r\n/**\r\n * One entry: a responsive prop value plus a mapper from that value to a\r\n * partial CSSProperties object.\r\n *\r\n * Using `any` for the value type because different entries may have different\r\n * value types, and we only need to call the mapper with the resolved value.\r\n */\r\nexport type ResponsivePropEntry = [\r\n value: ResponsiveValue<any> | undefined,\r\n toCss: (value: any) => Partial<CSSProperties>,\r\n];\r\n\r\nfunction mergeResponsiveProps(\r\n entries: ResponsivePropEntry[],\r\n): ResponsiveStyles {\r\n const result: ResponsiveStyles = {};\r\n\r\n for (const [value, toCss] of entries) {\r\n if (value === undefined) continue;\r\n\r\n const { base, responsive } = resolveResponsiveValue(value);\r\n\r\n if (base !== undefined) {\r\n result.base = { ...result.base, ...toCss(base) };\r\n }\r\n\r\n for (const [bp, v] of Object.entries(responsive)) {\r\n result[bp] = { ...result[bp], ...toCss(v) };\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Merges multiple ResponsiveValue<T> props into one ResponsiveStyles map,\r\n * memoized on the entries' values.\r\n *\r\n * @example\r\n * const responsiveStyles = useMergedResponsiveStyles([\r\n * [gap, (v) => ({ gap: spaceVar(v) })],\r\n * [align, (v) => ({ alignItems: v })],\r\n * ]);\r\n */\r\nexport function useMergedResponsiveStyles(\r\n entries: ResponsivePropEntry[],\r\n): ResponsiveStyles {\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n return useMemo(\r\n () => mergeResponsiveProps(entries),\r\n entries.map(([value]) => value),\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { type CSSProperties, useId, useMemo } from \"react\";\r\n\r\nimport type { ResponsiveStyles } from \"@/types\";\r\nimport { useTheme } from \"@/provider/useTheme\";\r\n\r\nconst cssPropertyToKebab = (property: string) =>\r\n property.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n\r\nconst cssValue = (value: CSSProperties[keyof CSSProperties]) => {\r\n if (typeof value === \"number\") {\r\n return String(value);\r\n }\r\n\r\n return value;\r\n};\r\n\r\nexport function useResponsiveStyles(responsiveStyles?: ResponsiveStyles) {\r\n const { theme } = useTheme();\r\n const id = useId();\r\n\r\n return useMemo(() => {\r\n if (!responsiveStyles || Object.keys(responsiveStyles).length === 0) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n const breakpoints = theme.tokens.breakpoints;\r\n\r\n if (!breakpoints) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n const attribute = id.replace(/:/g, \"\");\r\n\r\n const selector = `[data-kui-responsive=\"${attribute}\"]`;\r\n\r\n const rules: string[] = [];\r\n\r\n for (const [breakpoint, styles] of Object.entries(responsiveStyles)) {\r\n const declarations = Object.entries(styles)\r\n .filter(([, value]) => value !== undefined)\r\n .map(\r\n ([property, value]) =>\r\n `${cssPropertyToKebab(property)}:${cssValue(value)};`,\r\n )\r\n .join(\"\");\r\n\r\n if (!declarations) continue;\r\n\r\n if (breakpoint === \"base\") {\r\n rules.push(`\r\n ${selector} {\r\n ${declarations}\r\n }\r\n `);\r\n\r\n continue;\r\n }\r\n\r\n const breakpointToken = breakpoints[breakpoint];\r\n\r\n if (!breakpointToken) continue;\r\n\r\n rules.push(`\r\n @media (min-width: ${breakpointToken.value}) {\r\n ${selector} {\r\n ${declarations}\r\n }\r\n }\r\n `);\r\n }\r\n\r\n if (rules.length === 0) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n return {\r\n attribute,\r\n style: rules.join(\"\\n\"),\r\n };\r\n }, [responsiveStyles, theme.tokens.breakpoints, id]);\r\n}\r\n","\"use client\";\n\nimport { useMemo, type CSSProperties } from \"react\";\n\nimport type {\n CSSPropertiesWithVars,\n ResponsiveStyles,\n ResponsiveValue,\n} from \"@/types\";\nimport { isResponsiveValue } from \"@/utils/responsive\";\nimport { useTheme } from \"@/provider/useTheme\";\n\n/**\n * Options for {@link useSizeStyle}.\n */\nexport interface UseSizeStyleOptions {\n /**\n * Include `height` in the resolved style.\n * @default true\n */\n includeHeight?: boolean;\n\n /**\n * Include `width` in the resolved style.\n *\n * When enabled, width is derived from the token's own `width` if\n * `iconOnly` is set, otherwise from the token's `height`.\n * @default false\n */\n includeWidth?: boolean;\n\n /**\n * Force `width` to mirror `height`, even when not in icon-only mode.\n * @default false\n */\n widthFromHeight?: boolean;\n\n /**\n * CSS length subtracted from the resolved `height` / `width`\n * (e.g. `\"2px\"`). Applied via `calc(...)`.\n */\n sizeOffset?: string;\n\n /**\n * CSS length subtracted from the resolved `fontSize`.\n * Applied via `calc(...)`.\n */\n fontSizeOffset?: string;\n}\n\n/**\n * Result of {@link useSizeStyle}.\n */\nexport interface ResolvedSize {\n /**\n * Inline styles for non-responsive sizing.\n *\n * For responsive values this is intentionally empty so that\n * breakpoint styles can override each other through CSS.\n */\n style: CSSProperties;\n\n /**\n * Styles generated for responsive sizing.\n */\n responsiveStyles?: ResponsiveStyles;\n\n /** Resolved icon size, if defined on the token. */\n iconSize?: CSSProperties[\"width\"];\n\n /** Resolved font size, after applying `fontSizeOffset`. */\n fontSize?: CSSProperties[\"fontSize\"];\n\n /** Resolved gap between child elements. */\n gap?: CSSProperties[\"gap\"];\n}\n\nconst applySizeOffset = (\n value: string | undefined,\n offset: string | undefined,\n) => {\n if (!value || !offset) return value;\n\n return `calc(${value} - ${offset})`;\n};\n\nimport type { DesignTokens } from \"@/types\";\nimport { resolveFontSize, resolveTokenReference } from \"@/utils\";\n\n/**\n * Builds size-related inline styles from a theme size token.\n *\n * Accepts either a plain size name (e.g. `\"md\"`) or a responsive value\n * (e.g. `{ base: \"sm\", lg: \"md\" }`). All token values are expanded through\n * `resolveTokenReference`, so aliases like `\"{spacing.4}\"` become concrete\n * values.\n *\n * Behavior notes:\n * - Padding is skipped when `iconOnly` is `true`.\n * - `gap` is forced to `0` when `iconOnly` is `true`.\n * - The token's `radius` is exposed as the CSS variable\n * `--kui-<componentName>-radius` so consumers can reuse it in CSS.\n * - For responsive inputs, breakpoint styles are returned in\n * `responsiveStyles` and `style` stays empty.\n *\n * @param size - Size name or responsive size object to resolve.\n * @param iconOnly - When `true`, applies icon-specific sizing (square,\n * no horizontal padding, no gap).\n * @param componentName - Namespace used for generated CSS variables.\n * @param options - See {@link UseSizeStyleOptions}.\n * @returns A {@link ResolvedSize} containing inline and/or responsive styles.\n *\n * @example\n * ```ts\n * const { style } = useSizeStyle(\"md\");\n * // <button style={style} />\n * ```\n *\n * @example\n * ```ts\n * const { responsiveStyles } = useSizeStyle(\n * { base: \"sm\", lg: \"md\" },\n * false,\n * \"button\",\n * { includeWidth: true, sizeOffset: \"2px\" },\n * );\n * ```\n */\nexport function useSizeStyle(\n size: ResponsiveValue<string>,\n iconOnly = false,\n componentName = \"component\",\n options: UseSizeStyleOptions = {},\n): ResolvedSize {\n const {\n widthFromHeight = false,\n includeHeight = true,\n includeWidth = false,\n sizeOffset,\n fontSizeOffset,\n } = options;\n\n const { theme, fallbackSize } = useTheme();\n\n return useMemo(() => {\n const scale = theme.sizes;\n const tokens = theme.tokens as unknown as DesignTokens;\n const typography = theme.typography;\n\n const resolveValue = (value: unknown) =>\n String(resolveTokenReference(value, tokens));\n\n const resolveFont = (value: unknown) =>\n String(resolveFontSize(value, typography, tokens));\n\n const resolveToken = (sizeName: string) =>\n scale[sizeName] ?? scale[fallbackSize] ?? Object.values(scale)[0] ?? {};\n\n const buildStyle = (sizeName: string): CSSPropertiesWithVars => {\n const token = resolveToken(sizeName);\n const style: CSSPropertiesWithVars = {};\n\n const height = resolveValue(token.height);\n const width = resolveValue(token.width);\n const paddingX = resolveValue(token.paddingX);\n const paddingY = resolveValue(token.paddingY);\n const fontSize = resolveFont(token.fontSize);\n const gap = resolveValue(token.gap);\n const radius = resolveValue(token.radius);\n\n if (includeHeight && height) {\n style.height = applySizeOffset(height, sizeOffset);\n }\n\n if (includeWidth) {\n if (iconOnly && width) {\n style.width = applySizeOffset(width, sizeOffset);\n } else if ((iconOnly || widthFromHeight) && includeHeight && height) {\n style.width = applySizeOffset(height, sizeOffset);\n }\n }\n\n if (!iconOnly && paddingX) {\n style.paddingLeft = paddingX;\n style.paddingRight = paddingX;\n }\n\n if (paddingY) {\n style.paddingTop = paddingY;\n style.paddingBottom = paddingY;\n }\n\n if (fontSize) {\n style.fontSize = applySizeOffset(fontSize, fontSizeOffset);\n }\n\n if (gap) {\n style.gap = iconOnly ? 0 : gap;\n }\n\n if (radius) {\n const varName = `--kui-${componentName}-radius` as `--kui-${string}`;\n style[varName] = radius;\n }\n\n return style;\n };\n\n if (!isResponsiveValue(size)) {\n const style = buildStyle(size);\n const token = resolveToken(size);\n\n return {\n style,\n iconSize: resolveValue(token.iconSize),\n fontSize: applySizeOffset(resolveFont(token.fontSize), fontSizeOffset),\n gap: resolveValue(token.gap),\n };\n }\n\n const { base, ...breakpoints } = size;\n\n const baseSize = base ?? fallbackSize;\n\n const responsiveStyles: ResponsiveStyles = {\n base: buildStyle(baseSize),\n };\n\n for (const [breakpoint, breakpointSize] of Object.entries(breakpoints)) {\n if (breakpointSize === undefined) continue;\n\n responsiveStyles[breakpoint] = buildStyle(breakpointSize);\n }\n\n const token = resolveToken(baseSize);\n\n return {\n style: {},\n responsiveStyles,\n iconSize: resolveValue(token.iconSize),\n fontSize: applySizeOffset(resolveFont(token.fontSize), fontSizeOffset),\n gap: resolveValue(token.gap),\n };\n }, [\n theme,\n size,\n fallbackSize,\n iconOnly,\n includeHeight,\n includeWidth,\n widthFromHeight,\n componentName,\n sizeOffset,\n fontSizeOffset,\n ]);\n}\n","import type { ResponsiveValue, SizeToken, DesignTokens } from \"@/types\";\r\n\r\nimport { useMemo } from \"react\";\r\nimport { useTheme } from \"@/provider/useTheme\";\r\nimport { isResponsiveValue } from \"@/utils/responsive\";\r\nimport { resolveTokenReference } from \"@/utils/resolveTokenReference\";\r\nimport { resolveFontSize } from \"@/utils/resolveFontSize\";\r\n\r\ntype SizeTokenValue = SizeToken[keyof SizeToken];\r\n\r\nfunction applyOffset(value: SizeTokenValue, offset?: string): SizeTokenValue {\r\n if (offset == null || value == null) {\r\n return value;\r\n }\r\n\r\n if (typeof value !== \"string\") {\r\n return value;\r\n }\r\n\r\n return `calc(${value} - ${offset})`;\r\n}\r\n\r\n/**\r\n * Resolves a size token from the active theme.\r\n *\r\n * Accepts either a plain size name (e.g. `\"md\"`) or a responsive value\r\n * (e.g. `{ base: \"md\", lg: \"xl\" }`). When a responsive object is passed,\r\n * the `base` key is used, falling back to the theme's `fallbackSize`.\r\n *\r\n * All token values are passed through `resolveTokenReference`, so token\r\n * aliases like `\"{spacing.4}\"` are expanded to their concrete value.\r\n * `fontSize` is the one exception: it's a reference into `typography`,\r\n * not `tokens` directly, and is resolved via `resolveFontSize`.\r\n *\r\n * @param size - Size name or responsive size object to resolve.\r\n * @returns The full resolved {@link SizeToken} for the requested size.\r\n *\r\n * @example\r\n * ```ts\r\n * const token = useSizeToken(\"md\");\r\n * // { height: \"40px\", paddingX: \"16px\", fontSize: \"14px\", ... }\r\n * ```\r\n *\r\n * @example\r\n * ```ts\r\n * const token = useSizeToken({ base: \"sm\", lg: \"md\" });\r\n * ```\r\n */\r\nexport function useSizeToken(size: ResponsiveValue<string>): SizeToken;\r\n\r\n/**\r\n * Resolves a single value from a size token.\r\n *\r\n * Like the object overload, this accepts a plain or responsive size name and\r\n * expands token references. When `offset` is provided, the resolved value is\r\n * wrapped in a `calc(...)` expression subtracting the offset — useful for\r\n * trimming sizes without redefining a token.\r\n *\r\n * @typeParam K - The key of {@link SizeToken} to read (e.g. `\"height\"`, `\"fontSize\"`).\r\n * @param size - Size name or responsive size object to resolve.\r\n * @param key - The token field to read.\r\n * @param offset - Optional CSS length to subtract from the resolved value.\r\n * @returns The resolved (and optionally offset) token field.\r\n *\r\n * @example\r\n * ```ts\r\n * const height = useSizeToken(\"md\", \"height\");\r\n * // \"40px\"\r\n *\r\n * const height = useSizeToken(\"md\", \"height\", \"4px\");\r\n * // \"calc(40px - 4px)\"\r\n * ```\r\n *\r\n * @example\r\n * ```ts\r\n * const fontSize = useSizeToken({ base: \"sm\", lg: \"md\" }, \"fontSize\");\r\n * ```\r\n */\r\nexport function useSizeToken<K extends keyof SizeToken>(\r\n size: ResponsiveValue<string>,\r\n key: K,\r\n offset?: string,\r\n): SizeToken[K];\r\n\r\nexport function useSizeToken<K extends keyof SizeToken>(\r\n size: ResponsiveValue<string>,\r\n key?: K,\r\n offset?: string,\r\n): SizeToken | SizeToken[K] {\r\n const { theme, fallbackSize } = useTheme();\r\n\r\n return useMemo(() => {\r\n const scale = theme.sizes;\r\n const tokens = theme.tokens as unknown as DesignTokens;\r\n const typography = theme.typography;\r\n\r\n const baseSize = isResponsiveValue(size)\r\n ? (size.base ?? fallbackSize)\r\n : size;\r\n\r\n const token =\r\n scale[baseSize] ?? scale[fallbackSize] ?? Object.values(scale)[0] ?? {};\r\n\r\n const resolve = (value: unknown, field?: string) =>\r\n field === \"fontSize\"\r\n ? resolveFontSize(value, typography, tokens)\r\n : value == null\r\n ? value\r\n : resolveTokenReference(value, tokens);\r\n\r\n if (!key) {\r\n const resolved = Object.fromEntries(\r\n Object.entries(token).map(([k, v]) => [k, resolve(v, k)]),\r\n ) as SizeToken;\r\n\r\n return resolved;\r\n }\r\n\r\n return applyOffset(\r\n resolve(token[key], key) as SizeTokenValue,\r\n offset,\r\n ) as SizeToken[K];\r\n }, [theme, size, fallbackSize, key, offset]);\r\n}\r\n","import { useTheme } from \"@/provider/useTheme\";\r\nimport type { Size, Theme } from \"@/types\";\r\n\r\nexport function getSizes(theme: Theme): Size[] {\r\n return Object.keys(theme.sizes ?? {}) as Size[];\r\n}\r\n\r\nexport function useSizes(): Size[] {\r\n const { theme } = useTheme();\r\n return getSizes(theme);\r\n}\r\n","import { useTheme } from \"@/provider\";\r\nimport { resolveTypography } from \"@/utils\";\r\n\r\nexport function useTypography(name?: string) {\r\n const { theme } = useTheme();\r\n\r\n return resolveTypography(\r\n name ? theme.typography[name] : undefined,\r\n theme.tokens,\r\n );\r\n}","import { useCallback, useRef, useState } from \"react\";\r\n\r\ninterface UseUndoRedoOptions {\r\n /**\r\n * Maximum number of history entries to keep.\r\n * Only applies when `undoable` is `true` and the component manages its own history.\r\n * @default 30\r\n */\r\n maxHistory?: number;\r\n}\r\n\r\n/**\r\n * Manages a history stack for a value, providing undo/redo capabilities.\r\n * The hook stores the current value in its own state, but you can also\r\n * sync it with external state by calling `push` when the external value changes.\r\n *\r\n * @param initialValue - The starting value.\r\n * @param options - Configuration (maxHistory).\r\n * @returns An object with the current value, setters, and undo/redo controls.\r\n */\r\nexport function useUndoRedo<T>(\r\n initialValue: T,\r\n options: UseUndoRedoOptions & {\r\n onValueChange?: (value: T | undefined) => void;\r\n } = {},\r\n) {\r\n const { maxHistory = 30, onValueChange } = options;\r\n\r\n const [value, setValue] = useState<T | undefined>(initialValue);\r\n const historyRef = useRef<T[]>([initialValue]);\r\n const indexRef = useRef(0);\r\n\r\n const push = useCallback(\r\n (newValue: T) => {\r\n if (newValue === historyRef.current[indexRef.current]) return;\r\n\r\n historyRef.current = historyRef.current.slice(0, indexRef.current + 1);\r\n\r\n historyRef.current.push(newValue);\r\n if (historyRef.current.length > maxHistory) {\r\n historyRef.current = historyRef.current.slice(-maxHistory);\r\n indexRef.current = historyRef.current.length - 1;\r\n } else {\r\n indexRef.current = historyRef.current.length - 1;\r\n }\r\n\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n },\r\n [maxHistory, onValueChange],\r\n );\r\n\r\n const undo = useCallback(() => {\r\n if (indexRef.current <= 0) return;\r\n indexRef.current -= 1;\r\n const newValue = historyRef.current[indexRef.current];\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n }, [onValueChange]);\r\n\r\n const redo = useCallback(() => {\r\n if (indexRef.current >= historyRef.current.length - 1) return;\r\n indexRef.current += 1;\r\n const newVal = historyRef.current[indexRef.current];\r\n setValue(newVal);\r\n }, []);\r\n\r\n const reset = useCallback(\r\n (newValue: T) => {\r\n historyRef.current = [newValue];\r\n indexRef.current = 0;\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n },\r\n [onValueChange],\r\n );\r\n\r\n const canUndo = indexRef.current > 0;\r\n const canRedo = indexRef.current < historyRef.current.length - 1;\r\n\r\n return {\r\n value,\r\n setValue,\r\n push,\r\n undo,\r\n redo,\r\n reset,\r\n canUndo,\r\n canRedo,\r\n history: historyRef.current,\r\n currentIndex: indexRef.current,\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useBreakpoint.ts","../../src/hooks/useColorMode.ts","../../src/hooks/useControllableState.ts","../../src/hooks/useMergedResponsiveStyles.ts","../../src/hooks/useResponsiveStyles.ts","../../src/hooks/useSizeStyle.ts","../../src/hooks/useSizeToken.ts","../../src/hooks/useSizes.ts","../../src/hooks/useTypography.ts","../../src/hooks/useUndoRedo.ts"],"names":["useMemo","token","useState","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\r\n\r\nimport { BaseBreakpoint } from \"@/types\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nconst BREAKPOINTS: Record<BaseBreakpoint, number> = {\r\n sm: 640,\r\n md: 768,\r\n lg: 1024,\r\n xl: 1280,\r\n \"2xl\": 1536,\r\n};\r\n\r\nexport function useBreakpoint(breakpoint: BaseBreakpoint): boolean {\r\n const query = `(min-width: ${BREAKPOINTS[breakpoint]}px)`;\r\n const [matches, setMatches] = useState(\r\n () => typeof window !== \"undefined\" && window.matchMedia(query).matches,\r\n );\r\n\r\n useEffect(() => {\r\n const mql = window.matchMedia(query);\r\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\r\n mql.addEventListener(\"change\", listener);\r\n setMatches(mql.matches);\r\n return () => mql.removeEventListener(\"change\", listener);\r\n }, [query]);\r\n\r\n return matches;\r\n}\r\n","import { useContext } from \"react\";\nimport { ThemeContext } from \"../provider/ThemeContext\";\nimport { ColorMode } from \"@/types/theme\";\n\nexport interface UseColorModeReturn {\n mode: ColorMode;\n setMode: (mode: ColorMode) => void;\n toggleColorMode: () => void;\n}\n\nexport function useColorMode(): UseColorModeReturn {\n const ctx = useContext(ThemeContext);\n\n if (!ctx) {\n throw new Error(\"useColorMode must be used within a ThemeProvider\");\n }\n\n return {\n mode: ctx.mode,\n setMode: ctx.setMode,\n toggleColorMode: () => {\n throw new Error(\"not implemented\");\n },\n };\n}\n","import * as React from \"react\";\n\nexport interface UseControllableStateOptions<T> {\n value?: T;\n defaultValue: T;\n onChange?: (next: T) => void;\n}\n\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: UseControllableStateOptions<T>): [T, (next: T) => void] {\n const [internal, setInternal] = React.useState<T>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? (value as T) : internal;\n const currentRef = React.useRef(current);\n currentRef.current = current;\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n\n const set = React.useCallback(\n (next: T) => {\n if (Object.is(next, currentRef.current)) return;\n if (!isControlled) setInternal(next);\n onChangeRef.current?.(next);\n },\n [isControlled],\n );\n return [current, set];\n}\n","\"use client\";\r\n\r\nimport { useMemo } from \"react\";\r\nimport type { CSSProperties } from \"react\";\r\nimport type { ResponsiveValue, ResponsiveStyles } from \"@/types\";\r\nimport { resolveResponsiveValue } from \"@/utils/responsive\";\r\n\r\n/**\r\n * One entry: a responsive prop value plus a mapper from that value to a\r\n * partial CSSProperties object.\r\n *\r\n * Using `any` for the value type because different entries may have different\r\n * value types, and we only need to call the mapper with the resolved value.\r\n */\r\nexport type ResponsivePropEntry = [\r\n value: ResponsiveValue<any> | undefined,\r\n toCss: (value: any) => Partial<CSSProperties>,\r\n];\r\n\r\nfunction mergeResponsiveProps(\r\n entries: ResponsivePropEntry[],\r\n): ResponsiveStyles {\r\n const result: ResponsiveStyles = {};\r\n\r\n for (const [value, toCss] of entries) {\r\n if (value === undefined) continue;\r\n\r\n const { base, responsive } = resolveResponsiveValue(value);\r\n\r\n if (base !== undefined) {\r\n result.base = { ...result.base, ...toCss(base) };\r\n }\r\n\r\n for (const [bp, v] of Object.entries(responsive)) {\r\n result[bp] = { ...result[bp], ...toCss(v) };\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Merges multiple ResponsiveValue<T> props into one ResponsiveStyles map,\r\n * memoized on the entries' values.\r\n *\r\n * @example\r\n * const responsiveStyles = useMergedResponsiveStyles([\r\n * [gap, (v) => ({ gap: spaceVar(v) })],\r\n * [align, (v) => ({ alignItems: v })],\r\n * ]);\r\n */\r\nexport function useMergedResponsiveStyles(\r\n entries: ResponsivePropEntry[],\r\n): ResponsiveStyles {\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n return useMemo(\r\n () => mergeResponsiveProps(entries),\r\n entries.map(([value]) => value),\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { type CSSProperties, useId, useMemo } from \"react\";\r\n\r\nimport type { ResponsiveStyles } from \"@/types\";\r\nimport { useTheme } from \"@/provider/useTheme\";\r\n\r\nconst cssPropertyToKebab = (property: string) =>\r\n property.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n\r\nconst cssValue = (value: CSSProperties[keyof CSSProperties]) => {\r\n if (typeof value === \"number\") {\r\n return String(value);\r\n }\r\n\r\n return value;\r\n};\r\n\r\nexport function useResponsiveStyles(responsiveStyles?: ResponsiveStyles) {\r\n const { theme } = useTheme();\r\n const id = useId();\r\n\r\n return useMemo(() => {\r\n if (!responsiveStyles || Object.keys(responsiveStyles).length === 0) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n const breakpoints = theme.tokens.breakpoints;\r\n\r\n if (!breakpoints) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n const attribute = id.replace(/:/g, \"\");\r\n\r\n const selector = `[data-kui-responsive=\"${attribute}\"]`;\r\n\r\n const rules: string[] = [];\r\n\r\n for (const [breakpoint, styles] of Object.entries(responsiveStyles)) {\r\n const declarations = Object.entries(styles)\r\n .filter(([, value]) => value !== undefined)\r\n .map(\r\n ([property, value]) =>\r\n `${cssPropertyToKebab(property)}:${cssValue(value)};`,\r\n )\r\n .join(\"\");\r\n\r\n if (!declarations) continue;\r\n\r\n if (breakpoint === \"base\") {\r\n rules.push(`\r\n ${selector} {\r\n ${declarations}\r\n }\r\n `);\r\n\r\n continue;\r\n }\r\n\r\n const breakpointToken = breakpoints[breakpoint];\r\n\r\n if (!breakpointToken) continue;\r\n\r\n rules.push(`\r\n @media (min-width: ${breakpointToken.value}) {\r\n ${selector} {\r\n ${declarations}\r\n }\r\n }\r\n `);\r\n }\r\n\r\n if (rules.length === 0) {\r\n return {\r\n attribute: undefined,\r\n style: undefined,\r\n };\r\n }\r\n\r\n return {\r\n attribute,\r\n style: rules.join(\"\\n\"),\r\n };\r\n }, [responsiveStyles, theme.tokens.breakpoints, id]);\r\n}\r\n","\"use client\";\n\nimport { useMemo, type CSSProperties } from \"react\";\n\nimport type {\n CSSPropertiesWithVars,\n ResponsiveStyles,\n ResponsiveValue,\n} from \"@/types\";\nimport { isResponsiveValue } from \"@/utils/responsive\";\nimport { useTheme } from \"@/provider/useTheme\";\n\n/**\n * Options for {@link useSizeStyle}.\n */\nexport interface UseSizeStyleOptions {\n /**\n * Include `height` in the resolved style.\n * @default true\n */\n includeHeight?: boolean;\n\n /**\n * Include `width` in the resolved style.\n *\n * When enabled, width is derived from the token's own `width` if\n * `iconOnly` is set, otherwise from the token's `height`.\n * @default false\n */\n includeWidth?: boolean;\n\n /**\n * Force `width` to mirror `height`, even when not in icon-only mode.\n * @default false\n */\n widthFromHeight?: boolean;\n\n /**\n * CSS length subtracted from the resolved `height` / `width`\n * (e.g. `\"2px\"`). Applied via `calc(...)`.\n */\n sizeOffset?: string;\n\n /**\n * CSS length subtracted from the resolved `fontSize`.\n * Applied via `calc(...)`.\n */\n fontSizeOffset?: string;\n}\n\n/**\n * Result of {@link useSizeStyle}.\n */\nexport interface ResolvedSize {\n /**\n * Inline styles for non-responsive sizing.\n *\n * For responsive values this is intentionally empty so that\n * breakpoint styles can override each other through CSS.\n */\n style: CSSProperties;\n\n /**\n * Styles generated for responsive sizing.\n */\n responsiveStyles?: ResponsiveStyles;\n\n /** Resolved icon size, if defined on the token. */\n iconSize?: CSSProperties[\"width\"];\n\n /** Resolved font size, after applying `fontSizeOffset`. */\n fontSize?: CSSProperties[\"fontSize\"];\n\n /** Resolved gap between child elements. */\n gap?: CSSProperties[\"gap\"];\n}\n\nconst applySizeOffset = (\n value: string | undefined,\n offset: string | undefined,\n) => {\n if (!value || !offset) return value;\n\n return `calc(${value} - ${offset})`;\n};\n\nimport type { DesignTokens } from \"@/types\";\nimport { resolveFontSize, resolveTokenReference } from \"@/utils\";\n\n/**\n * Builds size-related inline styles from a theme size token.\n *\n * Accepts either a plain size name (e.g. `\"md\"`) or a responsive value\n * (e.g. `{ base: \"sm\", lg: \"md\" }`). All token values are expanded through\n * `resolveTokenReference`, so aliases like `\"{spacing.4}\"` become concrete\n * values.\n *\n * Behavior notes:\n * - Padding is skipped when `iconOnly` is `true`.\n * - `gap` is forced to `0` when `iconOnly` is `true`.\n * - The token's `radius` is exposed as the CSS variable\n * `--kui-<componentName>-radius` so consumers can reuse it in CSS.\n * - For responsive inputs, breakpoint styles are returned in\n * `responsiveStyles` and `style` stays empty.\n *\n * @param size - Size name or responsive size object to resolve.\n * @param iconOnly - When `true`, applies icon-specific sizing (square,\n * no horizontal padding, no gap).\n * @param componentName - Namespace used for generated CSS variables.\n * @param options - See {@link UseSizeStyleOptions}.\n * @returns A {@link ResolvedSize} containing inline and/or responsive styles.\n *\n * @example\n * ```ts\n * const { style } = useSizeStyle(\"md\");\n * // <button style={style} />\n * ```\n *\n * @example\n * ```ts\n * const { responsiveStyles } = useSizeStyle(\n * { base: \"sm\", lg: \"md\" },\n * false,\n * \"button\",\n * { includeWidth: true, sizeOffset: \"2px\" },\n * );\n * ```\n */\nexport function useSizeStyle(\n size: ResponsiveValue<string>,\n iconOnly = false,\n componentName = \"component\",\n options: UseSizeStyleOptions = {},\n): ResolvedSize {\n const {\n widthFromHeight = false,\n includeHeight = true,\n includeWidth = false,\n sizeOffset,\n fontSizeOffset,\n } = options;\n\n const { theme, fallbackSize } = useTheme();\n\n return useMemo(() => {\n const scale = theme.sizes;\n const tokens = theme.tokens as unknown as DesignTokens;\n const typography = theme.typography;\n\n const resolveValue = (value: unknown) =>\n String(resolveTokenReference(value, tokens));\n\n const resolveFont = (value: unknown) =>\n String(resolveFontSize(value, typography, tokens));\n\n const resolveToken = (sizeName: string) =>\n scale[sizeName] ?? scale[fallbackSize] ?? Object.values(scale)[0] ?? {};\n\n const buildStyle = (sizeName: string): CSSPropertiesWithVars => {\n const token = resolveToken(sizeName);\n const style: CSSPropertiesWithVars = {};\n\n const height = resolveValue(token.height);\n const width = resolveValue(token.width);\n const paddingX = resolveValue(token.paddingX);\n const paddingY = resolveValue(token.paddingY);\n const fontSize = resolveFont(token.fontSize);\n const gap = resolveValue(token.gap);\n const radius = resolveValue(token.radius);\n\n if (includeHeight && height) {\n style.height = applySizeOffset(height, sizeOffset);\n }\n\n if (includeWidth) {\n if (iconOnly && width) {\n style.width = applySizeOffset(width, sizeOffset);\n } else if ((iconOnly || widthFromHeight) && includeHeight && height) {\n style.width = applySizeOffset(height, sizeOffset);\n }\n }\n\n if (!iconOnly && paddingX) {\n style.paddingLeft = paddingX;\n style.paddingRight = paddingX;\n }\n\n if (paddingY) {\n style.paddingTop = paddingY;\n style.paddingBottom = paddingY;\n }\n\n if (fontSize) {\n style.fontSize = applySizeOffset(fontSize, fontSizeOffset);\n }\n\n if (gap) {\n style.gap = iconOnly ? 0 : gap;\n }\n\n if (radius) {\n const varName = `--kui-${componentName}-radius` as `--kui-${string}`;\n style[varName] = radius;\n }\n\n return style;\n };\n\n if (!isResponsiveValue(size)) {\n const style = buildStyle(size);\n const token = resolveToken(size);\n\n return {\n style,\n iconSize: resolveValue(token.iconSize),\n fontSize: applySizeOffset(resolveFont(token.fontSize), fontSizeOffset),\n gap: resolveValue(token.gap),\n };\n }\n\n const { base, ...breakpoints } = size;\n\n const baseSize = base ?? fallbackSize;\n\n const responsiveStyles: ResponsiveStyles = {\n base: buildStyle(baseSize),\n };\n\n for (const [breakpoint, breakpointSize] of Object.entries(breakpoints)) {\n if (breakpointSize === undefined) continue;\n\n responsiveStyles[breakpoint] = buildStyle(breakpointSize);\n }\n\n const token = resolveToken(baseSize);\n\n return {\n style: {},\n responsiveStyles,\n iconSize: resolveValue(token.iconSize),\n fontSize: applySizeOffset(resolveFont(token.fontSize), fontSizeOffset),\n gap: resolveValue(token.gap),\n };\n }, [\n theme,\n size,\n fallbackSize,\n iconOnly,\n includeHeight,\n includeWidth,\n widthFromHeight,\n componentName,\n sizeOffset,\n fontSizeOffset,\n ]);\n}\n","import type { ResponsiveValue, SizeToken, DesignTokens } from \"@/types\";\r\n\r\nimport { useMemo } from \"react\";\r\nimport { useTheme } from \"@/provider/useTheme\";\r\nimport { isResponsiveValue } from \"@/utils/responsive\";\r\nimport { resolveTokenReference } from \"@/utils/resolveTokenReference\";\r\nimport { resolveFontSize } from \"@/utils/resolveFontSize\";\r\n\r\ntype SizeTokenValue = SizeToken[keyof SizeToken];\r\n\r\nfunction applyOffset(value: SizeTokenValue, offset?: string): SizeTokenValue {\r\n if (offset == null || value == null) {\r\n return value;\r\n }\r\n\r\n if (typeof value !== \"string\") {\r\n return value;\r\n }\r\n\r\n return `calc(${value} - ${offset})`;\r\n}\r\n\r\n/**\r\n * Resolves a size token from the active theme.\r\n *\r\n * Accepts either a plain size name (e.g. `\"md\"`) or a responsive value\r\n * (e.g. `{ base: \"md\", lg: \"xl\" }`). When a responsive object is passed,\r\n * the `base` key is used, falling back to the theme's `fallbackSize`.\r\n *\r\n * All token values are passed through `resolveTokenReference`, so token\r\n * aliases like `\"{spacing.4}\"` are expanded to their concrete value.\r\n * `fontSize` is the one exception: it's a reference into `typography`,\r\n * not `tokens` directly, and is resolved via `resolveFontSize`.\r\n *\r\n * @param size - Size name or responsive size object to resolve.\r\n * @returns The full resolved {@link SizeToken} for the requested size.\r\n *\r\n * @example\r\n * ```ts\r\n * const token = useSizeToken(\"md\");\r\n * // { height: \"40px\", paddingX: \"16px\", fontSize: \"14px\", ... }\r\n * ```\r\n *\r\n * @example\r\n * ```ts\r\n * const token = useSizeToken({ base: \"sm\", lg: \"md\" });\r\n * ```\r\n */\r\nexport function useSizeToken(size: ResponsiveValue<string>): SizeToken;\r\n\r\n/**\r\n * Resolves a single value from a size token.\r\n *\r\n * Like the object overload, this accepts a plain or responsive size name and\r\n * expands token references. When `offset` is provided, the resolved value is\r\n * wrapped in a `calc(...)` expression subtracting the offset — useful for\r\n * trimming sizes without redefining a token.\r\n *\r\n * @typeParam K - The key of {@link SizeToken} to read (e.g. `\"height\"`, `\"fontSize\"`).\r\n * @param size - Size name or responsive size object to resolve.\r\n * @param key - The token field to read.\r\n * @param offset - Optional CSS length to subtract from the resolved value.\r\n * @returns The resolved (and optionally offset) token field.\r\n *\r\n * @example\r\n * ```ts\r\n * const height = useSizeToken(\"md\", \"height\");\r\n * // \"40px\"\r\n *\r\n * const height = useSizeToken(\"md\", \"height\", \"4px\");\r\n * // \"calc(40px - 4px)\"\r\n * ```\r\n *\r\n * @example\r\n * ```ts\r\n * const fontSize = useSizeToken({ base: \"sm\", lg: \"md\" }, \"fontSize\");\r\n * ```\r\n */\r\nexport function useSizeToken<K extends keyof SizeToken>(\r\n size: ResponsiveValue<string>,\r\n key: K,\r\n offset?: string,\r\n): SizeToken[K];\r\n\r\nexport function useSizeToken<K extends keyof SizeToken>(\r\n size: ResponsiveValue<string>,\r\n key?: K,\r\n offset?: string,\r\n): SizeToken | SizeToken[K] {\r\n const { theme, fallbackSize } = useTheme();\r\n\r\n return useMemo(() => {\r\n const scale = theme.sizes;\r\n const tokens = theme.tokens as unknown as DesignTokens;\r\n const typography = theme.typography;\r\n\r\n const baseSize = isResponsiveValue(size)\r\n ? (size.base ?? fallbackSize)\r\n : size;\r\n\r\n const token =\r\n scale[baseSize] ?? scale[fallbackSize] ?? Object.values(scale)[0] ?? {};\r\n\r\n const resolve = (value: unknown, field?: string) =>\r\n field === \"fontSize\"\r\n ? resolveFontSize(value, typography, tokens)\r\n : value == null\r\n ? value\r\n : resolveTokenReference(value, tokens);\r\n\r\n if (!key) {\r\n const resolved = Object.fromEntries(\r\n Object.entries(token).map(([k, v]) => [k, resolve(v, k)]),\r\n ) as SizeToken;\r\n\r\n return resolved;\r\n }\r\n\r\n return applyOffset(\r\n resolve(token[key], key) as SizeTokenValue,\r\n offset,\r\n ) as SizeToken[K];\r\n }, [theme, size, fallbackSize, key, offset]);\r\n}\r\n","import { useTheme } from \"@/provider/useTheme\";\r\nimport type { Size, Theme } from \"@/types\";\r\n\r\nexport function getSizes(theme: Theme): Size[] {\r\n return Object.keys(theme.sizes ?? {}) as Size[];\r\n}\r\n\r\nexport function useSizes(): Size[] {\r\n const { theme } = useTheme();\r\n return getSizes(theme);\r\n}\r\n","import { useTheme } from \"@/provider\";\r\nimport { resolveTypography } from \"@/utils\";\r\n\r\nexport function useTypography(name?: string) {\r\n const { theme } = useTheme();\r\n\r\n return resolveTypography(\r\n name ? theme.typography[name] : undefined,\r\n theme.tokens,\r\n );\r\n}","import { useCallback, useRef, useState } from \"react\";\r\n\r\ninterface UseUndoRedoOptions {\r\n /**\r\n * Maximum number of history entries to keep.\r\n * Only applies when `undoable` is `true` and the component manages its own history.\r\n * @default 30\r\n */\r\n maxHistory?: number;\r\n}\r\n\r\n/**\r\n * Manages a history stack for a value, providing undo/redo capabilities.\r\n * The hook stores the current value in its own state, but you can also\r\n * sync it with external state by calling `push` when the external value changes.\r\n *\r\n * @param initialValue - The starting value.\r\n * @param options - Configuration (maxHistory).\r\n * @returns An object with the current value, setters, and undo/redo controls.\r\n */\r\nexport function useUndoRedo<T>(\r\n initialValue: T,\r\n options: UseUndoRedoOptions & {\r\n onValueChange?: (value: T | undefined) => void;\r\n } = {},\r\n) {\r\n const { maxHistory = 30, onValueChange } = options;\r\n\r\n const [value, setValue] = useState<T | undefined>(initialValue);\r\n const historyRef = useRef<T[]>([initialValue]);\r\n const indexRef = useRef(0);\r\n\r\n const push = useCallback(\r\n (newValue: T) => {\r\n if (newValue === historyRef.current[indexRef.current]) return;\r\n\r\n historyRef.current = historyRef.current.slice(0, indexRef.current + 1);\r\n\r\n historyRef.current.push(newValue);\r\n if (historyRef.current.length > maxHistory) {\r\n historyRef.current = historyRef.current.slice(-maxHistory);\r\n indexRef.current = historyRef.current.length - 1;\r\n } else {\r\n indexRef.current = historyRef.current.length - 1;\r\n }\r\n\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n },\r\n [maxHistory, onValueChange],\r\n );\r\n\r\n const undo = useCallback(() => {\r\n if (indexRef.current <= 0) return;\r\n indexRef.current -= 1;\r\n const newValue = historyRef.current[indexRef.current];\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n }, [onValueChange]);\r\n\r\n const redo = useCallback(() => {\r\n if (indexRef.current >= historyRef.current.length - 1) return;\r\n indexRef.current += 1;\r\n const newVal = historyRef.current[indexRef.current];\r\n setValue(newVal);\r\n }, []);\r\n\r\n const reset = useCallback(\r\n (newValue: T) => {\r\n historyRef.current = [newValue];\r\n indexRef.current = 0;\r\n setValue(newValue);\r\n onValueChange?.(newValue);\r\n },\r\n [onValueChange],\r\n );\r\n\r\n const canUndo = indexRef.current > 0;\r\n const canRedo = indexRef.current < historyRef.current.length - 1;\r\n\r\n return {\r\n value,\r\n setValue,\r\n push,\r\n undo,\r\n redo,\r\n reset,\r\n canUndo,\r\n canRedo,\r\n history: historyRef.current,\r\n currentIndex: indexRef.current,\r\n };\r\n}\r\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -386,4 +386,9 @@ declare const ThemeContext: React.Context<ThemeContextValue | null>;
|
|
|
386
386
|
|
|
387
387
|
declare function useTheme(): ThemeContextValue;
|
|
388
388
|
|
|
389
|
-
|
|
389
|
+
interface PersistModeProps {
|
|
390
|
+
storageKey?: string;
|
|
391
|
+
}
|
|
392
|
+
declare function PersistMode({ storageKey }: PersistModeProps): null;
|
|
393
|
+
|
|
394
|
+
export { ColorMode, type CycleValidationResult, DesignTokens, type ExtractPath, type Invalid, type IsTokenReference, type PathExists, PersistMode, type PersistModeProps, RecipeDefinition, type ResolvePath, ResolvedTokens, SemanticToken, SemanticTokens, SizeScale, SizeToken, type SplitPath, Theme, ThemeContext, type ThemeContextValue, TokenDefinition, TokenReferenceString$1 as TokenReferenceString, TokenValue, Typography, type ValidateRecipeSection, type ValidateRecipes, type ValidateReferenceExists, type ValidateSemanticTokenSection, type ValidateSemanticTokens, type ValidateSizes, type ValidateSizesSection, type ValidateTheme, type ValidateTokenSection, type ValidateTokens, type ValidateTypography, type ValidateTypographyReferencesSection, type ValidateTypographySection, assertNoCycles, defineRecipe, defineSemanticToken, defineSemanticTokens, defineSize, defineSizes, defineTheme, defineToken, defineTokens, defineTypography, useTheme, validateNoCycles };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { useThemeModePersistence } from './chunk-QP6G3F24.js';
|
|
2
|
+
export { ThemeContext, useTheme } from './chunk-QP6G3F24.js';
|
|
2
3
|
export { composeRefs, createComponent, createFromProps, cssToClass, deepMerge, hasKuiMeta, hashStyle, injectStyle, isMotionGated, isResponsiveValue, kebabCase, mergeResponsiveValue, registerStyle, requireProvider, resolveFontSize, resolveResponsiveValue, resolveSemanticTokenReferences, resolveStyle, resolveToken, resolveTokenReference, resolveTokens, resolveTypography, serializeStyle, styleRegistry, toKebabCase, toResponsiveClasses, tokensToCssVars, useValidateChildren, warnOnFlatCompoundConflict } from './chunk-O4WVNYS5.js';
|
|
3
4
|
import './chunk-RV5MKKBP.js';
|
|
4
5
|
|
|
@@ -145,6 +146,12 @@ function defineTheme(theme) {
|
|
|
145
146
|
return theme;
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
// src/provider/PersistMode.tsx
|
|
150
|
+
function PersistMode({ storageKey }) {
|
|
151
|
+
useThemeModePersistence(storageKey);
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export { PersistMode, assertNoCycles, defineRecipe, defineSemanticToken, defineSemanticTokens, defineSize, defineSizes, defineTheme, defineToken, defineTokens, defineTypography, validateNoCycles };
|
|
149
156
|
//# sourceMappingURL=index.js.map
|
|
150
157
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/define/token.ts","../src/define/semanticToken.ts","../src/define/size.ts","../src/define/typography.ts","../src/define/recipe.ts","../src/runtime/validateCycles.ts","../src/define/theme.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { TokenValue } from \"@/types\";\n\nexport function defineToken<T extends TokenValue>(value: T) {\n return {\n value,\n };\n}\n\nexport function defineTokens<T extends Record<string, TokenValue>>(tokens: T) {\n return Object.fromEntries(\n Object.entries(tokens).map(([key, value]) => [key, defineToken(value)]),\n ) as {\n [K in keyof T]: ReturnType<typeof defineToken<T[K]>>;\n };\n}\n","import type { SemanticToken, TokenValue } from \"@/types\";\n\n/**\n * Defines a semantic token that shares a single value across both\n * light and dark modes (the explicit sameForBothModes shorthand).\n */\nexport function defineSemanticToken<T extends TokenValue>(\n value: T,\n): SemanticToken<T>;\n/**\n * Defines a semantic token with distinct light and dark values.\n */\nexport function defineSemanticToken<T extends TokenValue>(\n light: T,\n dark: T,\n): SemanticToken<T>;\nexport function defineSemanticToken<T extends TokenValue>(\n lightOrValue: T,\n dark?: T,\n): SemanticToken<T> {\n if (dark === undefined) {\n return {\n value: {\n sameForBothModes: true,\n value: lightOrValue,\n },\n };\n }\n\n return {\n value: {\n sameForBothModes: false,\n light: lightOrValue,\n dark,\n },\n };\n}\n\ntype SemanticTokenInput<T extends TokenValue> = T | { light: T; dark: T };\n\nexport function defineSemanticTokens<\n T extends Record<string, SemanticTokenInput<TokenValue>>,\n>(\n tokens: T,\n): {\n [K in keyof T]: SemanticToken<T[K] extends { light: infer V; dark: infer _ }\n ? V extends TokenValue\n ? V\n : never\n : T[K] extends TokenValue\n ? T[K]\n : never>;\n} {\n return Object.fromEntries(\n Object.entries(tokens).map(([key, entry]) => [\n key,\n entry !== null &&\n typeof entry === \"object\" &&\n \"light\" in entry &&\n \"dark\" in entry\n ? defineSemanticToken(entry.light, entry.dark)\n : defineSemanticToken(entry as TokenValue),\n ]),\n ) as ReturnType<typeof defineSemanticTokens<T>>;\n}\n","import type { SizeScale, SizeToken } from \"@/types\";\n\nexport function defineSize<const T extends SizeToken>(size: T): T {\n return size;\n}\n\nexport function defineSizes<const T extends SizeScale>(sizes: T): T {\n return sizes;\n}\n","import type { Typography } from \"@/types\";\n\nexport function defineTypography<const T extends Typography>(typography: T): T {\n return typography;\n}\n","import type { RecipeDefinition } from \"@/types\";\n\n/**\n * Defines a recipe while preserving its literal type.\n *\n * Use this when authoring a custom recipe so TypeScript keeps the exact\n * shape you wrote (variant names, value keys, etc.) instead of widening\n * them to `string`. The returned object is the same reference you passed\n * in — this is a type-only helper with no runtime behavior.\n *\n * @typeParam T - The literal {@link RecipeDefinition} type inferred from `recipe`.\n * @param recipe - The recipe definition to register.\n * @returns The same `recipe`, typed as `T`.\n *\n * @example\n * ```ts\n * const button = defineRecipe({\n * base: { display: \"inline-flex\" },\n * variants: {\n * size: { sm: { height: \"32px\" }, md: { height: \"40px\" } },\n * tone: { solid: \"btn-solid\", ghost: \"btn-ghost\" },\n * },\n * defaultVariants: { size: \"md\", tone: \"solid\" },\n * });\n *\n * button.variants?.size; // { sm: ...; md: ... } — not Record<string, ...>\n * ```\n */\nexport function defineRecipe<const T extends RecipeDefinition>(recipe: T): T {\n return recipe;\n}\n","import type { SemanticTokens } from \"@/types\";\n\nconst REFERENCE_PATTERN = /^\\{(.+)\\}$/;\n\n/**\n * If value is a \"{colors.brand.500}\"-style reference string, returns\n * the raw dotted path (\"colors.brand.500\"). Otherwise returns null.\n */\nfunction extractReferencePath(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const match = value.match(REFERENCE_PATTERN);\n return match ? match[1] : undefined;\n}\n\n/**\n * Resolves a dotted path against an object tree. Returns undefined\n * if any segment doesn't exist.\n */\nfunction resolvePath(tree: unknown, path: string): unknown {\n const segments = path.split(\".\");\n let current: unknown = tree;\n\n for (const segment of segments) {\n if (current === null || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n\n return current;\n}\n\n/**\n * Given a resolved semantic-token node (shape: { value: ColorModeValue }),\n * returns the reference string(s) its value points to, if any — i.e.\n * the next hop(s) in a semantic->semantic chain. Non-reference\n * (literal) values return an empty array — the chain ends there.\n */\nfunction nextReferences(node: unknown): string[] {\n if (node === null || typeof node !== \"object\" || !(\"value\" in node)) {\n return [];\n }\n\n const colorModeValue = (node as { value: unknown }).value;\n\n if (colorModeValue === null || typeof colorModeValue !== \"object\") {\n return [];\n }\n\n const cmv = colorModeValue as Record<string, unknown>;\n\n if (cmv.sameForBothModes === true) {\n const ref = extractReferencePath(cmv.value);\n return ref ? [ref] : [];\n }\n\n const refs: string[] = [];\n const lightRef = extractReferencePath(cmv.light);\n const darkRef = extractReferencePath(cmv.dark);\n if (lightRef) refs.push(lightRef);\n if (darkRef) refs.push(darkRef);\n return refs;\n}\n\nexport interface CycleValidationResult {\n valid: boolean;\n cyclePath?: string[];\n}\n\n/**\n * Walks every semantic token's reference chain looking for a\n * semantic->semantic cycle. Reference *existence* (does the path\n * resolve at all) is validated separately at the type level via\n * ValidateSemanticTokenSection — this function only detects cycles\n * among references that do resolve to another semantic token.\n *\n * A reference that resolves to nothing (dangling) or to a primitive\n * token is a dead end for cycle-walking purposes here, not an error\n * this function raises — that's the type-level existence check's job.\n */\nexport function validateNoCycles(\n semanticTokens: SemanticTokens,\n): CycleValidationResult {\n function walk(path: string, visited: string[]): CycleValidationResult {\n if (visited.includes(path)) {\n return { valid: false, cyclePath: [...visited, path] };\n }\n\n const node = resolvePath(semanticTokens, path);\n const refs = nextReferences(node);\n\n for (const ref of refs) {\n const result = walk(ref, [...visited, path]);\n if (!result.valid) return result;\n }\n\n return { valid: true };\n }\n\n function collectPaths(tree: unknown, prefix: string[] = []): string[][] {\n if (tree === null || typeof tree !== \"object\") return [];\n\n const entries = Object.entries(tree as Record<string, unknown>);\n const paths: string[][] = [];\n\n for (const [key, value] of entries) {\n const currentPath = [...prefix, key];\n\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"value\" in (value as Record<string, unknown>)\n ) {\n paths.push(currentPath);\n } else {\n paths.push(...collectPaths(value, currentPath));\n }\n }\n\n return paths;\n }\n\n const allLeafPaths = collectPaths(semanticTokens);\n\n for (const pathSegments of allLeafPaths) {\n const path = pathSegments.join(\".\");\n const result = walk(path, []);\n if (!result.valid) return result;\n }\n\n return { valid: true };\n}\n\n/**\n * Throws a descriptive error if a semantic->semantic cycle is found.\n * Intended to be called from defineTheme/extendTheme.\n */\nexport function assertNoCycles(semanticTokens: SemanticTokens): void {\n const result = validateNoCycles(semanticTokens);\n\n if (!result.valid) {\n throw new Error(\n `Kreativ UI: circular semantic token reference detected: ${result.cyclePath?.join(\" -> \")}`,\n );\n }\n}\n","import type { Theme } from \"@/types\";\nimport type { ValidateTheme } from \"../validate/theme\";\nimport { assertNoCycles } from \"../runtime/validateCycles\";\n\n/**\n * Defines a Kreativ UI theme.\n *\n * Type-safe boundary for creating themes while preserving the exact\n * structure and types of the supplied theme. Does not merge with the\n * default theme or mutate the provided object — extension/resolution\n * are handled separately by extendTheme.\n *\n * `T & ValidateTheme<T>` is what actually enforces validation at the\n * call site: ValidateTheme<T> resolves to `unknown` (a no-op) when\n * every section passes, or a section-named `{ tokens: Invalid<...> }`\n * / `{ semanticTokens: Invalid<...> }` / etc. object when a section\n * fails. Intersecting that onto the parameter type means a failing\n * theme produces a real compile error naming the failing section and\n * message, not just a generic \"not assignable to Theme\".\n *\n * Reference *existence* (does \"{colors.brand.500}\" resolve to a real\n * token) is checked at compile time via ValidateSemanticTokenSection,\n * as part of ValidateTheme above. Reference *cycles* (semantic token\n * A -> B -> A) can't be reliably caught at the type level (hit TS\n * inference edge cases in recursive conditional types), so they're\n * checked here at call time instead, via assertNoCycles.\n */\nexport function defineTheme<T extends Theme>(theme: T & ValidateTheme<T>): T {\n assertNoCycles(theme.semanticTokens);\n return theme;\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/define/token.ts","../src/define/semanticToken.ts","../src/define/size.ts","../src/define/typography.ts","../src/define/recipe.ts","../src/runtime/validateCycles.ts","../src/define/theme.ts","../src/provider/PersistMode.tsx"],"names":[],"mappings":";;;;;;AAEO,SAAS,YAAkC,KAAA,EAAU;AAC1D,EAAA,OAAO;AAAA,IACL;AAAA,GACF;AACF;AAEO,SAAS,aAAmD,MAAA,EAAW;AAC5E,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,KAAK,MAAM,CAAC,GAAA,EAAK,WAAA,CAAY,KAAK,CAAC,CAAC;AAAA,GACxE;AAGF;;;ACEO,SAAS,mBAAA,CACd,cACA,IAAA,EACkB;AAClB,EAAA,IAAI,SAAS,MAAA,EAAW;AACtB,IAAA,OAAO;AAAA,MACL,KAAA,EAAO;AAAA,QACL,gBAAA,EAAkB,IAAA;AAAA,QAClB,KAAA,EAAO;AAAA;AACT,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO;AAAA,MACL,gBAAA,EAAkB,KAAA;AAAA,MAClB,KAAA,EAAO,YAAA;AAAA,MACP;AAAA;AACF,GACF;AACF;AAIO,SAAS,qBAGd,MAAA,EASA;AACA,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAAA,MAC3C,GAAA;AAAA,MACA,UAAU,IAAA,IACV,OAAO,KAAA,KAAU,QAAA,IACjB,WAAW,KAAA,IACX,MAAA,IAAU,KAAA,GACN,mBAAA,CAAoB,MAAM,KAAA,EAAO,KAAA,CAAM,IAAI,CAAA,GAC3C,oBAAoB,KAAmB;AAAA,KAC5C;AAAA,GACH;AACF;;;AC9DO,SAAS,WAAsC,IAAA,EAAY;AAChE,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,YAAuC,KAAA,EAAa;AAClE,EAAA,OAAO,KAAA;AACT;;;ACNO,SAAS,iBAA6C,UAAA,EAAkB;AAC7E,EAAA,OAAO,UAAA;AACT;;;ACwBO,SAAS,aAA+C,MAAA,EAAc;AAC3E,EAAA,OAAO,MAAA;AACT;;;AC5BA,IAAM,iBAAA,GAAoB,YAAA;AAM1B,SAAS,qBAAqB,KAAA,EAAoC;AAChE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,MAAA;AACtC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,iBAAiB,CAAA;AAC3C,EAAA,OAAO,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,GAAI,MAAA;AAC5B;AAMA,SAAS,WAAA,CAAY,MAAe,IAAA,EAAuB;AACzD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC/B,EAAA,IAAI,OAAA,GAAmB,IAAA;AAEvB,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,OAAA,KAAY,IAAA,IAAQ,OAAO,OAAA,KAAY,UAAU,OAAO,MAAA;AAC5D,IAAA,OAAA,GAAW,QAAoC,OAAO,CAAA;AAAA,EACxD;AAEA,EAAA,OAAO,OAAA;AACT;AAQA,SAAS,eAAe,IAAA,EAAyB;AAC/C,EAAA,IAAI,SAAS,IAAA,IAAQ,OAAO,SAAS,QAAA,IAAY,EAAE,WAAW,IAAA,CAAA,EAAO;AACnE,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,iBAAkB,IAAA,CAA4B,KAAA;AAEpD,EAAA,IAAI,cAAA,KAAmB,IAAA,IAAQ,OAAO,cAAA,KAAmB,QAAA,EAAU;AACjE,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,GAAA,GAAM,cAAA;AAEZ,EAAA,IAAI,GAAA,CAAI,qBAAqB,IAAA,EAAM;AACjC,IAAA,MAAM,GAAA,GAAM,oBAAA,CAAqB,GAAA,CAAI,KAAK,CAAA;AAC1C,IAAA,OAAO,GAAA,GAAM,CAAC,GAAG,CAAA,GAAI,EAAC;AAAA,EACxB;AAEA,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,GAAA,CAAI,KAAK,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,GAAA,CAAI,IAAI,CAAA;AAC7C,EAAA,IAAI,QAAA,EAAU,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAChC,EAAA,IAAI,OAAA,EAAS,IAAA,CAAK,IAAA,CAAK,OAAO,CAAA;AAC9B,EAAA,OAAO,IAAA;AACT;AAkBO,SAAS,iBACd,cAAA,EACuB;AACvB,EAAA,SAAS,IAAA,CAAK,MAAc,OAAA,EAA0C;AACpE,IAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG;AAC1B,MAAA,OAAO,EAAE,OAAO,KAAA,EAAO,SAAA,EAAW,CAAC,GAAG,OAAA,EAAS,IAAI,CAAA,EAAE;AAAA,IACvD;AAEA,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,cAAA,EAAgB,IAAI,CAAA;AAC7C,IAAA,MAAM,IAAA,GAAO,eAAe,IAAI,CAAA;AAEhC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,SAAS,IAAA,CAAK,GAAA,EAAK,CAAC,GAAG,OAAA,EAAS,IAAI,CAAC,CAAA;AAC3C,MAAA,IAAI,CAAC,MAAA,CAAO,KAAA,EAAO,OAAO,MAAA;AAAA,IAC5B;AAEA,IAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AAAA,EACvB;AAEA,EAAA,SAAS,YAAA,CAAa,IAAA,EAAe,MAAA,GAAmB,EAAC,EAAe;AACtE,IAAA,IAAI,SAAS,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,SAAiB,EAAC;AAEvD,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,IAA+B,CAAA;AAC9D,IAAA,MAAM,QAAoB,EAAC;AAE3B,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,OAAA,EAAS;AAClC,MAAA,MAAM,WAAA,GAAc,CAAC,GAAG,MAAA,EAAQ,GAAG,CAAA;AAEnC,MAAA,IACE,UAAU,IAAA,IACV,OAAO,KAAA,KAAU,QAAA,IACjB,WAAY,KAAA,EACZ;AACA,QAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AAAA,MACxB,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,IAAA,CAAK,GAAG,YAAA,CAAa,KAAA,EAAO,WAAW,CAAC,CAAA;AAAA,MAChD;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAA,GAAe,aAAa,cAAc,CAAA;AAEhD,EAAA,KAAA,MAAW,gBAAgB,YAAA,EAAc;AACvC,IAAA,MAAM,IAAA,GAAO,YAAA,CAAa,IAAA,CAAK,GAAG,CAAA;AAClC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,EAAM,EAAE,CAAA;AAC5B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,EAAO,OAAO,MAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACvB;AAMO,SAAS,eAAe,cAAA,EAAsC;AACnE,EAAA,MAAM,MAAA,GAAS,iBAAiB,cAAc,CAAA;AAE9C,EAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACjB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wDAAA,EAA2D,MAAA,CAAO,SAAA,EAAW,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,KAC3F;AAAA,EACF;AACF;;;ACpHO,SAAS,YAA6B,KAAA,EAAgC;AAC3E,EAAA,cAAA,CAAe,MAAM,cAAc,CAAA;AACnC,EAAA,OAAO,KAAA;AACT;;;ACxBO,SAAS,WAAA,CAAY,EAAE,UAAA,EAAW,EAA2B;AAClE,EAAA,uBAAA,CAAwB,UAAU,CAAA;AAClC,EAAA,OAAO,IAAA;AACT","file":"index.js","sourcesContent":["import type { TokenValue } from \"@/types\";\n\nexport function defineToken<T extends TokenValue>(value: T) {\n return {\n value,\n };\n}\n\nexport function defineTokens<T extends Record<string, TokenValue>>(tokens: T) {\n return Object.fromEntries(\n Object.entries(tokens).map(([key, value]) => [key, defineToken(value)]),\n ) as {\n [K in keyof T]: ReturnType<typeof defineToken<T[K]>>;\n };\n}\n","import type { SemanticToken, TokenValue } from \"@/types\";\n\n/**\n * Defines a semantic token that shares a single value across both\n * light and dark modes (the explicit sameForBothModes shorthand).\n */\nexport function defineSemanticToken<T extends TokenValue>(\n value: T,\n): SemanticToken<T>;\n/**\n * Defines a semantic token with distinct light and dark values.\n */\nexport function defineSemanticToken<T extends TokenValue>(\n light: T,\n dark: T,\n): SemanticToken<T>;\nexport function defineSemanticToken<T extends TokenValue>(\n lightOrValue: T,\n dark?: T,\n): SemanticToken<T> {\n if (dark === undefined) {\n return {\n value: {\n sameForBothModes: true,\n value: lightOrValue,\n },\n };\n }\n\n return {\n value: {\n sameForBothModes: false,\n light: lightOrValue,\n dark,\n },\n };\n}\n\ntype SemanticTokenInput<T extends TokenValue> = T | { light: T; dark: T };\n\nexport function defineSemanticTokens<\n T extends Record<string, SemanticTokenInput<TokenValue>>,\n>(\n tokens: T,\n): {\n [K in keyof T]: SemanticToken<T[K] extends { light: infer V; dark: infer _ }\n ? V extends TokenValue\n ? V\n : never\n : T[K] extends TokenValue\n ? T[K]\n : never>;\n} {\n return Object.fromEntries(\n Object.entries(tokens).map(([key, entry]) => [\n key,\n entry !== null &&\n typeof entry === \"object\" &&\n \"light\" in entry &&\n \"dark\" in entry\n ? defineSemanticToken(entry.light, entry.dark)\n : defineSemanticToken(entry as TokenValue),\n ]),\n ) as ReturnType<typeof defineSemanticTokens<T>>;\n}\n","import type { SizeScale, SizeToken } from \"@/types\";\n\nexport function defineSize<const T extends SizeToken>(size: T): T {\n return size;\n}\n\nexport function defineSizes<const T extends SizeScale>(sizes: T): T {\n return sizes;\n}\n","import type { Typography } from \"@/types\";\n\nexport function defineTypography<const T extends Typography>(typography: T): T {\n return typography;\n}\n","import type { RecipeDefinition } from \"@/types\";\n\n/**\n * Defines a recipe while preserving its literal type.\n *\n * Use this when authoring a custom recipe so TypeScript keeps the exact\n * shape you wrote (variant names, value keys, etc.) instead of widening\n * them to `string`. The returned object is the same reference you passed\n * in — this is a type-only helper with no runtime behavior.\n *\n * @typeParam T - The literal {@link RecipeDefinition} type inferred from `recipe`.\n * @param recipe - The recipe definition to register.\n * @returns The same `recipe`, typed as `T`.\n *\n * @example\n * ```ts\n * const button = defineRecipe({\n * base: { display: \"inline-flex\" },\n * variants: {\n * size: { sm: { height: \"32px\" }, md: { height: \"40px\" } },\n * tone: { solid: \"btn-solid\", ghost: \"btn-ghost\" },\n * },\n * defaultVariants: { size: \"md\", tone: \"solid\" },\n * });\n *\n * button.variants?.size; // { sm: ...; md: ... } — not Record<string, ...>\n * ```\n */\nexport function defineRecipe<const T extends RecipeDefinition>(recipe: T): T {\n return recipe;\n}\n","import type { SemanticTokens } from \"@/types\";\n\nconst REFERENCE_PATTERN = /^\\{(.+)\\}$/;\n\n/**\n * If value is a \"{colors.brand.500}\"-style reference string, returns\n * the raw dotted path (\"colors.brand.500\"). Otherwise returns null.\n */\nfunction extractReferencePath(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const match = value.match(REFERENCE_PATTERN);\n return match ? match[1] : undefined;\n}\n\n/**\n * Resolves a dotted path against an object tree. Returns undefined\n * if any segment doesn't exist.\n */\nfunction resolvePath(tree: unknown, path: string): unknown {\n const segments = path.split(\".\");\n let current: unknown = tree;\n\n for (const segment of segments) {\n if (current === null || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n\n return current;\n}\n\n/**\n * Given a resolved semantic-token node (shape: { value: ColorModeValue }),\n * returns the reference string(s) its value points to, if any — i.e.\n * the next hop(s) in a semantic->semantic chain. Non-reference\n * (literal) values return an empty array — the chain ends there.\n */\nfunction nextReferences(node: unknown): string[] {\n if (node === null || typeof node !== \"object\" || !(\"value\" in node)) {\n return [];\n }\n\n const colorModeValue = (node as { value: unknown }).value;\n\n if (colorModeValue === null || typeof colorModeValue !== \"object\") {\n return [];\n }\n\n const cmv = colorModeValue as Record<string, unknown>;\n\n if (cmv.sameForBothModes === true) {\n const ref = extractReferencePath(cmv.value);\n return ref ? [ref] : [];\n }\n\n const refs: string[] = [];\n const lightRef = extractReferencePath(cmv.light);\n const darkRef = extractReferencePath(cmv.dark);\n if (lightRef) refs.push(lightRef);\n if (darkRef) refs.push(darkRef);\n return refs;\n}\n\nexport interface CycleValidationResult {\n valid: boolean;\n cyclePath?: string[];\n}\n\n/**\n * Walks every semantic token's reference chain looking for a\n * semantic->semantic cycle. Reference *existence* (does the path\n * resolve at all) is validated separately at the type level via\n * ValidateSemanticTokenSection — this function only detects cycles\n * among references that do resolve to another semantic token.\n *\n * A reference that resolves to nothing (dangling) or to a primitive\n * token is a dead end for cycle-walking purposes here, not an error\n * this function raises — that's the type-level existence check's job.\n */\nexport function validateNoCycles(\n semanticTokens: SemanticTokens,\n): CycleValidationResult {\n function walk(path: string, visited: string[]): CycleValidationResult {\n if (visited.includes(path)) {\n return { valid: false, cyclePath: [...visited, path] };\n }\n\n const node = resolvePath(semanticTokens, path);\n const refs = nextReferences(node);\n\n for (const ref of refs) {\n const result = walk(ref, [...visited, path]);\n if (!result.valid) return result;\n }\n\n return { valid: true };\n }\n\n function collectPaths(tree: unknown, prefix: string[] = []): string[][] {\n if (tree === null || typeof tree !== \"object\") return [];\n\n const entries = Object.entries(tree as Record<string, unknown>);\n const paths: string[][] = [];\n\n for (const [key, value] of entries) {\n const currentPath = [...prefix, key];\n\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"value\" in (value as Record<string, unknown>)\n ) {\n paths.push(currentPath);\n } else {\n paths.push(...collectPaths(value, currentPath));\n }\n }\n\n return paths;\n }\n\n const allLeafPaths = collectPaths(semanticTokens);\n\n for (const pathSegments of allLeafPaths) {\n const path = pathSegments.join(\".\");\n const result = walk(path, []);\n if (!result.valid) return result;\n }\n\n return { valid: true };\n}\n\n/**\n * Throws a descriptive error if a semantic->semantic cycle is found.\n * Intended to be called from defineTheme/extendTheme.\n */\nexport function assertNoCycles(semanticTokens: SemanticTokens): void {\n const result = validateNoCycles(semanticTokens);\n\n if (!result.valid) {\n throw new Error(\n `Kreativ UI: circular semantic token reference detected: ${result.cyclePath?.join(\" -> \")}`,\n );\n }\n}\n","import type { Theme } from \"@/types\";\nimport type { ValidateTheme } from \"../validate/theme\";\nimport { assertNoCycles } from \"../runtime/validateCycles\";\n\n/**\n * Defines a Kreativ UI theme.\n *\n * Type-safe boundary for creating themes while preserving the exact\n * structure and types of the supplied theme. Does not merge with the\n * default theme or mutate the provided object — extension/resolution\n * are handled separately by extendTheme.\n *\n * `T & ValidateTheme<T>` is what actually enforces validation at the\n * call site: ValidateTheme<T> resolves to `unknown` (a no-op) when\n * every section passes, or a section-named `{ tokens: Invalid<...> }`\n * / `{ semanticTokens: Invalid<...> }` / etc. object when a section\n * fails. Intersecting that onto the parameter type means a failing\n * theme produces a real compile error naming the failing section and\n * message, not just a generic \"not assignable to Theme\".\n *\n * Reference *existence* (does \"{colors.brand.500}\" resolve to a real\n * token) is checked at compile time via ValidateSemanticTokenSection,\n * as part of ValidateTheme above. Reference *cycles* (semantic token\n * A -> B -> A) can't be reliably caught at the type level (hit TS\n * inference edge cases in recursive conditional types), so they're\n * checked here at call time instead, via assertNoCycles.\n */\nexport function defineTheme<T extends Theme>(theme: T & ValidateTheme<T>): T {\n assertNoCycles(theme.semanticTokens);\n return theme;\n}\n\n","import { useThemeModePersistence } from \"@/hooks/useThemeModePersistence\";\r\n\r\nexport interface PersistModeProps {\r\n storageKey?: string;\r\n}\r\n\r\nexport function PersistMode({ storageKey }: PersistModeProps): null {\r\n useThemeModePersistence(storageKey);\r\n return null;\r\n}\r\n"]}
|
package/package.json
CHANGED
package/dist/chunk-5CYSF7C3.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
|
|
3
|
-
// src/provider/ThemeContext.tsx
|
|
4
|
-
var ThemeContext = createContext(null);
|
|
5
|
-
|
|
6
|
-
// src/utils/assertProviderContext.ts
|
|
7
|
-
function assertProviderContext(ctx, hookName, providerName, packageName = "kreativ-core") {
|
|
8
|
-
if (ctx == null) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
`[${packageName}] ${hookName}() must be used within a <${providerName}>. Did you forget to wrap your app with <${providerName}>? import { ${providerName} } from '${packageName}';`
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// src/provider/useTheme.ts
|
|
16
|
-
function useTheme() {
|
|
17
|
-
const ctx = useContext(ThemeContext);
|
|
18
|
-
assertProviderContext(ctx, "useTheme", "ThemeProvider");
|
|
19
|
-
return ctx;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export { ThemeContext, useTheme };
|
|
23
|
-
//# sourceMappingURL=chunk-5CYSF7C3.js.map
|
|
24
|
-
//# sourceMappingURL=chunk-5CYSF7C3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider/ThemeContext.tsx","../src/utils/assertProviderContext.ts","../src/provider/useTheme.ts"],"names":[],"mappings":";;;AAcO,IAAM,YAAA,GAAe,cAAwC,IAAI;;;ACRjE,SAAS,qBAAA,CACd,GAAA,EACA,QAAA,EACA,YAAA,EACA,cAAc,cAAA,EACI;AAClB,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,CAAA,EAAI,WAAW,CAAA,EAAA,EAAK,QAAQ,CAAA,0BAAA,EAA6B,YAAY,CAAA,yCAAA,EAC1B,YAAY,CAAA,YAAA,EACzC,YAAY,CAAA,SAAA,EAAY,WAAW,CAAA,EAAA;AAAA,KACnD;AAAA,EACF;AACF;;;ACbO,SAAS,QAAA,GAAW;AACzB,EAAA,MAAM,GAAA,GAAM,WAAW,YAAY,CAAA;AACnC,EAAA,qBAAA,CAAsB,GAAA,EAAK,YAAY,eAAe,CAAA;AACtD,EAAA,OAAO,GAAA;AACT","file":"chunk-5CYSF7C3.js","sourcesContent":["\"use client\";\r\n\r\nimport { createContext } from \"react\";\r\nimport type { ColorMode, Theme, ResolvedTokens } from \"@/types/theme\";\r\n\r\nexport interface ThemeContextValue {\r\n theme: Theme;\r\n mode: ColorMode;\r\n resolvedMode: \"light\" | \"dark\";\r\n setMode: (mode: ColorMode) => void;\r\n fallbackSize: string;\r\n tokens: ResolvedTokens;\r\n}\r\n\r\nexport const ThemeContext = createContext<ThemeContextValue | null>(null);\r\n","\"use client\";\r\n\r\n/**\r\n * Throws a standardized \"used outside provider\" error.\r\n * Shared across all kreativ-core hooks so the message stays consistent.\r\n */\r\nexport function assertProviderContext<T>(\r\n ctx: T | null | undefined,\r\n hookName: string,\r\n providerName: string,\r\n packageName = \"kreativ-core\",\r\n): asserts ctx is T {\r\n if (ctx == null) {\r\n throw new Error(\r\n `[${packageName}] ${hookName}() must be used within a <${providerName}>. ` +\r\n `Did you forget to wrap your app with <${providerName}>? ` +\r\n `import { ${providerName} } from '${packageName}';`,\r\n );\r\n }\r\n}\r\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { ThemeContext } from \"@/provider/ThemeContext\";\nimport { assertProviderContext } from \"@/utils/assertProviderContext\";\n\nexport function useTheme() {\n const ctx = useContext(ThemeContext);\n assertProviderContext(ctx, \"useTheme\", \"ThemeProvider\");\n return ctx;\n}\n"]}
|