@mindees/atlas 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/primitives.js +1 -1
- package/dist/primitives.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { Maturity, NotImplementedError, PackageInfo, notImplemented } from "@min
|
|
|
16
16
|
/** The npm package name. */
|
|
17
17
|
declare const name = "@mindees/atlas";
|
|
18
18
|
/** The package version. All `@mindees/*` packages share one locked version line. */
|
|
19
|
-
declare const VERSION = "0.
|
|
19
|
+
declare const VERSION = "0.11.0";
|
|
20
20
|
/** Current maturity of this package. See the repository `STATUS.md`. */
|
|
21
21
|
declare const maturity: Maturity;
|
|
22
22
|
/**
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { NotImplementedError, notImplemented } from "@mindees/core";
|
|
|
15
15
|
/** The npm package name. */
|
|
16
16
|
const name = "@mindees/atlas";
|
|
17
17
|
/** The package version. All `@mindees/*` packages share one locked version line. */
|
|
18
|
-
const VERSION = "0.
|
|
18
|
+
const VERSION = "0.11.0";
|
|
19
19
|
/** Current maturity of this package. See the repository `STATUS.md`. */
|
|
20
20
|
const maturity = "experimental";
|
|
21
21
|
/**
|
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.
|
|
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.11.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 Skeleton,\n type SkeletonProps,\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 useSafeAreaInsets,\n useWindowDimensions,\n type WindowDimensions,\n} from './environment'\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 Toggle,\n useAsync,\n useCounter,\n usePrevious,\n useReducer,\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} 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 { 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"}
|
package/dist/primitives.js
CHANGED
|
@@ -168,7 +168,7 @@ const ScrollView = (props) => {
|
|
|
168
168
|
});
|
|
169
169
|
if (onScroll) host.onScroll = onScroll;
|
|
170
170
|
if (horizontal) host["data-orientation"] = "horizontal";
|
|
171
|
-
return createElement("scrollview", host, children);
|
|
171
|
+
return createElement(horizontal ? "horizontalscrollview" : "scrollview", host, children);
|
|
172
172
|
};
|
|
173
173
|
//#endregion
|
|
174
174
|
export { Button, Column, Image, Pressable, Row, ScrollView, Spacer, Stack, Text, TextInput, View, usePressable };
|
package/dist/primitives.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.js","names":[],"sources":["../src/primitives.ts"],"sourcesContent":["/**\n * Atlas primitives — accessible, signals-native UI building blocks. Each is a\n * `Component<P>` over `@mindees/core`'s `createElement`, returning a renderer-agnostic\n * `MindeesNode`. Web rendering is real (via the Helix DOM backend); native is a labeled 🔬\n * research track (the same serializable tree, interpreted by a native host later). See\n * `docs/adr/0022-atlas-primitives.md`.\n *\n * @module\n */\n\nimport {\n type Accessor,\n type Component,\n createElement,\n type MindeesNode,\n signal,\n} from '@mindees/core'\nimport { type BaseProps, type Reactive, resolveStyle, toHostProps } from './host'\nimport { flattenStyle, type StyleInput } from './style'\n\n/** Merge a base layout style with a caller's (possibly reactive) style, staying reactive if it is. */\nfunction withBaseStyle(\n base: StyleInput,\n style: Reactive<StyleInput> | undefined,\n): Reactive<StyleInput> {\n if (typeof style === 'function') {\n const accessor = style as Accessor<StyleInput>\n return () => flattenStyle([base, accessor()])\n }\n return flattenStyle([base, style])\n}\n\n/** Dev-only warning (silent in production). Structural global access — no DOM/Node lib needed. */\nfunction warnDev(message: string): void {\n const g = globalThis as {\n process?: { env?: Record<string, string | undefined> }\n console?: { warn?: (message: string) => void }\n }\n if (g.process?.env?.NODE_ENV === 'production') return\n g.console?.warn?.(`[atlas] ${message}`)\n}\n\nfunction eventValue(event: unknown): string {\n return (event as { target?: { value?: string } })?.target?.value ?? ''\n}\n\n/** A generic container (→ `view`/`div`). */\nexport interface ViewProps extends BaseProps {\n readonly children?: MindeesNode\n}\nexport const View: Component<ViewProps> = (props) =>\n createElement('view', toHostProps(props), props.children)\n\n/** Text content (→ `text`/`span`). No default `role` (a bare span is correct; pass `role` to opt in). */\nexport interface TextProps extends BaseProps {\n readonly children?: MindeesNode\n}\nexport const Text: Component<TextProps> = (props) =>\n createElement('text', toHostProps(props), props.children)\n\n/** An image (→ `image`/`img`). Requires `label` (alt) unless `decorative`. */\nexport interface ImageProps extends BaseProps {\n readonly src: string\n /** Mark purely-decorative images so screen readers skip them (alt=\"\" + aria-hidden). */\n readonly decorative?: boolean\n}\nexport const Image: Component<ImageProps> = (props) => {\n const host = toHostProps(props)\n host.src = props.src\n if (props.decorative) {\n host.alt = ''\n host['aria-hidden'] = 'true'\n // A decorative image must expose NO accessible name; drop any label lowered by\n // toHostProps so we don't emit a contradictory aria-label on a hidden element.\n delete host['aria-label']\n delete host['aria-labelledby']\n } else {\n if (props.label === undefined) {\n warnDev('Image without a `label` (alt text); pass `label` or set `decorative`.')\n }\n host.alt = props.label ?? ''\n }\n return createElement('image', host)\n}\n\n/** A text field (→ `textinput`/`input`). `value` may be reactive (controlled). */\nexport interface TextInputProps extends BaseProps {\n readonly value?: Reactive<string>\n readonly placeholder?: string\n readonly type?: 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url'\n readonly disabled?: boolean\n /** Fires on every keystroke with the current value (`input` event). */\n readonly onInput?: (value: string) => void\n /** Fires on commit/blur with the current value (`change` event). */\n readonly onChange?: (value: string) => void\n}\nexport const TextInput: Component<TextInputProps> = (props) => {\n const host = toHostProps(props)\n if (!host.role) host.role = 'textbox'\n if (props.value !== undefined) host.value = props.value\n if (props.placeholder !== undefined) host.placeholder = props.placeholder\n if (props.type !== undefined) host.type = props.type\n if (props.disabled) host.disabled = true\n if (props.onInput) host.onInput = (e: unknown) => props.onInput?.(eventValue(e))\n if (props.onChange) host.onChange = (e: unknown) => props.onChange?.(eventValue(e))\n return createElement('textinput', host)\n}\n\n/** Interaction state exposed to a Pressable style function. */\nexport interface InteractionState {\n readonly hovered: boolean\n readonly pressed: boolean\n readonly focused: boolean\n}\n\n/** A pressable surface with built-in hover/press/focus state. Web-real via DOM events. */\nexport interface PressableProps extends Omit<BaseProps, 'style'> {\n readonly children?: MindeesNode\n /** Called when activated (click / Enter / Space) — skipped while `disabled`. */\n readonly onPress?: () => void\n readonly disabled?: boolean\n /** Static/reactive style, or a function of the live interaction state. */\n readonly style?: Reactive<StyleInput> | ((state: InteractionState) => StyleInput)\n}\n\n/**\n * Create the interaction signals + host handlers a pressable surface needs. Reusable so other\n * primitives can compose interaction state. Web wires REAL DOM events (`click`, `pointer*`,\n * `focus`/`blur`, `keydown`) — never a fake cross-platform `press` event that no-ops on web.\n */\nexport function usePressable(options: { onPress?: () => void; disabled?: boolean } = {}): {\n state: () => InteractionState\n handlers: Record<string, (event: unknown) => void>\n} {\n const hovered = signal(false)\n const pressed = signal(false)\n const focused = signal(false)\n const enabled = (): boolean => !options.disabled\n const fire = (): void => {\n if (enabled()) options.onPress?.()\n }\n // A disabled control is inert: its interaction signals don't update, so a state-driven style\n // shows no hover/press/focus feedback (and `fire` blocks onPress / keyboard activation).\n const handlers: Record<string, (event: unknown) => void> = {\n onClick: () => fire(),\n onPointerEnter: () => {\n if (enabled()) hovered.set(true)\n },\n onPointerLeave: () => {\n if (enabled()) {\n hovered.set(false)\n pressed.set(false)\n }\n },\n onPointerDown: () => {\n if (enabled()) pressed.set(true)\n },\n onPointerUp: () => {\n if (enabled()) pressed.set(false)\n },\n onFocus: () => {\n if (enabled()) focused.set(true)\n },\n onBlur: () => {\n if (enabled()) focused.set(false)\n },\n onKeyDown: (e: unknown) => {\n const ev = e as { key?: string; preventDefault?: () => void }\n if (ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault?.() // stop Space from page-scrolling a div[role=button]\n fire()\n }\n },\n }\n return {\n state: () => ({ hovered: hovered(), pressed: pressed(), focused: focused() }),\n handlers,\n }\n}\n\nexport const Pressable: Component<PressableProps> = (props) => {\n const { state, handlers } = usePressable({\n ...(props.onPress ? { onPress: props.onPress } : {}),\n ...(props.disabled ? { disabled: true } : {}),\n })\n // Base host props WITHOUT style (Pressable resolves style itself, supporting a state fn).\n const { style, ...rest } = props\n const host: Record<string, unknown> = { ...toHostProps(rest), ...handlers }\n if (!host.role) host.role = 'button'\n if (props.disabled) host['aria-disabled'] = 'true'\n else host.tabindex = 0\n if (style !== undefined) {\n // Distinguish a state-fn `(state) => StyleInput` from a plain reactive style accessor\n // `() => StyleInput` by ARITY: both are functions, but only the state-fn declares a\n // parameter. Treating every function as a state-fn would subscribe an ordinary\n // reactive style to hover/press/focus, re-running it on every interaction.\n const isStateFn = typeof style === 'function' && style.length >= 1\n host.style = isStateFn\n ? () => flattenStyle((style as (s: InteractionState) => StyleInput)(state()))\n : // Arity ruled the state-fn out, so the remainder is a plain `Reactive<StyleInput>`.\n // TS can't narrow on `.length`, so assert it (mirrors the state-fn cast above).\n resolveStyle(style as Reactive<StyleInput>)\n }\n return createElement('view', host, props.children)\n}\n\n/** A labelled button = {@link Pressable} wrapping a {@link Text}. */\nexport interface ButtonProps extends PressableProps {\n /** Convenience text label (alternative to `children`). */\n readonly title?: string\n}\nexport const Button: Component<ButtonProps> = (props) => {\n const { title, children, ...rest } = props\n // The renderer always passes `children` as an array (`[]` when empty), so `??` wouldn't\n // trigger the title fallback — treat an empty array as \"no children\".\n const hasChildren = Array.isArray(children) ? children.length > 0 : children != null\n const content = hasChildren\n ? children\n : title !== undefined\n ? createElement(Text, null, title)\n : null\n return createElement(Pressable, rest, content)\n}\n\n// --- Layout composition (pure View + style, no new host concepts) ---\n\ntype FlexAlign = 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'\ntype FlexJustify =\n | 'flex-start'\n | 'flex-end'\n | 'center'\n | 'space-between'\n | 'space-around'\n | 'space-evenly'\n\n/** A flex container. `direction` defaults to `column`. */\nexport interface StackProps extends ViewProps {\n readonly direction?: 'row' | 'column'\n readonly gap?: number | string\n readonly align?: FlexAlign\n readonly justify?: FlexJustify\n}\nexport const Stack: Component<StackProps> = (props) => {\n const { direction = 'column', gap, align, justify, style, children, ...rest } = props\n const layout: StyleInput = {\n display: 'flex',\n flexDirection: direction,\n ...(gap !== undefined ? { gap } : {}),\n ...(align !== undefined ? { alignItems: align } : {}),\n ...(justify !== undefined ? { justifyContent: justify } : {}),\n }\n return createElement(View, { ...rest, style: withBaseStyle(layout, style) }, children)\n}\n\n/** A horizontal {@link Stack}. */\nexport const Row: Component<Omit<StackProps, 'direction'>> = (props) =>\n createElement(Stack, { ...props, direction: 'row' }, props.children)\n\n/** A vertical {@link Stack}. */\nexport const Column: Component<Omit<StackProps, 'direction'>> = (props) =>\n createElement(Stack, { ...props, direction: 'column' }, props.children)\n\n/** Flexible (or fixed) empty space. */\nexport interface SpacerProps {\n /** Fixed size (px) instead of flexible fill. */\n readonly size?: number | string\n}\nexport const Spacer: Component<SpacerProps> = (props) =>\n createElement(View, {\n style: props.size !== undefined ? { width: props.size, height: props.size } : { flex: 1 },\n })\n\n/** A scrollable container (→ `scrollview`/`div` with `overflow:auto`). */\nexport interface ScrollViewProps extends ViewProps {\n readonly horizontal?: boolean\n /** Fires on scroll with the host scroll event. */\n readonly onScroll?: (event: unknown) => void\n}\nexport const ScrollView: Component<ScrollViewProps> = (props) => {\n const { horizontal, onScroll, style, children, ...rest } = props\n // A horizontal scroller lays its children out in a row and scrolls along x; a vertical\n // one stacks and scrolls along y. Drive real layout through the curated cross-platform\n // style subset (flexDirection + overflow), not an inert `data-orientation` attribute that\n // no backend reads.\n const host = toHostProps({\n ...rest,\n style: withBaseStyle(\n horizontal\n ? // `display: 'flex'` is required for `flexDirection`/`flexWrap` to take effect —\n // without it the row layout is inert (the element keeps the default block flow).\n { display: 'flex', overflow: 'auto', flexDirection: 'row', flexWrap: 'nowrap' }\n : { overflow: 'auto' },\n style,\n ),\n })\n if (onScroll) host.onScroll = onScroll\n if (horizontal) host['data-orientation'] = 'horizontal' // extra hint for native hosts\n return createElement('scrollview', host, children)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"primitives.js","names":[],"sources":["../src/primitives.ts"],"sourcesContent":["/**\n * Atlas primitives — accessible, signals-native UI building blocks. Each is a\n * `Component<P>` over `@mindees/core`'s `createElement`, returning a renderer-agnostic\n * `MindeesNode`. Web rendering is real (via the Helix DOM backend); native is a labeled 🔬\n * research track (the same serializable tree, interpreted by a native host later). See\n * `docs/adr/0022-atlas-primitives.md`.\n *\n * @module\n */\n\nimport {\n type Accessor,\n type Component,\n createElement,\n type MindeesNode,\n signal,\n} from '@mindees/core'\nimport { type BaseProps, type Reactive, resolveStyle, toHostProps } from './host'\nimport { flattenStyle, type StyleInput } from './style'\n\n/** Merge a base layout style with a caller's (possibly reactive) style, staying reactive if it is. */\nfunction withBaseStyle(\n base: StyleInput,\n style: Reactive<StyleInput> | undefined,\n): Reactive<StyleInput> {\n if (typeof style === 'function') {\n const accessor = style as Accessor<StyleInput>\n return () => flattenStyle([base, accessor()])\n }\n return flattenStyle([base, style])\n}\n\n/** Dev-only warning (silent in production). Structural global access — no DOM/Node lib needed. */\nfunction warnDev(message: string): void {\n const g = globalThis as {\n process?: { env?: Record<string, string | undefined> }\n console?: { warn?: (message: string) => void }\n }\n if (g.process?.env?.NODE_ENV === 'production') return\n g.console?.warn?.(`[atlas] ${message}`)\n}\n\nfunction eventValue(event: unknown): string {\n return (event as { target?: { value?: string } })?.target?.value ?? ''\n}\n\n/** A generic container (→ `view`/`div`). */\nexport interface ViewProps extends BaseProps {\n readonly children?: MindeesNode\n}\nexport const View: Component<ViewProps> = (props) =>\n createElement('view', toHostProps(props), props.children)\n\n/** Text content (→ `text`/`span`). No default `role` (a bare span is correct; pass `role` to opt in). */\nexport interface TextProps extends BaseProps {\n readonly children?: MindeesNode\n}\nexport const Text: Component<TextProps> = (props) =>\n createElement('text', toHostProps(props), props.children)\n\n/** An image (→ `image`/`img`). Requires `label` (alt) unless `decorative`. */\nexport interface ImageProps extends BaseProps {\n readonly src: string\n /** Mark purely-decorative images so screen readers skip them (alt=\"\" + aria-hidden). */\n readonly decorative?: boolean\n}\nexport const Image: Component<ImageProps> = (props) => {\n const host = toHostProps(props)\n host.src = props.src\n if (props.decorative) {\n host.alt = ''\n host['aria-hidden'] = 'true'\n // A decorative image must expose NO accessible name; drop any label lowered by\n // toHostProps so we don't emit a contradictory aria-label on a hidden element.\n delete host['aria-label']\n delete host['aria-labelledby']\n } else {\n if (props.label === undefined) {\n warnDev('Image without a `label` (alt text); pass `label` or set `decorative`.')\n }\n host.alt = props.label ?? ''\n }\n return createElement('image', host)\n}\n\n/** A text field (→ `textinput`/`input`). `value` may be reactive (controlled). */\nexport interface TextInputProps extends BaseProps {\n readonly value?: Reactive<string>\n readonly placeholder?: string\n readonly type?: 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url'\n readonly disabled?: boolean\n /** Fires on every keystroke with the current value (`input` event). */\n readonly onInput?: (value: string) => void\n /** Fires on commit/blur with the current value (`change` event). */\n readonly onChange?: (value: string) => void\n}\nexport const TextInput: Component<TextInputProps> = (props) => {\n const host = toHostProps(props)\n if (!host.role) host.role = 'textbox'\n if (props.value !== undefined) host.value = props.value\n if (props.placeholder !== undefined) host.placeholder = props.placeholder\n if (props.type !== undefined) host.type = props.type\n if (props.disabled) host.disabled = true\n if (props.onInput) host.onInput = (e: unknown) => props.onInput?.(eventValue(e))\n if (props.onChange) host.onChange = (e: unknown) => props.onChange?.(eventValue(e))\n return createElement('textinput', host)\n}\n\n/** Interaction state exposed to a Pressable style function. */\nexport interface InteractionState {\n readonly hovered: boolean\n readonly pressed: boolean\n readonly focused: boolean\n}\n\n/** A pressable surface with built-in hover/press/focus state. Web-real via DOM events. */\nexport interface PressableProps extends Omit<BaseProps, 'style'> {\n readonly children?: MindeesNode\n /** Called when activated (click / Enter / Space) — skipped while `disabled`. */\n readonly onPress?: () => void\n readonly disabled?: boolean\n /** Static/reactive style, or a function of the live interaction state. */\n readonly style?: Reactive<StyleInput> | ((state: InteractionState) => StyleInput)\n}\n\n/**\n * Create the interaction signals + host handlers a pressable surface needs. Reusable so other\n * primitives can compose interaction state. Web wires REAL DOM events (`click`, `pointer*`,\n * `focus`/`blur`, `keydown`) — never a fake cross-platform `press` event that no-ops on web.\n */\nexport function usePressable(options: { onPress?: () => void; disabled?: boolean } = {}): {\n state: () => InteractionState\n handlers: Record<string, (event: unknown) => void>\n} {\n const hovered = signal(false)\n const pressed = signal(false)\n const focused = signal(false)\n const enabled = (): boolean => !options.disabled\n const fire = (): void => {\n if (enabled()) options.onPress?.()\n }\n // A disabled control is inert: its interaction signals don't update, so a state-driven style\n // shows no hover/press/focus feedback (and `fire` blocks onPress / keyboard activation).\n const handlers: Record<string, (event: unknown) => void> = {\n onClick: () => fire(),\n onPointerEnter: () => {\n if (enabled()) hovered.set(true)\n },\n onPointerLeave: () => {\n if (enabled()) {\n hovered.set(false)\n pressed.set(false)\n }\n },\n onPointerDown: () => {\n if (enabled()) pressed.set(true)\n },\n onPointerUp: () => {\n if (enabled()) pressed.set(false)\n },\n onFocus: () => {\n if (enabled()) focused.set(true)\n },\n onBlur: () => {\n if (enabled()) focused.set(false)\n },\n onKeyDown: (e: unknown) => {\n const ev = e as { key?: string; preventDefault?: () => void }\n if (ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault?.() // stop Space from page-scrolling a div[role=button]\n fire()\n }\n },\n }\n return {\n state: () => ({ hovered: hovered(), pressed: pressed(), focused: focused() }),\n handlers,\n }\n}\n\nexport const Pressable: Component<PressableProps> = (props) => {\n const { state, handlers } = usePressable({\n ...(props.onPress ? { onPress: props.onPress } : {}),\n ...(props.disabled ? { disabled: true } : {}),\n })\n // Base host props WITHOUT style (Pressable resolves style itself, supporting a state fn).\n const { style, ...rest } = props\n const host: Record<string, unknown> = { ...toHostProps(rest), ...handlers }\n if (!host.role) host.role = 'button'\n if (props.disabled) host['aria-disabled'] = 'true'\n else host.tabindex = 0\n if (style !== undefined) {\n // Distinguish a state-fn `(state) => StyleInput` from a plain reactive style accessor\n // `() => StyleInput` by ARITY: both are functions, but only the state-fn declares a\n // parameter. Treating every function as a state-fn would subscribe an ordinary\n // reactive style to hover/press/focus, re-running it on every interaction.\n const isStateFn = typeof style === 'function' && style.length >= 1\n host.style = isStateFn\n ? () => flattenStyle((style as (s: InteractionState) => StyleInput)(state()))\n : // Arity ruled the state-fn out, so the remainder is a plain `Reactive<StyleInput>`.\n // TS can't narrow on `.length`, so assert it (mirrors the state-fn cast above).\n resolveStyle(style as Reactive<StyleInput>)\n }\n return createElement('view', host, props.children)\n}\n\n/** A labelled button = {@link Pressable} wrapping a {@link Text}. */\nexport interface ButtonProps extends PressableProps {\n /** Convenience text label (alternative to `children`). */\n readonly title?: string\n}\nexport const Button: Component<ButtonProps> = (props) => {\n const { title, children, ...rest } = props\n // The renderer always passes `children` as an array (`[]` when empty), so `??` wouldn't\n // trigger the title fallback — treat an empty array as \"no children\".\n const hasChildren = Array.isArray(children) ? children.length > 0 : children != null\n const content = hasChildren\n ? children\n : title !== undefined\n ? createElement(Text, null, title)\n : null\n return createElement(Pressable, rest, content)\n}\n\n// --- Layout composition (pure View + style, no new host concepts) ---\n\ntype FlexAlign = 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'\ntype FlexJustify =\n | 'flex-start'\n | 'flex-end'\n | 'center'\n | 'space-between'\n | 'space-around'\n | 'space-evenly'\n\n/** A flex container. `direction` defaults to `column`. */\nexport interface StackProps extends ViewProps {\n readonly direction?: 'row' | 'column'\n readonly gap?: number | string\n readonly align?: FlexAlign\n readonly justify?: FlexJustify\n}\nexport const Stack: Component<StackProps> = (props) => {\n const { direction = 'column', gap, align, justify, style, children, ...rest } = props\n const layout: StyleInput = {\n display: 'flex',\n flexDirection: direction,\n ...(gap !== undefined ? { gap } : {}),\n ...(align !== undefined ? { alignItems: align } : {}),\n ...(justify !== undefined ? { justifyContent: justify } : {}),\n }\n return createElement(View, { ...rest, style: withBaseStyle(layout, style) }, children)\n}\n\n/** A horizontal {@link Stack}. */\nexport const Row: Component<Omit<StackProps, 'direction'>> = (props) =>\n createElement(Stack, { ...props, direction: 'row' }, props.children)\n\n/** A vertical {@link Stack}. */\nexport const Column: Component<Omit<StackProps, 'direction'>> = (props) =>\n createElement(Stack, { ...props, direction: 'column' }, props.children)\n\n/** Flexible (or fixed) empty space. */\nexport interface SpacerProps {\n /** Fixed size (px) instead of flexible fill. */\n readonly size?: number | string\n}\nexport const Spacer: Component<SpacerProps> = (props) =>\n createElement(View, {\n style: props.size !== undefined ? { width: props.size, height: props.size } : { flex: 1 },\n })\n\n/** A scrollable container (→ `scrollview`/`div` with `overflow:auto`). */\nexport interface ScrollViewProps extends ViewProps {\n readonly horizontal?: boolean\n /** Fires on scroll with the host scroll event. */\n readonly onScroll?: (event: unknown) => void\n}\nexport const ScrollView: Component<ScrollViewProps> = (props) => {\n const { horizontal, onScroll, style, children, ...rest } = props\n // A horizontal scroller lays its children out in a row and scrolls along x; a vertical\n // one stacks and scrolls along y. Drive real layout through the curated cross-platform\n // style subset (flexDirection + overflow), not an inert `data-orientation` attribute that\n // no backend reads.\n const host = toHostProps({\n ...rest,\n style: withBaseStyle(\n horizontal\n ? // `display: 'flex'` is required for `flexDirection`/`flexWrap` to take effect —\n // without it the row layout is inert (the element keeps the default block flow).\n { display: 'flex', overflow: 'auto', flexDirection: 'row', flexWrap: 'nowrap' }\n : { overflow: 'auto' },\n style,\n ),\n })\n if (onScroll) host.onScroll = onScroll\n if (horizontal) host['data-orientation'] = 'horizontal' // extra hint for native hosts\n // Orientation is fixed at creation, so emit a distinct tag a native host can branch on in\n // makeElement (a vertical ScrollView and a HorizontalScrollView are different widgets). Web\n // maps both to <div> and derives orientation from the style above.\n return createElement(horizontal ? 'horizontalscrollview' : 'scrollview', host, children)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindees/atlas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"directory": "packages/atlas"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@mindees/
|
|
43
|
-
"@mindees/
|
|
42
|
+
"@mindees/router": "0.11.0",
|
|
43
|
+
"@mindees/core": "0.11.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"happy-dom": "20.9.0",
|
|
47
|
-
"@mindees/renderer": "0.
|
|
47
|
+
"@mindees/renderer": "0.11.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsdown",
|