@mindees/atlas 0.24.0 → 0.26.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/README.md CHANGED
@@ -41,10 +41,10 @@ The Atlas component library — MindeesNative's batteries-included UI primitives
41
41
  `animateTo` drive spring/interpolated animations on the same scene.
42
42
  - **Theming** — design tokens in two tiers: primitive scales (`space`, `radius`,
43
43
  `fontSize`, `palette`, …) and semantic `tokens`/`Theme` (`bg`/`surface`/`text`/
44
- `primary`/…). `useTheme` returns a reactive theme driven by `useColorScheme`, so
45
- **dark mode** is a fine-grained token-set swap — only the color nodes update. The
46
- `@mindees/atlas/theme` subpath additionally exports a structural `createTheme()`
47
- with `@mindees/core` selector isolation.
44
+ `primary`/…), all on the main entry. `useTheme` returns a reactive theme driven by
45
+ `useColorScheme`, so **dark mode** is a fine-grained token-set swap — only the color
46
+ nodes update. Every built-in component reads its colors via `useTheme`, so a token
47
+ swap re-themes them automatically.
48
48
  - **List** — `@mindees/atlas/list` exports `List`, `createList`, and `computeWindow`.
49
49
  It renders a fixed pool of recycled row regions for fixed-height virtualization;
50
50
  variable-height measurement is a 🔬 research track.
@@ -57,12 +57,11 @@ The Atlas component library — MindeesNative's batteries-included UI primitives
57
57
  ## Quick start
58
58
 
59
59
  ```ts
60
- import { Button, Column, Text } from '@mindees/atlas'
60
+ import { Button, Column, Text, useTheme } from '@mindees/atlas'
61
61
  import { List } from '@mindees/atlas/list'
62
- import { createTheme } from '@mindees/atlas/theme'
63
62
 
64
- const theme = createTheme({ colors: { primary: '#2563eb' } })
65
- const primary = theme.select((tokens) => tokens.colors.primary)
63
+ const theme = useTheme() // reactive; tracks color-scheme (dark mode) automatically
64
+ const primary = () => theme().color.primary
66
65
 
67
66
  export const Screen = Column({
68
67
  gap: 12,
package/dist/index.d.ts CHANGED
@@ -12,13 +12,14 @@ import { animateTo, motion } from "./motion.js";
12
12
  import { FocusScope, FocusScopeProps, Modal, ModalProps, Toast, ToastProps } from "./overlay.js";
13
13
  import { Button, ButtonProps, Column, Image, ImageProps, InteractionState, Pressable, PressableProps, Row, ScrollView, ScrollViewProps, Spacer, SpacerProps, Stack, StackProps, Text, TextInput, TextInputProps, TextProps, View, ViewProps, usePressable } from "./primitives.js";
14
14
  import { Show, ShowProps } from "./show.js";
15
+ import { WebEnvWindow, connectWebEnvironment } from "./web-environment.js";
15
16
  import { Maturity, NotImplementedError, PackageInfo, notImplemented } from "@mindees/core";
16
17
 
17
18
  //#region src/index.d.ts
18
19
  /** The npm package name. */
19
20
  declare const name = "@mindees/atlas";
20
21
  /** The package version. All `@mindees/*` packages share one locked version line. */
21
- declare const VERSION = "0.24.0";
22
+ declare const VERSION = "0.26.0";
22
23
  /** Current maturity of this package. See the repository `STATUS.md`. */
23
24
  declare const maturity: Maturity;
24
25
  /**
@@ -28,5 +29,5 @@ declare const maturity: Maturity;
28
29
  */
29
30
  declare const info: PackageInfo;
30
31
  //#endregion
