aeon-ui-engine 1.9.0 → 1.10.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.
@@ -4,7 +4,7 @@ import * as xstate from 'xstate';
4
4
  import { AnyStateMachine } from 'xstate';
5
5
  import { useMachine } from '@xstate/react';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
- import { AsyncContext, ContentRegionState, AppNavChild, StickyBarState } from '@aeon-ui/primitives';
7
+ import { AsyncContext, ContentRegionState, AppNavChild, StickyBarState, AnySlices, AeonStore, QueryOf, QueryResult, EntityOf, StoreState } from '@aeon-ui/primitives';
8
8
  export { AppNavChild, AppNavContext, createAsyncMachine, fieldMachine } from '@aeon-ui/primitives';
9
9
  import { fieldFace, ListWindowAxis, ListWindow, AeonColorMode, ResponsiveLayoutSpec, LayoutMode, LayoutCompositionSpec } from '@aeon-ui/core';
10
10
  export { AeonColorMode as AeonMode } from '@aeon-ui/core';
@@ -1282,6 +1282,15 @@ declare const StickyBar: {
1282
1282
  Seam: react.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
1283
1283
  };
1284
1284
 
1285
+ /**
1286
+ * Reads a slice of an Aeon store. Re-renders only when the selected value
1287
+ * changes under `equals` (shallow by default), so a component that selects
1288
+ * one entity ignores writes to every other.
1289
+ */
1290
+ declare function useAeonSelector<S extends AnySlices, T>(store: AeonStore<S>, selector: (state: StoreState<S>) => T, equals?: (a: T, b: T) => boolean): T;
1291
+ /** Fetches a query while mounted and returns its result; the entities stay in the store. */
1292
+ declare function useAeonQuery<S extends AnySlices, N extends keyof S & string>(store: AeonStore<S>, slice: N, query: QueryOf<S[N]>): QueryResult<EntityOf<S[N]>>;
1293
+
1285
1294
  declare function useLayoutMode(spec: ResponsiveLayoutSpec): {
1286
1295
  mode: LayoutMode;
1287
1296
  composition: LayoutCompositionSpec;
@@ -1307,4 +1316,4 @@ declare const Slot: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement>
1307
1316
  children?: ReactNode;
1308
1317
  } & react.RefAttributes<HTMLElement>>;
1309
1318
 