31
- export { type A11yProps, type A11yState, Accordion, type AccordionProps, type AccordionSection, ActivityIndicator, type ActivityIndicatorProps, type AsyncState, type AttachableGesture, Avatar, type AvatarProps, Badge, type BadgeProps, type BaseProps, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, Chip, type ChipProps, type ColorScheme, Column, type Counter, Divider, type DividerProps, ErrorBoundary, type ErrorBoundaryProps, type Field, FocusScope, type FocusScopeProps, type FormApi, GestureView, type GestureViewProps, Image, type ImageProps, type InteractionState, KeyboardAvoidingView, type KeyboardAvoidingViewProps, type KeyboardState, type Maturity, Modal, type ModalProps, NotImplementedError, type PackageInfo, type PersistentSignalOptions, type PlatformEnvironment, Pressable, type PressableProps, ProgressBar, type ProgressBarProps, RadioGroup, type RadioGroupProps, type RadioOption, type Reactive, type Role, Row, type SafeAreaInsets, SafeAreaView, type SafeAreaViewProps, ScrollView, type ScrollViewProps, type Segment, SegmentedControl, type SegmentedControlProps, Show, type ShowProps, type SignalStorage, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Stack, type StackProps, Stepper, type StepperProps, type StyleInput, type StyleObject, type StyleValue, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, TextInput, type TextInputProps, type TextProps, type Theme, type ThemeColors, Toast, type ToastProps, type Toggle, type UseFormOptions, VERSION, View, type ViewProps, type WindowDimensions, animateTo, duration, easing, flattenStyle, fontSize, fontWeight, getEnvironment, getTheme, info, lineHeight, maturity, motion, name, notImplemented, palette, radius, resolveStyle, setEnvironment, space, toA11yProps, toHostProps, tokens, useAsync, useColorScheme, useCounter, useDebounce, useForm, useInterval, useKeyboard, usePersistentSignal, usePressable, usePrevious, useReducedMotion, useReducer, useSafeAreaInsets, useTheme, useTimeout, useToggle, useWindowDimensions };
32
+ export { type A11yProps, type A11yState, Accordion, type AccordionProps, type AccordionSection, ActivityIndicator, type ActivityIndicatorProps, type AsyncState, type AttachableGesture, Avatar, type AvatarProps, Badge, type BadgeProps, type BaseProps, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, Chip, type ChipProps, type ColorScheme, Column, type Counter, Divider, type DividerProps, ErrorBoundary, type ErrorBoundaryProps, type Field, FocusScope, type FocusScopeProps, type FormApi, GestureView, type GestureViewProps, Image, type ImageProps, type InteractionState, KeyboardAvoidingView, type KeyboardAvoidingViewProps, type KeyboardState, type Maturity, Modal, type ModalProps, NotImplementedError, type PackageInfo, type PersistentSignalOptions, type PlatformEnvironment, Pressable, type PressableProps, ProgressBar, type ProgressBarProps, RadioGroup, type RadioGroupProps, type RadioOption, type Reactive, type Role, Row, type SafeAreaInsets, SafeAreaView, type SafeAreaViewProps, ScrollView, type ScrollViewProps, type Segment, SegmentedControl, type SegmentedControlProps, Show, type ShowProps, type SignalStorage, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Stack, type StackProps, Stepper, type StepperProps, type StyleInput, type StyleObject, type StyleValue, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, TextInput, type TextInputProps, type TextProps, type Theme, type ThemeColors, Toast, type ToastProps, type Toggle, type UseFormOptions, VERSION, View, type ViewProps, type WebEnvWindow, type WindowDimensions, animateTo, connectWebEnvironment, duration, easing, flattenStyle, fontSize, fontWeight, getEnvironment, getTheme, info, lineHeight, maturity, motion, name, notImplemented, palette, radius, resolveStyle, setEnvironment, space, toA11yProps, toHostProps, tokens, useAsync, useColorScheme, useCounter, useDebounce, useForm, useInterval, useKeyboard, usePersistentSignal, usePressable, usePrevious, useReducedMotion, useReducer, useSafeAreaInsets, useTheme, useTimeout, useToggle, useWindowDimensions };
32
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAea,IAAA;;cAGA,OAAA;;cAGA,QAAA,EAAU,QAAyB;;;;AAN/B;AAGjB;cAUa,IAAA,EAAM,WAAiE"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;cAea,IAAA;;cAGA,OAAA;;cAGA,QAAA,EAAU,QAAyB;AANhD;;;;AAAiB;AAAjB,cAaa,IAAA,EAAM,WAAiE"}
package/dist/index.js CHANGED
@@ -12,12 +12,13 @@ import { useAsync, useCounter, useDebounce, useInterval, usePersistentSignal, us
12
12
  import { animateTo, motion } from "./motion.js";
13
13
  import { FocusScope, Modal, Toast } from "./overlay.js";
14
14
  import { Show } from "./show.js";
15
+ import { connectWebEnvironment } from "./web-environment.js";
15
16
  import { NotImplementedError, notImplemented } from "@mindees/core";
16
17
  //#region src/index.ts
17
18
  /** The npm package name. */
18
19
  const name = "@mindees/atlas";
19
20
  /** The package version. All `@mindees/*` packages share one locked version line. */
20
- const VERSION = "0.24.0";
21
+ const VERSION = "0.26.0";
21
22
  /** Current maturity of this package. See the repository `STATUS.md`. */
22
23
  const maturity = "experimental";
23
24
  /**
@@ -31,6 +32,6 @@ const info = Object.freeze({
31
32
  maturity
32
33
  });
33
34
  //#endregion
34
- export { Accordion, ActivityIndicator, Avatar, Badge, Button, Card, Checkbox, Chip, Column, Divider, ErrorBoundary, FocusScope, GestureView, Image, KeyboardAvoidingView, Modal, NotImplementedError, Pressable, ProgressBar, RadioGroup, Row, SafeAreaView, ScrollView, SegmentedControl, Show, Skeleton, Spacer, Stack, Stepper, Switch, Tabs, Text, TextInput, Toast, VERSION, View, animateTo, duration, easing, flattenStyle, fontSize, fontWeight, getEnvironment, getTheme, info, lineHeight, maturity, motion, name, notImplemented, palette, radius, resolveStyle, setEnvironment, space, toA11yProps, toHostProps, tokens, useAsync, useColorScheme, useCounter, useDebounce, useForm, useInterval, useKeyboard, usePersistentSignal, usePressable, usePrevious, useReducedMotion, useReducer, useSafeAreaInsets, useTheme, useTimeout, useToggle, useWindowDimensions };
35
+ export { Accordion, ActivityIndicator, Avatar, Badge, Button, Card, Checkbox, Chip, Column, Divider, ErrorBoundary, FocusScope, GestureView, Image, KeyboardAvoidingView, Modal, NotImplementedError, Pressable, ProgressBar, RadioGroup, Row, SafeAreaView, ScrollView, SegmentedControl, Show, Skeleton, Spacer, Stack, Stepper, Switch, Tabs, Text, TextInput, Toast, VERSION, View, animateTo, connectWebEnvironment, duration, easing, flattenStyle, fontSize, fontWeight, getEnvironment, getTheme, info, lineHeight, maturity, motion, name, notImplemented, palette, radius, resolveStyle, setEnvironment, space, toA11yProps, toHostProps, tokens, useAsync, useColorScheme, useCounter, useDebounce, useForm, useInterval, useKeyboard, usePersistentSignal, usePressable, usePrevious, useReducedMotion, useReducer, useSafeAreaInsets, useTheme, useTimeout, useToggle, useWindowDimensions };
35
36
 
36
37
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@mindees/atlas` (Atlas) — accessible, signals-native UI primitives. Function components\n * over `@mindees/core`'s `createElement` that return renderer-agnostic `MindeesNode` trees:\n * web rendering is real via the Helix DOM backend; native is a labeled 🔬 research track (the\n * same serializable tree, interpreted by a native host later). A curated cross-platform\n * `StyleObject`, typed accessibility, and a structural theme (on the `@mindees/atlas/theme`\n * subpath). The virtualized recycling `List` is on the `@mindees/atlas/list` subpath.\n *\n * @module\n */\n\nimport type { Maturity, PackageInfo } from '@mindees/core'\nimport { NotImplementedError, notImplemented } from '@mindees/core'\n\n/** The npm package name. */\nexport const name = '@mindees/atlas'\n\n/** The package version. All `@mindees/*` packages share one locked version line. */\nexport const VERSION = '0.24.0'\n\n/** Current maturity of this package. See the repository `STATUS.md`. */\nexport const maturity: Maturity = 'experimental'\n\n/**\n * Static identity + maturity metadata for this package. Frozen so the\n * self-reported identity tooling introspects cannot be mutated at runtime,\n * matching the `readonly` fields of {@link PackageInfo}.\n */\nexport const info: PackageInfo = Object.freeze({ name, version: VERSION, maturity })\n\nexport { type A11yProps, type A11yState, type Role, toA11yProps } from './a11y'\nexport {\n Accordion,\n type AccordionProps,\n type AccordionSection,\n ActivityIndicator,\n type ActivityIndicatorProps,\n Avatar,\n type AvatarProps,\n Badge,\n type BadgeProps,\n Card,\n type CardProps,\n Checkbox,\n type CheckboxProps,\n Chip,\n type ChipProps,\n Divider,\n type DividerProps,\n KeyboardAvoidingView,\n type KeyboardAvoidingViewProps,\n ProgressBar,\n type ProgressBarProps,\n RadioGroup,\n type RadioGroupProps,\n type RadioOption,\n SafeAreaView,\n type SafeAreaViewProps,\n type Segment,\n SegmentedControl,\n type SegmentedControlProps,\n Skeleton,\n type SkeletonProps,\n Stepper,\n type StepperProps,\n Switch,\n type SwitchProps,\n type TabItem,\n Tabs,\n type TabsProps,\n} from './components'\nexport {\n type ColorScheme,\n getEnvironment,\n type KeyboardState,\n type PlatformEnvironment,\n type SafeAreaInsets,\n setEnvironment,\n useColorScheme,\n useKeyboard,\n useReducedMotion,\n useSafeAreaInsets,\n useWindowDimensions,\n type WindowDimensions,\n} from './environment'\nexport { ErrorBoundary, type ErrorBoundaryProps } from './error-boundary'\nexport { type Field, type FormApi, type UseFormOptions, useForm } from './form'\nexport { type AttachableGesture, GestureView, type GestureViewProps } from './gesture'\nexport {\n type AsyncState,\n type Counter,\n type PersistentSignalOptions,\n type SignalStorage,\n type Toggle,\n useAsync,\n useCounter,\n useDebounce,\n useInterval,\n usePersistentSignal,\n usePrevious,\n useReducer,\n useTimeout,\n useToggle,\n} from './hooks'\nexport { type BaseProps, type Reactive, resolveStyle, toHostProps } from './host'\nexport { animateTo, motion } from './motion'\nexport {\n FocusScope,\n type FocusScopeProps,\n Modal,\n type ModalProps,\n Toast,\n type ToastProps,\n} from './overlay'\nexport {\n Button,\n type ButtonProps,\n Column,\n Image,\n type ImageProps,\n type InteractionState,\n Pressable,\n type PressableProps,\n Row,\n ScrollView,\n type ScrollViewProps,\n Spacer,\n type SpacerProps,\n Stack,\n type StackProps,\n Text,\n TextInput,\n type TextInputProps,\n type TextProps,\n usePressable,\n View,\n type ViewProps,\n} from './primitives'\nexport { Show, type ShowProps } from './show'\nexport { flattenStyle, type StyleInput, type StyleObject, type StyleValue } from './style'\nexport {\n duration,\n easing,\n fontSize,\n fontWeight,\n getTheme,\n lineHeight,\n palette,\n radius,\n space,\n type Theme,\n type ThemeColors,\n tokens,\n useTheme,\n} from './tokens'\nexport type { Maturity, PackageInfo }\nexport { NotImplementedError, notImplemented }\n"],"mappings":";;;;;;;;;;;;;;;;;AAeA,MAAa,OAAO;;AAGpB,MAAa,UAAU;;AAGvB,MAAa,WAAqB;;;;;;AAOlC,MAAa,OAAoB,OAAO,OAAO;CAAE;CAAM,SAAS;CAAS;AAAS,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@mindees/atlas` (Atlas) — accessible, signals-native UI primitives. Function components\n * over `@mindees/core`'s `createElement` that return renderer-agnostic `MindeesNode` trees:\n * web rendering is real via the Helix DOM backend; native is a labeled 🔬 research track (the\n * same serializable tree, interpreted by a native host later). A curated cross-platform\n * `StyleObject`, typed accessibility, and design-token theming (`useTheme`/`tokens`, on the main entry).\n * The virtualized recycling `List` is on the `@mindees/atlas/list` subpath.\n *\n * @module\n */\n\nimport type { Maturity, PackageInfo } from '@mindees/core'\nimport { NotImplementedError, notImplemented } from '@mindees/core'\n\n/** The npm package name. */\nexport const name = '@mindees/atlas'\n\n/** The package version. All `@mindees/*` packages share one locked version line. */\nexport const VERSION = '0.26.0'\n\n/** Current maturity of this package. See the repository `STATUS.md`. */\nexport const maturity: Maturity = 'experimental'\n\n/**\n * Static identity + maturity metadata for this package. Frozen so the\n * self-reported identity tooling introspects cannot be mutated at runtime,\n * matching the `readonly` fields of {@link PackageInfo}.\n */\nexport const info: PackageInfo = Object.freeze({ name, version: VERSION, maturity })\n\nexport { type A11yProps, type A11yState, type Role, toA11yProps } from './a11y'\nexport {\n Accordion,\n type AccordionProps,\n type AccordionSection,\n ActivityIndicator,\n type ActivityIndicatorProps,\n Avatar,\n type AvatarProps,\n Badge,\n type BadgeProps,\n Card,\n type CardProps,\n Checkbox,\n type CheckboxProps,\n Chip,\n type ChipProps,\n Divider,\n type DividerProps,\n KeyboardAvoidingView,\n type KeyboardAvoidingViewProps,\n ProgressBar,\n type ProgressBarProps,\n RadioGroup,\n type RadioGroupProps,\n type RadioOption,\n SafeAreaView,\n type SafeAreaViewProps,\n type Segment,\n SegmentedControl,\n type SegmentedControlProps,\n Skeleton,\n type SkeletonProps,\n Stepper,\n type StepperProps,\n Switch,\n type SwitchProps,\n type TabItem,\n Tabs,\n type TabsProps,\n} from './components'\nexport {\n type ColorScheme,\n getEnvironment,\n type KeyboardState,\n type PlatformEnvironment,\n type SafeAreaInsets,\n setEnvironment,\n useColorScheme,\n useKeyboard,\n useReducedMotion,\n useSafeAreaInsets,\n useWindowDimensions,\n type WindowDimensions,\n} from './environment'\nexport { ErrorBoundary, type ErrorBoundaryProps } from './error-boundary'\nexport { type Field, type FormApi, type UseFormOptions, useForm } from './form'\nexport { type AttachableGesture, GestureView, type GestureViewProps } from './gesture'\nexport {\n type AsyncState,\n type Counter,\n type PersistentSignalOptions,\n type SignalStorage,\n type Toggle,\n useAsync,\n useCounter,\n useDebounce,\n useInterval,\n usePersistentSignal,\n usePrevious,\n useReducer,\n useTimeout,\n useToggle,\n} from './hooks'\nexport { type BaseProps, type Reactive, resolveStyle, toHostProps } from './host'\nexport { animateTo, motion } from './motion'\nexport {\n FocusScope,\n type FocusScopeProps,\n Modal,\n type ModalProps,\n Toast,\n type ToastProps,\n} from './overlay'\nexport {\n Button,\n type ButtonProps,\n Column,\n Image,\n type ImageProps,\n type InteractionState,\n Pressable,\n type PressableProps,\n Row,\n ScrollView,\n type ScrollViewProps,\n Spacer,\n type SpacerProps,\n Stack,\n type StackProps,\n Text,\n TextInput,\n type TextInputProps,\n type TextProps,\n usePressable,\n View,\n type ViewProps,\n} from './primitives'\nexport { Show, type ShowProps } from './show'\nexport { flattenStyle, type StyleInput, type StyleObject, type StyleValue } from './style'\nexport {\n duration,\n easing,\n fontSize,\n fontWeight,\n getTheme,\n lineHeight,\n palette,\n radius,\n space,\n type Theme,\n type ThemeColors,\n tokens,\n useTheme,\n} from './tokens'\nexport { connectWebEnvironment, type WebEnvWindow } from './web-environment'\nexport type { Maturity, PackageInfo }\nexport { NotImplementedError, notImplemented }\n"],"mappings":";;;;;;;;;;;;;;;;;;AAeA,MAAa,OAAO;;AAGpB,MAAa,UAAU;;AAGvB,MAAa,WAAqB;;;;;;AAOlC,MAAa,OAAoB,OAAO,OAAO;CAAE;CAAM,SAAS;CAAS;AAAS,CAAC"}
@@ -0,0 +1,60 @@
1
+ //#region src/web-environment.d.ts
2
+ /**
3
+ * Web adapter for the platform environment.
4
+ *
5
+ * Wires the browser's live signals — color scheme, reduced motion, window size, the soft keyboard (via
6
+ * `visualViewport`), and CSS `env(safe-area-inset-*)` — into {@link setEnvironment}, so the device hooks
7
+ * (`useColorScheme`, `useWindowDimensions`, `useSafeAreaInsets`, `useKeyboard`, `useReducedMotion`) are
8
+ * LIVE on the web target with zero configuration. Without this, those signals keep their inert defaults
9
+ * (0×0, light, no insets, keyboard hidden) on web.
10
+ *
11
+ * SSR-safe: a no-op when there is no DOM. Call once at startup — the `create` template wires it into
12
+ * `main.tsx`. Returns a `disconnect()` that removes every listener and the probe element.
13
+ *
14
+ * @module
15
+ */
16
+ interface MediaQueryLike {
17
+ readonly matches: boolean;
18
+ addEventListener(type: 'change', listener: () => void): void;
19
+ removeEventListener(type: 'change', listener: () => void): void;
20
+ }
21
+ interface VisualViewportLike {
22
+ readonly height: number;
23
+ readonly offsetTop: number;
24
+ addEventListener(type: string, listener: () => void): void;
25
+ removeEventListener(type: string, listener: () => void): void;
26
+ }
27
+ interface ProbeLike {
28
+ style: {
29
+ cssText: string;
30
+ };
31
+ remove(): void;
32
+ }
33
+ interface DocumentLike {
34
+ body: {
35
+ appendChild(node: ProbeLike): void;
36
+ } | null;
37
+ createElement(tag: string): ProbeLike;
38
+ }
39
+ /** The subset of `Window` the adapter uses. */
40
+ interface WebEnvWindow {
41
+ readonly innerWidth: number;
42
+ readonly innerHeight: number;
43
+ readonly devicePixelRatio?: number;
44
+ readonly visualViewport?: VisualViewportLike | null;
45
+ readonly document?: DocumentLike;
46
+ matchMedia(query: string): MediaQueryLike;
47
+ getComputedStyle?(el: ProbeLike): {
48
+ getPropertyValue(prop: string): string;
49
+ };
50
+ addEventListener(type: string, listener: () => void): void;
51
+ removeEventListener(type: string, listener: () => void): void;
52
+ }
53
+ /**
54
+ * Connect the browser environment to the reactive device hooks. Pass a `window` (defaults to the global).
55
+ * Returns a `disconnect()`.
56
+ */
57
+ declare function connectWebEnvironment(win?: WebEnvWindow): () => void;
58
+ //#endregion
59
+ export { WebEnvWindow, connectWebEnvironment };
60
+ //# sourceMappingURL=web-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-environment.d.ts","names":[],"sources":["../src/web-environment.ts"],"mappings":";;;;;;;;;;;;;;AAsB0D;UAHhD,cAAA;EAAA,SACC,OAAA;EACT,gBAAA,CAAiB,IAAA,YAAgB,QAAA;EACjC,mBAAA,CAAoB,IAAA,YAAgB,QAAA;AAAA;AAAA,UAE5B,kBAAA;EAAA,SACC,MAAA;EAAA,SACA,SAAA;EACT,gBAAA,CAAiB,IAAA,UAAc,QAAA;EAC/B,mBAAA,CAAoB,IAAA,UAAc,QAAA;AAAA;AAAA,UAE1B,SAAA;EACR,KAAA;IAAS,OAAA;EAAA;EACT,MAAA;AAAA;AAAA,UAEQ,YAAA;EACR,IAAA;IAAQ,WAAA,CAAY,IAAA,EAAM,SAAA;EAAA;EAC1B,aAAA,CAAc,GAAA,WAAc,SAAS;AAAA;AAJ/B;AAAA,UAOS,YAAA;EAAA,SACN,UAAA;EAAA,SACA,WAAA;EAAA,SACA,gBAAA;EAAA,SACA,cAAA,GAAiB,kBAAA;EAAA,SACjB,QAAA,GAAW,YAAA;EACpB,UAAA,CAAW,KAAA,WAAgB,cAAA;EAC3B,gBAAA,EAAkB,EAAA,EAAI,SAAA;IAAc,gBAAA,CAAiB,IAAA;EAAA;EACrD,gBAAA,CAAiB,IAAA,UAAc,QAAA;EAC/B,mBAAA,CAAoB,IAAA,UAAc,QAAA;AAAA;;;;;iBAUpB,qBAAA,CAAsB,GAAkB,GAAZ,YAAY"}
@@ -0,0 +1,98 @@
1
+ import { setEnvironment } from "./environment.js";
2
+ //#region src/web-environment.ts
3
+ /**
4
+ * Web adapter for the platform environment.
5
+ *
6
+ * Wires the browser's live signals — color scheme, reduced motion, window size, the soft keyboard (via
7
+ * `visualViewport`), and CSS `env(safe-area-inset-*)` — into {@link setEnvironment}, so the device hooks
8
+ * (`useColorScheme`, `useWindowDimensions`, `useSafeAreaInsets`, `useKeyboard`, `useReducedMotion`) are
9
+ * LIVE on the web target with zero configuration. Without this, those signals keep their inert defaults
10
+ * (0×0, light, no insets, keyboard hidden) on web.
11
+ *
12
+ * SSR-safe: a no-op when there is no DOM. Call once at startup — the `create` template wires it into
13
+ * `main.tsx`. Returns a `disconnect()` that removes every listener and the probe element.
14
+ *
15
+ * @module
16
+ */
17
+ const KEYBOARD_THRESHOLD = 80;
18
+ /**
19
+ * Connect the browser environment to the reactive device hooks. Pass a `window` (defaults to the global).
20
+ * Returns a `disconnect()`.
21
+ */
22
+ function connectWebEnvironment(win) {
23
+ const w = win ?? globalThis.window;
24
+ if (!w || typeof w.matchMedia !== "function") return () => {};
25
+ const cleanups = [];
26
+ const bindMedia = (query, apply) => {
27
+ const mq = w.matchMedia(query);
28
+ const on = () => apply(mq.matches);
29
+ on();
30
+ mq.addEventListener("change", on);
31
+ cleanups.push(() => mq.removeEventListener("change", on));
32
+ };
33
+ bindMedia("(prefers-color-scheme: dark)", (m) => setEnvironment({ colorScheme: m ? "dark" : "light" }));
34
+ bindMedia("(prefers-reduced-motion: reduce)", (m) => setEnvironment({ reducedMotion: m }));
35
+ const readWindow = () => setEnvironment({ window: {
36
+ width: w.innerWidth,
37
+ height: w.innerHeight,
38
+ scale: w.devicePixelRatio ?? 1,
39
+ fontScale: 1
40
+ } });
41
+ const doc = w.document;
42
+ let probe = null;
43
+ if (doc?.body && typeof doc.createElement === "function" && typeof w.getComputedStyle === "function") {
44
+ probe = doc.createElement("div");
45
+ probe.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";
46
+ doc.body.appendChild(probe);
47
+ cleanups.push(() => probe?.remove());
48
+ }
49
+ const readSafeArea = () => {
50
+ if (!probe || typeof w.getComputedStyle !== "function") return;
51
+ const cs = w.getComputedStyle(probe);
52
+ const px = (v) => Number.parseFloat(v) || 0;
53
+ setEnvironment({ safeAreaInsets: {
54
+ top: px(cs.getPropertyValue("padding-top")),
55
+ right: px(cs.getPropertyValue("padding-right")),
56
+ bottom: px(cs.getPropertyValue("padding-bottom")),
57
+ left: px(cs.getPropertyValue("padding-left"))
58
+ } });
59
+ };
60
+ const vv = w.visualViewport;
61
+ const readKeyboard = () => {
62
+ if (!vv) return;
63
+ const h = Math.max(0, w.innerHeight - vv.height - vv.offsetTop);
64
+ const visible = h > KEYBOARD_THRESHOLD;
65
+ setEnvironment({ keyboard: {
66
+ visible,
67
+ height: visible ? h : 0
68
+ } });
69
+ };
70
+ const onResize = () => {
71
+ readWindow();
72
+ readSafeArea();
73
+ readKeyboard();
74
+ };
75
+ onResize();
76
+ w.addEventListener("resize", onResize);
77
+ cleanups.push(() => w.removeEventListener("resize", onResize));
78
+ if (vv) {
79
+ const onViewport = () => {
80
+ readKeyboard();
81
+ readSafeArea();
82
+ };
83
+ vv.addEventListener("resize", onViewport);
84
+ vv.addEventListener("scroll", onViewport);
85
+ cleanups.push(() => {
86
+ vv.removeEventListener("resize", onViewport);
87
+ vv.removeEventListener("scroll", onViewport);
88
+ });
89
+ }
90
+ return () => {
91
+ for (const c of cleanups) c();
92
+ cleanups.length = 0;
93
+ };
94
+ }
95
+ //#endregion
96
+ export { connectWebEnvironment };
97
+
98
+ //# sourceMappingURL=web-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-environment.js","names":[],"sources":["../src/web-environment.ts"],"sourcesContent":["/**\n * Web adapter for the platform environment.\n *\n * Wires the browser's live signals — color scheme, reduced motion, window size, the soft keyboard (via\n * `visualViewport`), and CSS `env(safe-area-inset-*)` — into {@link setEnvironment}, so the device hooks\n * (`useColorScheme`, `useWindowDimensions`, `useSafeAreaInsets`, `useKeyboard`, `useReducedMotion`) are\n * LIVE on the web target with zero configuration. Without this, those signals keep their inert defaults\n * (0×0, light, no insets, keyboard hidden) on web.\n *\n * SSR-safe: a no-op when there is no DOM. Call once at startup — the `create` template wires it into\n * `main.tsx`. Returns a `disconnect()` that removes every listener and the probe element.\n *\n * @module\n */\n\nimport { setEnvironment } from './environment'\n\n// Minimal STRUCTURAL views of the DOM we touch — so this package needs no `lib.dom` in its types and\n// stays platform-neutral. A real `Window` satisfies these shapes.\ninterface MediaQueryLike {\n readonly matches: boolean\n addEventListener(type: 'change', listener: () => void): void\n removeEventListener(type: 'change', listener: () => void): void\n}\ninterface VisualViewportLike {\n readonly height: number\n readonly offsetTop: number\n addEventListener(type: string, listener: () => void): void\n removeEventListener(type: string, listener: () => void): void\n}\ninterface ProbeLike {\n style: { cssText: string }\n remove(): void\n}\ninterface DocumentLike {\n body: { appendChild(node: ProbeLike): void } | null\n createElement(tag: string): ProbeLike\n}\n/** The subset of `Window` the adapter uses. */\nexport interface WebEnvWindow {\n readonly innerWidth: number\n readonly innerHeight: number\n readonly devicePixelRatio?: number\n readonly visualViewport?: VisualViewportLike | null\n readonly document?: DocumentLike\n matchMedia(query: string): MediaQueryLike\n getComputedStyle?(el: ProbeLike): { getPropertyValue(prop: string): string }\n addEventListener(type: string, listener: () => void): void\n removeEventListener(type: string, listener: () => void): void\n}\n\n// Below this the viewport-height delta is browser chrome (URL bar), not a soft keyboard.\nconst KEYBOARD_THRESHOLD = 80\n\n/**\n * Connect the browser environment to the reactive device hooks. Pass a `window` (defaults to the global).\n * Returns a `disconnect()`.\n */\nexport function connectWebEnvironment(win?: WebEnvWindow): () => void {\n const w = win ?? (globalThis as unknown as { window?: WebEnvWindow }).window\n if (!w || typeof w.matchMedia !== 'function') return () => {} // SSR / non-DOM → inert\n\n const cleanups: Array<() => void> = []\n\n const bindMedia = (query: string, apply: (matches: boolean) => void): void => {\n const mq = w.matchMedia(query)\n const on = (): void => apply(mq.matches)\n on()\n mq.addEventListener('change', on)\n cleanups.push(() => mq.removeEventListener('change', on))\n }\n bindMedia('(prefers-color-scheme: dark)', (m) =>\n setEnvironment({ colorScheme: m ? 'dark' : 'light' }),\n )\n bindMedia('(prefers-reduced-motion: reduce)', (m) => setEnvironment({ reducedMotion: m }))\n\n const readWindow = (): void =>\n setEnvironment({\n window: {\n width: w.innerWidth,\n height: w.innerHeight,\n scale: w.devicePixelRatio ?? 1,\n fontScale: 1,\n },\n })\n\n // Safe-area insets: a hidden probe whose padding is `env(safe-area-inset-*)`; read its computed style.\n const doc = w.document\n let probe: ProbeLike | null = null\n if (\n doc?.body &&\n typeof doc.createElement === 'function' &&\n typeof w.getComputedStyle === 'function'\n ) {\n probe = doc.createElement('div')\n probe.style.cssText =\n 'position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)'\n doc.body.appendChild(probe)\n cleanups.push(() => probe?.remove())\n }\n const readSafeArea = (): void => {\n if (!probe || typeof w.getComputedStyle !== 'function') return\n const cs = w.getComputedStyle(probe)\n const px = (v: string): number => Number.parseFloat(v) || 0\n setEnvironment({\n safeAreaInsets: {\n top: px(cs.getPropertyValue('padding-top')),\n right: px(cs.getPropertyValue('padding-right')),\n bottom: px(cs.getPropertyValue('padding-bottom')),\n left: px(cs.getPropertyValue('padding-left')),\n },\n })\n }\n\n const vv = w.visualViewport\n const readKeyboard = (): void => {\n if (!vv) return\n const h = Math.max(0, w.innerHeight - vv.height - vv.offsetTop)\n const visible = h > KEYBOARD_THRESHOLD\n setEnvironment({ keyboard: { visible, height: visible ? h : 0 } })\n }\n\n const onResize = (): void => {\n readWindow()\n readSafeArea()\n readKeyboard()\n }\n onResize() // seed immediately\n w.addEventListener('resize', onResize)\n cleanups.push(() => w.removeEventListener('resize', onResize))\n\n if (vv) {\n const onViewport = (): void => {\n readKeyboard()\n readSafeArea()\n }\n vv.addEventListener('resize', onViewport)\n vv.addEventListener('scroll', onViewport)\n cleanups.push(() => {\n vv.removeEventListener('resize', onViewport)\n vv.removeEventListener('scroll', onViewport)\n })\n }\n\n return () => {\n for (const c of cleanups) c()\n cleanups.length = 0\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoDA,MAAM,qBAAqB;;;;;AAM3B,SAAgB,sBAAsB,KAAgC;CACpE,MAAM,IAAI,OAAQ,WAAoD;CACtE,IAAI,CAAC,KAAK,OAAO,EAAE,eAAe,YAAY,aAAa,CAAC;CAE5D,MAAM,WAA8B,CAAC;CAErC,MAAM,aAAa,OAAe,UAA4C;EAC5E,MAAM,KAAK,EAAE,WAAW,KAAK;EAC7B,MAAM,WAAiB,MAAM,GAAG,OAAO;EACvC,GAAG;EACH,GAAG,iBAAiB,UAAU,EAAE;EAChC,SAAS,WAAW,GAAG,oBAAoB,UAAU,EAAE,CAAC;CAC1D;CACA,UAAU,iCAAiC,MACzC,eAAe,EAAE,aAAa,IAAI,SAAS,QAAQ,CAAC,CACtD;CACA,UAAU,qCAAqC,MAAM,eAAe,EAAE,eAAe,EAAE,CAAC,CAAC;CAEzF,MAAM,mBACJ,eAAe,EACb,QAAQ;EACN,OAAO,EAAE;EACT,QAAQ,EAAE;EACV,OAAO,EAAE,oBAAoB;EAC7B,WAAW;CACb,EACF,CAAC;CAGH,MAAM,MAAM,EAAE;CACd,IAAI,QAA0B;CAC9B,IACE,KAAK,QACL,OAAO,IAAI,kBAAkB,cAC7B,OAAO,EAAE,qBAAqB,YAC9B;EACA,QAAQ,IAAI,cAAc,KAAK;EAC/B,MAAM,MAAM,UACV;EACF,IAAI,KAAK,YAAY,KAAK;EAC1B,SAAS,WAAW,OAAO,OAAO,CAAC;CACrC;CACA,MAAM,qBAA2B;EAC/B,IAAI,CAAC,SAAS,OAAO,EAAE,qBAAqB,YAAY;EACxD,MAAM,KAAK,EAAE,iBAAiB,KAAK;EACnC,MAAM,MAAM,MAAsB,OAAO,WAAW,CAAC,KAAK;EAC1D,eAAe,EACb,gBAAgB;GACd,KAAK,GAAG,GAAG,iBAAiB,aAAa,CAAC;GAC1C,OAAO,GAAG,GAAG,iBAAiB,eAAe,CAAC;GAC9C,QAAQ,GAAG,GAAG,iBAAiB,gBAAgB,CAAC;GAChD,MAAM,GAAG,GAAG,iBAAiB,cAAc,CAAC;EAC9C,EACF,CAAC;CACH;CAEA,MAAM,KAAK,EAAE;CACb,MAAM,qBAA2B;EAC/B,IAAI,CAAC,IAAI;EACT,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE,cAAc,GAAG,SAAS,GAAG,SAAS;EAC9D,MAAM,UAAU,IAAI;EACpB,eAAe,EAAE,UAAU;GAAE;GAAS,QAAQ,UAAU,IAAI;EAAE,EAAE,CAAC;CACnE;CAEA,MAAM,iBAAuB;EAC3B,WAAW;EACX,aAAa;EACb,aAAa;CACf;CACA,SAAS;CACT,EAAE,iBAAiB,UAAU,QAAQ;CACrC,SAAS,WAAW,EAAE,oBAAoB,UAAU,QAAQ,CAAC;CAE7D,IAAI,IAAI;EACN,MAAM,mBAAyB;GAC7B,aAAa;GACb,aAAa;EACf;EACA,GAAG,iBAAiB,UAAU,UAAU;EACxC,GAAG,iBAAiB,UAAU,UAAU;EACxC,SAAS,WAAW;GAClB,GAAG,oBAAoB,UAAU,UAAU;GAC3C,GAAG,oBAAoB,UAAU,UAAU;EAC7C,CAAC;CACH;CAEA,aAAa;EACX,KAAK,MAAM,KAAK,UAAU,EAAE;EAC5B,SAAS,SAAS;CACpB;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindees/atlas",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "description": "MindeesNative Atlas - accessible, signals-native UI primitives + a virtualized recycling list. Renderer-agnostic (web real, native research track).",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
@@ -13,10 +13,6 @@
13
13
  "types": "./dist/index.d.ts",
14
14
  "import": "./dist/index.js"
15
15
  },