1310
- export { Accordion, type AccordionItemContentProps, type AccordionItemProps, type AccordionItemTriggerProps, type AccordionRootProps, AppNav, type AppNavBreadcrumbProps, type AppNavRootProps, type AppNavSectionProps, AppShell, type AppShellRootProps, Async, AsyncActions, AsyncProvider, AsyncReadout, AsyncRoot, AsyncTrack, Avatar, type AvatarRootProps, type AvatarStatus, Bar, type BarRootProps, Button, type ButtonRootProps, type ButtonStatus, Checkbox, type CheckboxRootProps, Clipboard, type ClipboardIndicatorProps, type ClipboardRootProps, Combobox, type ComboboxItemProps, type ComboboxRootProps, Composer, type ComposerInputProps, type ComposerRootProps, type ComposerState, Content, type ContentRootProps, Conversation, type ConversationItemProps, type ConversationItemState, type ConversationRootProps, Dialog, type DialogPortalProps, type DialogRootProps, Entry, type EntryListProps, type EntryRootProps, type EntryState, Field, type FieldControlProps, type FieldRootProps, type FieldTextareaProps, FileUpload, type FileUploadRootProps, Identity, type IdentityRootProps, ListRow, type ListRowRootProps, Menu, type MenuItemProps, type MenuPositionerProps, type MenuRootProps, MetricStrip, type MetricStripRootProps, Nav, type NavItemProps, type NavRootProps, Panel, type PanelContentProps, type PanelGroupProps, type PanelLabelProps, type PanelRootProps, type PanelTriggerProps, PinInput, type PinInputInputProps, type PinInputRootProps, Popover, type PopoverPositionerProps, type PopoverRootProps, type PresenceState, ProfileHeader, type ProfileHeaderRootProps, Progress, type ProgressRootProps, Prompt, type PromptRootProps, type PromptStatus, Prose, type ProseRootProps, RadioGroup, type RadioGroupItemProps, type RadioGroupRootProps, RangeSlider, type RangeSliderRootProps, type RangeSliderThumbProps, Scroll, type ScrollRootProps, type ScrollViewportProps, SegmentGroup, type SegmentGroupItemProps, type SegmentGroupRootProps, Select, type SelectContentProps, type SelectItemProps, type SelectPositionerProps, type SelectRootProps, Separator, type SeparatorRootProps, Slider, type SliderContextValue, type SliderRootProps, Slot, StatusBanner, type StatusBannerRootProps, type StatusBannerTone, StickyBar, type StickyBarRootProps, Switch, type SwitchRootProps, Tabs, type TabsContentProps, type TabsRootProps, type TabsTriggerProps, Textarea, type TextareaRootProps, ThemeSwitcher, type ThemeSwitcherModeBtnProps, type ThemeSwitcherModesProps, type ThemeSwitcherRootProps, type ThemeSwitcherThemeSelectProps, Thread, type ThreadItemFace, type ThreadItemProps, type ThreadMessageState, type ThreadRootProps, Toast, ToastItem, type ToastPlacement, type ToastProviderProps, type ToastPublishOptions, type ToastRecord, type ToastRootProps, type ToastStore, type ToastViewportProps, Tooltip, type TooltipPositionerProps, type TooltipRootProps, type UseWindowedRangeOptions, asyncStatusToContentState, rowLimits, useAeonMachine, useAppNav, useAppNavMachine, useAppShellContext, useAsyncContext, useAutoGrow, useClipboardStatus, useContentContext, useFieldContext, useFileUploadCtx as useFileUpload, useFitText, useLayoutMode, useScrollContext, useScrollState, useSliderContext, useStickyBarContext, useToast, useToastStore, useWindowedRange };
1319
+ export { Accordion, type AccordionItemContentProps, type AccordionItemProps, type AccordionItemTriggerProps, type AccordionRootProps, AppNav, type AppNavBreadcrumbProps, type AppNavRootProps, type AppNavSectionProps, AppShell, type AppShellRootProps, Async, AsyncActions, AsyncProvider, AsyncReadout, AsyncRoot, AsyncTrack, Avatar, type AvatarRootProps, type AvatarStatus, Bar, type BarRootProps, Button, type ButtonRootProps, type ButtonStatus, Checkbox, type CheckboxRootProps, Clipboard, type ClipboardIndicatorProps, type ClipboardRootProps, Combobox, type ComboboxItemProps, type ComboboxRootProps, Composer, type ComposerInputProps, type ComposerRootProps, type ComposerState, Content, type ContentRootProps, Conversation, type ConversationItemProps, type ConversationItemState, type ConversationRootProps, Dialog, type DialogPortalProps, type DialogRootProps, Entry, type EntryListProps, type EntryRootProps, type EntryState, Field, type FieldControlProps, type FieldRootProps, type FieldTextareaProps, FileUpload, type FileUploadRootProps, Identity, type IdentityRootProps, ListRow, type ListRowRootProps, Menu, type MenuItemProps, type MenuPositionerProps, type MenuRootProps, MetricStrip, type MetricStripRootProps, Nav, type NavItemProps, type NavRootProps, Panel, type PanelContentProps, type PanelGroupProps, type PanelLabelProps, type PanelRootProps, type PanelTriggerProps, PinInput, type PinInputInputProps, type PinInputRootProps, Popover, type PopoverPositionerProps, type PopoverRootProps, type PresenceState, ProfileHeader, type ProfileHeaderRootProps, Progress, type ProgressRootProps, Prompt, type PromptRootProps, type PromptStatus, Prose, type ProseRootProps, RadioGroup, type RadioGroupItemProps, type RadioGroupRootProps, RangeSlider, type RangeSliderRootProps, type RangeSliderThumbProps, Scroll, type ScrollRootProps, type ScrollViewportProps, SegmentGroup, type SegmentGroupItemProps, type SegmentGroupRootProps, Select, type SelectContentProps, type SelectItemProps, type SelectPositionerProps, type SelectRootProps, Separator, type SeparatorRootProps, Slider, type SliderContextValue, type SliderRootProps, Slot, StatusBanner, type StatusBannerRootProps, type StatusBannerTone, StickyBar, type StickyBarRootProps, Switch, type SwitchRootProps, Tabs, type TabsContentProps, type TabsRootProps, type TabsTriggerProps, Textarea, type TextareaRootProps, ThemeSwitcher, type ThemeSwitcherModeBtnProps, type ThemeSwitcherModesProps, type ThemeSwitcherRootProps, type ThemeSwitcherThemeSelectProps, Thread, type ThreadItemFace, type ThreadItemProps, type ThreadMessageState, type ThreadRootProps, Toast, ToastItem, type ToastPlacement, type ToastProviderProps, type ToastPublishOptions, type ToastRecord, type ToastRootProps, type ToastStore, type ToastViewportProps, Tooltip, type TooltipPositionerProps, type TooltipRootProps, type UseWindowedRangeOptions, asyncStatusToContentState, rowLimits, useAeonMachine, useAeonQuery, useAeonSelector, useAppNav, useAppNavMachine, useAppShellContext, useAsyncContext, useAutoGrow, useClipboardStatus, useContentContext, useFieldContext, useFileUploadCtx as useFileUpload, useFitText, useLayoutMode, useScrollContext, useScrollState, useSliderContext, useStickyBarContext, useToast, useToastStore, useWindowedRange };
@@ -6218,13 +6218,40 @@ var StickyBar = {
6218
6218
  Seam
6219
6219
  };
6220
6220
 
6221
+ // src/hooks/use-aeon-store.ts
6222
+ import { useEffect as useEffect27, useRef as useRef15, useSyncExternalStore } from "react";
6223
+ import {
6224
+ shallowEqual
6225
+ } from "@aeon-ui/primitives";
6226
+ function useAeonSelector(store, selector, equals = shallowEqual) {
6227
+ const held = useRef15(null);
6228
+ const getSelection = () => {
6229
+ const state = store.getSnapshot();
6230
+ const last = held.current;
6231
+ if (last && last.state === state && last.selector === selector) return last.value;
6232
+ const next = selector(state);
6233
+ const value = last && equals(last.value, next) ? last.value : next;
6234
+ held.current = { state, selector, value };
6235
+ return value;
6236
+ };
6237
+ return useSyncExternalStore(store.subscribe, getSelection, getSelection);
6238
+ }
6239
+ function useAeonQuery(store, slice, query) {
6240
+ const key = typeof query === "string" ? query : JSON.stringify(query);
6241
+ useEffect27(() => {
6242
+ store.send({ type: "QUERY.FETCH", slice, query });
6243
+ }, [store, slice, key]);
6244
+ const read = () => store.query(slice, query);
6245
+ return useSyncExternalStore(store.subscribe, read, read);
6246
+ }
6247
+
6221
6248
  // src/hooks/use-layout-mode.ts
6222
6249
  import { getCompactMq, layoutCompositionForMode, matchLayoutMode } from "@aeon-ui/core";
6223
- import { useEffect as useEffect27, useMemo as useMemo32, useState as useState14 } from "react";
6250
+ import { useEffect as useEffect28, useMemo as useMemo32, useState as useState14 } from "react";
6224
6251
  function useLayoutMode(spec) {
6225
6252
  const mq = useMemo32(() => getCompactMq(spec), [spec.compactMq]);
6226
6253
  const [mode, setMode] = useState14(() => matchLayoutMode(spec, mq));
6227
- useEffect27(() => {
6254
+ useEffect28(() => {
6228
6255
  const sync = () => setMode(matchLayoutMode(spec, mq));
6229
6256
  sync();
6230
6257
  mq.addEventListener("change", sync);
@@ -6330,6 +6357,8 @@ export {
6330
6357
  fieldMachine,
6331
6358
  rowLimits,
6332
6359
  useAeonMachine,
6360
+ useAeonQuery,
6361
+ useAeonSelector,
6333
6362
  useAppNav,
6334
6363
  useAppNavMachine,
6335
6364
  useAppShellContext,
@@ -0,0 +1,50 @@
1
+ import { useEffect, useRef, useSyncExternalStore } from 'react'
2
+ import {
3
+ shallowEqual,
4
+ type AeonStore,
5
+ type AnySlices,
6
+ type EntityOf,
7
+ type QueryOf,
8
+ type QueryResult,
9
+ type StoreEvent,
10
+ type StoreState,
11
+ } from '@aeon-ui/primitives'
12
+
13
+ /**
14
+ * Reads a slice of an Aeon store. Re-renders only when the selected value
15
+ * changes under `equals` (shallow by default), so a component that selects
16
+ * one entity ignores writes to every other.
17
+ */
18
+ export function useAeonSelector<S extends AnySlices, T>(
19
+ store: AeonStore<S>,
20
+ selector: (state: StoreState<S>) => T,
21
+ equals: (a: T, b: T) => boolean = shallowEqual,
22
+ ): T {
23
+ const held = useRef<{ state: StoreState<S>; selector: (state: StoreState<S>) => T; value: T } | null>(null)
24
+ const getSelection = () => {
25
+ const state = store.getSnapshot()
26
+ const last = held.current
27
+ if (last && last.state === state && last.selector === selector) return last.value
28
+ const next = selector(state)
29
+ const value = last && equals(last.value, next) ? last.value : next
30
+ held.current = { state, selector, value }
31
+ return value
32
+ }
33
+ return useSyncExternalStore(store.subscribe, getSelection, getSelection)
34
+ }
35
+
36
+ /** Fetches a query while mounted and returns its result; the entities stay in the store. */
37
+ export function useAeonQuery<S extends AnySlices, N extends keyof S & string>(
38
+ store: AeonStore<S>,
39
+ slice: N,
40
+ query: QueryOf<S[N]>,
41
+ ): QueryResult<EntityOf<S[N]>> {
42
+ const key = typeof query === 'string' ? query : JSON.stringify(query)
43
+ useEffect(() => {
44
+ store.send({ type: 'QUERY.FETCH', slice, query } as StoreEvent<S>)
45
+ // `key` stands for `query`, which callers often rebuild each render.
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, [store, slice, key])
48
+ const read = () => store.query(slice, query)
49
+ return useSyncExternalStore(store.subscribe, read, read)
50
+ }
@@ -44,6 +44,7 @@ export * from './content/index.js'
44
44
  export * from './nav/index.js'
45
45
  export * from './sticky-bar/index.js'
46
46
  export { useAeonMachine } from './hooks/use-aeon-machine.js'
47
+ export { useAeonQuery, useAeonSelector } from './hooks/use-aeon-store.js'
47
48
  export { useLayoutMode } from './hooks/use-layout-mode.js'
48
49
  export { useFitText } from './hooks/use-fit-text.js'
49
50
  export { Slot } from './utils/slot.js'