16
- "./theme": {
17
- "types": "./dist/theme.d.ts",
18
- "import": "./dist/theme.js"
19
- },
20
16
  "./list": {
21
17
  "types": "./dist/list.d.ts",
22
18
  "import": "./dist/list.js"
@@ -39,12 +35,12 @@
39
35
  "directory": "packages/atlas"
40
36
  },
41
37
  "dependencies": {
42
- "@mindees/core": "0.24.0",
43
- "@mindees/router": "0.24.0"
38
+ "@mindees/core": "0.26.0",
39
+ "@mindees/router": "0.26.0"
44
40
  },
45
41
  "devDependencies": {
46
42
  "happy-dom": "20.9.0",
47
- "@mindees/renderer": "0.24.0"
43
+ "@mindees/renderer": "0.26.0"
48
44
  },
49
45
  "scripts": {
50
46
  "build": "tsdown",
package/dist/theme.d.ts DELETED
@@ -1,54 +0,0 @@
1
- import { Context, ContextProvider } from "@mindees/core";
2
-
3
- //#region src/theme.d.ts
4
- /** A design-token theme. External token packages can satisfy this shape. */
5
- interface ThemeTokens {
6
- readonly colors: {
7
- readonly background: string;
8
- readonly surface: string;
9
- readonly text: string;
10
- readonly textMuted: string;
11
- readonly primary: string;
12
- readonly onPrimary: string;
13
- readonly border: string;
14
- readonly danger: string;
15
- };
16
- /** Spacing scale (px), index 0 = none. */
17
- readonly space: readonly number[];
18
- readonly radii: {
19
- readonly sm: number;
20
- readonly md: number;
21
- readonly lg: number;
22
- readonly full: number;
23
- };
24
- readonly fontSizes: {
25
- readonly sm: number;
26
- readonly md: number;
27
- readonly lg: number;
28
- readonly xl: number;
29
- };
30
- readonly fontWeights: {
31
- readonly regular: number;
32
- readonly medium: number;
33
- readonly bold: number;
34
- };
35
- }
36
- /** A sensible, neutral default theme so Atlas works standalone. */
37
- declare const defaultTokens: ThemeTokens;
38
- /** The Atlas theme context (defaults to {@link defaultTokens}). */
39
- declare const ThemeContext: Context<ThemeTokens>;
40
- /** One-level-deep partial of the token groups (arrays are replaced wholesale, not deep-partialed). */
41
- type DeepPartial<T> = { [K in keyof T]?: T[K] extends ReadonlyArray<unknown> ? T[K] : T[K] extends object ? Partial<T[K]> : T[K] };
42
- /**
43
- * Create a theme provider. Pass partial overrides (deep-merged one level onto the defaults) or
44
- * nothing for the defaults. Use `.select(t => …)` for a reactive, isolated token accessor that
45
- * a primitive consumes as a `Reactive<StyleObject>`.
46
- *
47
- * @example
48
- * const theme = createTheme({ colors: { primary: '#7c3aed' } })
49
- * const accent = theme.select((t) => t.colors.primary)
50
- */
51
- declare function createTheme(overrides?: DeepPartial<ThemeTokens>): ContextProvider<ThemeTokens>;
52
- //#endregion
53
- export { ThemeContext, ThemeTokens, createTheme, defaultTokens };
54
- //# sourceMappingURL=theme.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme.d.ts","names":[],"sources":["../src/theme.ts"],"mappings":";;;;UAaiB,WAAA;EAAA,SACN,MAAA;IAAA,SACE,UAAA;IAAA,SACA,OAAA;IAAA,SACA,IAAA;IAAA,SACA,SAAA;IAAA,SACA,OAAA;IAAA,SACA,SAAA;IAAA,SACA,MAAA;IAAA,SACA,MAAA;EAAA;EAUF;EAAA,SAPA,KAAA;EAAA,SACA,KAAA;IAAA,SACE,EAAA;IAAA,SACA,EAAA;IAAA,SACA,EAAA;IAAA,SACA,IAAA;EAAA;EAAA,SAEF,SAAA;IAAA,SACE,EAAA;IAAA,SACA,EAAA;IAAA,SACA,EAAA;IAAA,SACA,EAAA;EAAA;EAAA,SAEF,WAAA;IAAA,SAAwB,OAAA;IAAA,SAA0B,MAAA;IAAA,SAAyB,IAAA;EAAA;AAAA;AAsBxC;AAAA,cAlBjC,aAAA,EAAe,WAe3B;;cAGY,YAAA,EAAc,OAAO,CAAC,WAAA;;KAc9B,WAAA,oBACS,CAAA,IAAK,CAAA,CAAE,CAAA,UAAW,aAAA,YAC1B,CAAA,CAAE,CAAA,IACF,CAAA,CAAE,CAAA,mBACA,OAAA,CAAQ,CAAA,CAAE,CAAA,KACV,CAAA,CAAE,CAAA;;;;;;;;;;iBAYM,WAAA,CACd,SAAA,GAAW,WAAA,CAAY,WAAA,IACtB,eAAA,CAAgB,WAAA"}
package/dist/theme.js DELETED
@@ -1,92 +0,0 @@
1
- import { createContext, createProvider } from "@mindees/core";
2
- //#region src/theme.ts
3
- /**
4
- * Atlas theming — a structural `ThemeTokens` interface + a minimal `defaultTokens`, consumed
5
- * through a `@mindees/core` selector-isolated context. Atlas takes **no dependency** on any
6
- * tokens package (the user's published `@mindees/tokens` can satisfy `ThemeTokens` and be
7
- * injected by the app); a component that selects one slice (`t => t.colors.primary`) only
8
- * re-runs when that slice changes. See `docs/adr/0022-atlas-primitives.md`.
9
- *
10
- * @module
11
- */
12
- /** A sensible, neutral default theme so Atlas works standalone. */
13
- const defaultTokens = {
14
- colors: {
15
- background: "#ffffff",
16
- surface: "#f5f5f5",
17
- text: "#111827",
18
- textMuted: "#6b7280",
19
- primary: "#2563eb",
20
- onPrimary: "#ffffff",
21
- border: "#e5e7eb",
22
- danger: "#dc2626"
23
- },
24
- space: [
25
- 0,
26
- 4,
27
- 8,
28
- 12,
29
- 16,
30
- 24,
31
- 32,
32
- 48,
33
- 64
34
- ],
35
- radii: {
36
- sm: 4,
37
- md: 8,
38
- lg: 16,
39
- full: 9999
40
- },
41
- fontSizes: {
42
- sm: 12,
43
- md: 14,
44
- lg: 18,
45
- xl: 24
46
- },
47
- fontWeights: {
48
- regular: 400,
49
- medium: 500,
50
- bold: 700
51
- }
52
- };
53
- /** The Atlas theme context (defaults to {@link defaultTokens}). */
54
- const ThemeContext = createContext(defaultTokens);
55
- /** Deep-merge (one level) token overrides onto the defaults. */
56
- function mergeTokens(overrides) {
57
- return {
58
- colors: {
59
- ...defaultTokens.colors,
60
- ...overrides.colors
61
- },
62
- space: overrides.space ?? defaultTokens.space,
63
- radii: {
64
- ...defaultTokens.radii,
65
- ...overrides.radii
66
- },
67
- fontSizes: {
68
- ...defaultTokens.fontSizes,
69
- ...overrides.fontSizes
70
- },
71
- fontWeights: {
72
- ...defaultTokens.fontWeights,
73
- ...overrides.fontWeights
74
- }
75
- };
76
- }
77
- /**
78
- * Create a theme provider. Pass partial overrides (deep-merged one level onto the defaults) or
79
- * nothing for the defaults. Use `.select(t => …)` for a reactive, isolated token accessor that
80
- * a primitive consumes as a `Reactive<StyleObject>`.
81
- *
82
- * @example
83
- * const theme = createTheme({ colors: { primary: '#7c3aed' } })
84
- * const accent = theme.select((t) => t.colors.primary)
85
- */
86
- function createTheme(overrides = {}) {
87
- return createProvider(ThemeContext, mergeTokens(overrides));
88
- }
89
- //#endregion
90
- export { ThemeContext, createTheme, defaultTokens };
91
-
92
- //# sourceMappingURL=theme.js.map
package/dist/theme.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme.js","names":[],"sources":["../src/theme.ts"],"sourcesContent":["/**\n * Atlas theming — a structural `ThemeTokens` interface + a minimal `defaultTokens`, consumed\n * through a `@mindees/core` selector-isolated context. Atlas takes **no dependency** on any\n * tokens package (the user's published `@mindees/tokens` can satisfy `ThemeTokens` and be\n * injected by the app); a component that selects one slice (`t => t.colors.primary`) only\n * re-runs when that slice changes. See `docs/adr/0022-atlas-primitives.md`.\n *\n * @module\n */\n\nimport { type Context, type ContextProvider, createContext, createProvider } from '@mindees/core'\n\n/** A design-token theme. External token packages can satisfy this shape. */\nexport interface ThemeTokens {\n readonly colors: {\n readonly background: string\n readonly surface: string\n readonly text: string\n readonly textMuted: string\n readonly primary: string\n readonly onPrimary: string\n readonly border: string\n readonly danger: string\n }\n /** Spacing scale (px), index 0 = none. */\n readonly space: readonly number[]\n readonly radii: {\n readonly sm: number\n readonly md: number\n readonly lg: number\n readonly full: number\n }\n readonly fontSizes: {\n readonly sm: number\n readonly md: number\n readonly lg: number\n readonly xl: number\n }\n readonly fontWeights: { readonly regular: number; readonly medium: number; readonly bold: number }\n}\n\n/** A sensible, neutral default theme so Atlas works standalone. */\nexport const defaultTokens: ThemeTokens = {\n colors: {\n background: '#ffffff',\n surface: '#f5f5f5',\n text: '#111827',\n textMuted: '#6b7280',\n primary: '#2563eb',\n onPrimary: '#ffffff',\n border: '#e5e7eb',\n danger: '#dc2626',\n },\n space: [0, 4, 8, 12, 16, 24, 32, 48, 64],\n radii: { sm: 4, md: 8, lg: 16, full: 9999 },\n fontSizes: { sm: 12, md: 14, lg: 18, xl: 24 },\n fontWeights: { regular: 400, medium: 500, bold: 700 },\n}\n\n/** The Atlas theme context (defaults to {@link defaultTokens}). */\nexport const ThemeContext: Context<ThemeTokens> = createContext(defaultTokens)\n\n/** Deep-merge (one level) token overrides onto the defaults. */\nfunction mergeTokens(overrides: DeepPartial<ThemeTokens>): ThemeTokens {\n return {\n colors: { ...defaultTokens.colors, ...overrides.colors },\n space: overrides.space ?? defaultTokens.space,\n radii: { ...defaultTokens.radii, ...overrides.radii },\n fontSizes: { ...defaultTokens.fontSizes, ...overrides.fontSizes },\n fontWeights: { ...defaultTokens.fontWeights, ...overrides.fontWeights },\n }\n}\n\n/** One-level-deep partial of the token groups (arrays are replaced wholesale, not deep-partialed). */\ntype DeepPartial<T> = {\n [K in keyof T]?: T[K] extends ReadonlyArray<unknown>\n ? T[K]\n : T[K] extends object\n ? Partial<T[K]>\n : T[K]\n}\n\n/**\n * Create a theme provider. Pass partial overrides (deep-merged one level onto the defaults) or\n * nothing for the defaults. Use `.select(t => …)` for a reactive, isolated token accessor that\n * a primitive consumes as a `Reactive<StyleObject>`.\n *\n * @example\n * const theme = createTheme({ colors: { primary: '#7c3aed' } })\n * const accent = theme.select((t) => t.colors.primary)\n */\nexport function createTheme(\n overrides: DeepPartial<ThemeTokens> = {},\n): ContextProvider<ThemeTokens> {\n return createProvider(ThemeContext, mergeTokens(overrides))\n}\n"],"mappings":";;;;;;;;;;;;AA0CA,MAAa,gBAA6B;CACxC,QAAQ;EACN,YAAY;EACZ,SAAS;EACT,MAAM;EACN,WAAW;EACX,SAAS;EACT,WAAW;EACX,QAAQ;EACR,QAAQ;CACV;CACA,OAAO;EAAC;EAAG;EAAG;EAAG;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;CACvC,OAAO;EAAE,IAAI;EAAG,IAAI;EAAG,IAAI;EAAI,MAAM;CAAK;CAC1C,WAAW;EAAE,IAAI;EAAI,IAAI;EAAI,IAAI;EAAI,IAAI;CAAG;CAC5C,aAAa;EAAE,SAAS;EAAK,QAAQ;EAAK,MAAM;CAAI;AACtD;;AAGA,MAAa,eAAqC,cAAc,aAAa;;AAG7E,SAAS,YAAY,WAAkD;CACrE,OAAO;EACL,QAAQ;GAAE,GAAG,cAAc;GAAQ,GAAG,UAAU;EAAO;EACvD,OAAO,UAAU,SAAS,cAAc;EACxC,OAAO;GAAE,GAAG,cAAc;GAAO,GAAG,UAAU;EAAM;EACpD,WAAW;GAAE,GAAG,cAAc;GAAW,GAAG,UAAU;EAAU;EAChE,aAAa;GAAE,GAAG,cAAc;GAAa,GAAG,UAAU;EAAY;CACxE;AACF;;;;;;;;;;AAoBA,SAAgB,YACd,YAAsC,CAAC,GACT;CAC9B,OAAO,eAAe,cAAc,YAAY,SAAS,CAAC;AAC5D"}