@dxos/react-ui-attention 0.9.0 → 0.9.1-staging.ee54ba693a

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.
Files changed (83) hide show
  1. package/dist/lib/browser/chunk-4HYAJ4IO.mjs +434 -0
  2. package/dist/lib/browser/chunk-4HYAJ4IO.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-I4VO2RQM.mjs → chunk-I4FDY4AZ.mjs} +92 -111
  4. package/dist/lib/browser/chunk-I4FDY4AZ.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +36 -15
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +4 -4
  9. package/dist/lib/browser/testing/index.mjs.map +2 -2
  10. package/dist/lib/browser/types/index.mjs +19 -5
  11. package/dist/lib/node-esm/{chunk-ZTUVSH4P.mjs → chunk-DLBZMHST.mjs} +92 -111
  12. package/dist/lib/node-esm/chunk-DLBZMHST.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-HWN7KJDX.mjs +436 -0
  14. package/dist/lib/node-esm/chunk-HWN7KJDX.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +36 -15
  16. package/dist/lib/node-esm/index.mjs.map +3 -3
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +4 -4
  19. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  20. package/dist/lib/node-esm/types/index.mjs +19 -5
  21. package/dist/types/src/components/AttentionGlyph/AttentionGlyph.d.ts.map +1 -1
  22. package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts +1 -1
  23. package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts.map +1 -1
  24. package/dist/types/src/components/ViewStateProvider/ViewStateProvider.d.ts +31 -0
  25. package/dist/types/src/components/ViewStateProvider/ViewStateProvider.d.ts.map +1 -0
  26. package/dist/types/src/components/ViewStateProvider/ViewStateProvider.test.d.ts +2 -0
  27. package/dist/types/src/components/ViewStateProvider/ViewStateProvider.test.d.ts.map +1 -0
  28. package/dist/types/src/components/ViewStateProvider/index.d.ts +2 -0
  29. package/dist/types/src/components/ViewStateProvider/index.d.ts.map +1 -0
  30. package/dist/types/src/components/index.d.ts +1 -1
  31. package/dist/types/src/index.d.ts +1 -0
  32. package/dist/types/src/index.d.ts.map +1 -1
  33. package/dist/types/src/selection.d.ts +10 -40
  34. package/dist/types/src/selection.d.ts.map +1 -1
  35. package/dist/types/src/selection.test.d.ts +2 -0
  36. package/dist/types/src/selection.test.d.ts.map +1 -0
  37. package/dist/types/src/types/index.d.ts +1 -0
  38. package/dist/types/src/types/index.d.ts.map +1 -1
  39. package/dist/types/src/useArticleKeyboardNavigation.d.ts.map +1 -1
  40. package/dist/types/src/view-state/backends.d.ts +24 -0
  41. package/dist/types/src/view-state/backends.d.ts.map +1 -0
  42. package/dist/types/src/view-state/backends.test.d.ts +2 -0
  43. package/dist/types/src/view-state/backends.test.d.ts.map +1 -0
  44. package/dist/types/src/view-state/index.d.ts +3 -0
  45. package/dist/types/src/view-state/index.d.ts.map +1 -0
  46. package/dist/types/src/view-state/view-state.d.ts +54 -0
  47. package/dist/types/src/view-state/view-state.d.ts.map +1 -0
  48. package/dist/types/src/view-state/view-state.test.d.ts +2 -0
  49. package/dist/types/src/view-state/view-state.test.d.ts.map +1 -0
  50. package/dist/types/src/vitest-setup.d.ts +2 -0
  51. package/dist/types/src/vitest-setup.d.ts.map +1 -0
  52. package/dist/types/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +22 -20
  54. package/src/components/AttentionGlyph/AttentionGlyph.tsx +1 -1
  55. package/src/components/AttentionProvider/AttentionProvider.tsx +3 -3
  56. package/src/components/ViewStateProvider/ViewStateProvider.test.tsx +45 -0
  57. package/src/components/ViewStateProvider/ViewStateProvider.tsx +129 -0
  58. package/src/components/ViewStateProvider/index.ts +5 -0
  59. package/src/components/index.ts +1 -1
  60. package/src/index.ts +1 -0
  61. package/src/selection.test.ts +67 -0
  62. package/src/selection.ts +39 -169
  63. package/src/testing/decorators/withAttention.ts +2 -2
  64. package/src/types/index.ts +1 -0
  65. package/src/useArticleKeyboardNavigation.ts +5 -4
  66. package/src/view-state/backends.test.ts +104 -0
  67. package/src/view-state/backends.ts +145 -0
  68. package/src/view-state/index.ts +6 -0
  69. package/src/view-state/view-state.test.ts +54 -0
  70. package/src/view-state/view-state.ts +91 -0
  71. package/src/vitest-setup.ts +6 -0
  72. package/dist/lib/browser/chunk-D2BLVJ6Z.mjs +0 -421
  73. package/dist/lib/browser/chunk-D2BLVJ6Z.mjs.map +0 -7
  74. package/dist/lib/browser/chunk-I4VO2RQM.mjs.map +0 -7
  75. package/dist/lib/node-esm/chunk-6INLBC62.mjs +0 -423
  76. package/dist/lib/node-esm/chunk-6INLBC62.mjs.map +0 -7
  77. package/dist/lib/node-esm/chunk-ZTUVSH4P.mjs.map +0 -7
  78. package/dist/types/src/components/SelectionProvider/SelectionProvider.d.ts +0 -28
  79. package/dist/types/src/components/SelectionProvider/SelectionProvider.d.ts.map +0 -1
  80. package/dist/types/src/components/SelectionProvider/index.d.ts +0 -2
  81. package/dist/types/src/components/SelectionProvider/index.d.ts.map +0 -1
  82. package/src/components/SelectionProvider/SelectionProvider.tsx +0 -174
  83. package/src/components/SelectionProvider/index.ts +0 -5
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/AttentionGlyph/AttentionGlyph.tsx", "../../../src/useArticleKeyboardNavigation.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Primitive } from '@radix-ui/react-primitive';\nimport React, { type CSSProperties, type ComponentPropsWithRef, forwardRef, useMemo } from 'react';\n\nimport { Icon, type ThemedClassName } from '@dxos/react-ui';\nimport { mx } from '@dxos/ui-theme';\n\nconst attentionGlyphStyles = mx(\n 'inline-block rounded-xs w-3 h-3 bg-transparent text-accent-text transition-colors',\n '[[data-contains-attended=true]_&]:bg-attention-contains',\n '[[data-attention=true]_&]:bg-accent-bg',\n '[[data-attention=true]_&]:text-accent-fg',\n '[[aria-current][data-attention=true]_&]:bg-accent-bg',\n '[[aria-current][data-attention=true]_&]:text-accent-fg',\n '[[aria-selected=\"true\"][data-attention=true]_&]:bg-accent-bg',\n '[[aria-selected=\"true\"][data-attention=true]_&]:text-accent-fg',\n);\n\nconst presenceIconStyles = mx('w-3 h-3');\n\nconst PresenceOne = () => {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 12 12'\n className={presenceIconStyles}\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <circle cx='6' cy='6' r='2.5' fill='currentColor' />\n </svg>\n );\n};\n\nconst PresenceMany = () => {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 12 12'\n className={presenceIconStyles}\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M6.75 8.27311C7.38815 7.72296 7.79212 6.90866 7.79212 6C7.79212 5.09134 7.38815 4.27704 6.75 3.72689C7.06722 3.58122 7.42019 3.5 7.79212 3.5C9.17283 3.5 10.2921 4.61929 10.2921 6C10.2921 7.38071 9.17283 8.5 7.79212 8.5C7.42019 8.5 7.06723 8.41878 6.75 8.27311Z'\n fill='currentColor'\n />\n <circle cx='4.25' cy='6' r='2.5' fill='currentColor' />\n </svg>\n );\n};\n\nexport const Syncing = () => {\n const animationProps = useMemo<CSSProperties>(\n () => ({\n // Synchronize animations.\n animationDelay: `-${Date.now() % 2_000}ms`,\n }),\n [],\n );\n\n return (\n <div role='status' className='flex items-center'>\n <Icon\n icon='ph--circle-notch--bold'\n size={3}\n style={animationProps}\n classNames='text-subdued animate-[spin_2s_linear_infinite]'\n />\n </div>\n );\n};\n\nexport type AttentionGlyphProps = {\n attended?: boolean;\n containsAttended?: boolean;\n syncing?: boolean;\n presence?: 'none' | 'one' | 'many';\n} & ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.span>, 'children'>>;\n\nexport const AttentionGlyph = forwardRef<HTMLSpanElement, AttentionGlyphProps>(\n ({ presence, attended, syncing, containsAttended, classNames, ...props }, forwardedRef) => {\n const icon = syncing ? (\n <Syncing />\n ) : presence === 'many' ? (\n <PresenceMany />\n ) : presence === 'one' ? (\n <PresenceOne />\n ) : null;\n\n return (\n <div className='flex group' data-attention={attended} data-contains-attended={containsAttended}>\n <span {...props} className={mx(attentionGlyphStyles, classNames)} ref={forwardedRef}>\n {icon}\n </span>\n </div>\n );\n },\n);\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { useEffect, useMemo } from 'react';\n\nimport { Keyboard } from '@dxos/keyboard';\n\nimport { useAttention } from './components';\n\n/**\n * Compute the id to select after pressing 'j' (delta = 1) or 'k' (delta = -1).\n * Clamps at the list ends — pressing 'j' on the last item keeps the last item\n * selected (vim-style), and 'k' on the first item keeps the first.\n *\n * When no current selection exists, returns the first id (for delta = 1) or the\n * last id (for delta = -1) so the user can enter the list with either key.\n */\nexport const advance = ({\n ids,\n currentId,\n delta,\n}: {\n ids: readonly string[];\n currentId: string | undefined;\n delta: 1 | -1;\n}): string | undefined => {\n if (ids.length === 0) {\n return undefined;\n }\n\n const idx = currentId ? ids.indexOf(currentId) : -1;\n if (idx === -1) {\n return delta === 1 ? ids[0] : ids[ids.length - 1];\n }\n\n const next = Math.max(0, Math.min(ids.length - 1, idx + delta));\n return ids[next];\n};\n\nexport type UseArticleKeyboardNavigationOptions<T> = {\n /** Stable id for the article (used as the keyboard context path). */\n articleId: string;\n /** Ordered list of selectable items as they appear in the article. */\n items: readonly T[];\n /** Currently-selected id, if any. */\n currentId: string | undefined;\n /** Extracts the id from an item. Defaults to `item.id`. */\n getId?: (item: T) => string;\n /** Called with the id to select when the user presses 'j' or 'k'. */\n onSelect: (id: string) => void;\n};\n\n/**\n * Wire 'j' (next) and 'k' (previous) keyboard shortcuts for an article that\n * navigates a list of items (e.g., messages, events). Bindings are scoped to\n * the article's keyboard context so they only fire while the article has attention.\n *\n * Pass the items directly; ids are derived via `getId` (defaults to `item.id`).\n * Clamps at list boundaries. Active only when the article is attended.\n */\nexport const useArticleKeyboardNavigation: {\n <T extends { id: string }>(options: UseArticleKeyboardNavigationOptions<T>): void;\n <T>(options: UseArticleKeyboardNavigationOptions<T> & { getId: (item: T) => string }): void;\n} = <T>({ articleId, items, currentId, getId, onSelect }: UseArticleKeyboardNavigationOptions<T>): void => {\n const { hasAttention } = useAttention(articleId);\n\n // `getId` is optional only when `T extends { id: string }` (enforced by the overloads above),\n // so the fallback is sound; the cast bridges the generic erased by the implementation signature.\n const ids = useMemo(() => items.map((item) => (getId ? getId(item) : (item as { id: string }).id)), [items, getId]);\n\n useEffect(() => {\n if (!hasAttention) {\n return;\n }\n\n const context = Keyboard.singleton.getContext(articleId);\n const prevContext = Keyboard.singleton.getCurrentContext();\n Keyboard.singleton.setCurrentContext(articleId);\n\n const nextBinding = {\n shortcut: 'j',\n handler: () => {\n const target = advance({ ids, currentId, delta: 1 });\n if (target !== undefined) {\n onSelect(target);\n }\n },\n data: 'Next item',\n disableInput: true,\n };\n const prevBinding = {\n shortcut: 'k',\n handler: () => {\n const target = advance({ ids, currentId, delta: -1 });\n if (target !== undefined) {\n onSelect(target);\n }\n },\n data: 'Previous item',\n disableInput: true,\n };\n\n context.bind(nextBinding);\n context.bind(prevBinding);\n\n return () => {\n context.unbind('j');\n context.unbind('k');\n // Restore the prior context if we were the ones who set it.\n if (Keyboard.singleton.getCurrentContext() === articleId) {\n Keyboard.singleton.setCurrentContext(prevContext);\n }\n };\n }, [articleId, ids, currentId, onSelect, hasAttention]);\n};\n"],
5
- "mappings": "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",
6
- "names": ["React", "forwardRef", "useMemo", "Icon", "mx", "attentionGlyphStyles", "presenceIconStyles", "PresenceOne", "svg", "width", "height", "viewBox", "className", "fill", "xmlns", "circle", "cx", "cy", "r", "PresenceMany", "path", "d", "Syncing", "animationProps", "animationDelay", "Date", "now", "div", "role", "icon", "size", "style", "classNames", "AttentionGlyph", "presence", "attended", "syncing", "containsAttended", "props", "forwardedRef", "data-attention", "data-contains-attended", "span", "ref", "useEffect", "useMemo", "Keyboard", "advance", "ids", "currentId", "delta", "length", "undefined", "idx", "indexOf", "next", "Math", "max", "min", "useArticleKeyboardNavigation", "articleId", "items", "getId", "onSelect", "hasAttention", "useAttention", "useMemo", "map", "item", "id", "useEffect", "context", "Keyboard", "singleton", "getContext", "prevContext", "getCurrentContext", "setCurrentContext", "nextBinding", "shortcut", "handler", "target", "data", "disableInput", "prevBinding", "bind", "unbind"]
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Primitive } from '@radix-ui/react-primitive';\nimport React, { type ComponentPropsWithRef, type CSSProperties, forwardRef, useMemo } from 'react';\n\nimport { Icon, type ThemedClassName } from '@dxos/react-ui';\nimport { mx } from '@dxos/ui-theme';\n\nconst attentionGlyphStyles = mx(\n 'inline-block rounded-xs w-3 h-3 bg-transparent text-accent-text transition-colors',\n '[[data-contains-attended=true]_&]:bg-attention-contains',\n '[[data-attention=true]_&]:bg-accent-bg',\n '[[data-attention=true]_&]:text-accent-fg',\n '[[aria-current][data-attention=true]_&]:bg-accent-bg',\n '[[aria-current][data-attention=true]_&]:text-accent-fg',\n '[[aria-selected=\"true\"][data-attention=true]_&]:bg-accent-bg',\n '[[aria-selected=\"true\"][data-attention=true]_&]:text-accent-fg',\n);\n\nconst presenceIconStyles = mx('w-3 h-3');\n\nconst PresenceOne = () => {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 12 12'\n className={presenceIconStyles}\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <circle cx='6' cy='6' r='2.5' fill='currentColor' />\n </svg>\n );\n};\n\nconst PresenceMany = () => {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 12 12'\n className={presenceIconStyles}\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M6.75 8.27311C7.38815 7.72296 7.79212 6.90866 7.79212 6C7.79212 5.09134 7.38815 4.27704 6.75 3.72689C7.06722 3.58122 7.42019 3.5 7.79212 3.5C9.17283 3.5 10.2921 4.61929 10.2921 6C10.2921 7.38071 9.17283 8.5 7.79212 8.5C7.42019 8.5 7.06723 8.41878 6.75 8.27311Z'\n fill='currentColor'\n />\n <circle cx='4.25' cy='6' r='2.5' fill='currentColor' />\n </svg>\n );\n};\n\nexport const Syncing = () => {\n const animationProps = useMemo<CSSProperties>(\n () => ({\n // Synchronize animations.\n animationDelay: `-${Date.now() % 2_000}ms`,\n }),\n [],\n );\n\n return (\n <div role='status' className='flex items-center'>\n <Icon\n icon='ph--circle-notch--bold'\n size={3}\n style={animationProps}\n classNames='text-subdued animate-[spin_2s_linear_infinite]'\n />\n </div>\n );\n};\n\nexport type AttentionGlyphProps = {\n attended?: boolean;\n containsAttended?: boolean;\n syncing?: boolean;\n presence?: 'none' | 'one' | 'many';\n} & ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.span>, 'children'>>;\n\nexport const AttentionGlyph = forwardRef<HTMLSpanElement, AttentionGlyphProps>(\n ({ presence, attended, syncing, containsAttended, classNames, ...props }, forwardedRef) => {\n const icon = syncing ? (\n <Syncing />\n ) : presence === 'many' ? (\n <PresenceMany />\n ) : presence === 'one' ? (\n <PresenceOne />\n ) : null;\n\n return (\n <div className='flex group' data-attention={attended} data-contains-attended={containsAttended}>\n <span {...props} className={mx(attentionGlyphStyles, classNames)} ref={forwardedRef}>\n {icon}\n </span>\n </div>\n );\n },\n);\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { useEffect, useMemo } from 'react';\n\nimport { Keyboard, nestKeyboardContext } from '@dxos/keyboard';\n\nimport { useAttention } from './components';\n\n/**\n * Compute the id to select after pressing 'j' (delta = 1) or 'k' (delta = -1).\n * Clamps at the list ends — pressing 'j' on the last item keeps the last item\n * selected (vim-style), and 'k' on the first item keeps the first.\n *\n * When no current selection exists, returns the first id (for delta = 1) or the\n * last id (for delta = -1) so the user can enter the list with either key.\n */\nexport const advance = ({\n ids,\n currentId,\n delta,\n}: {\n ids: readonly string[];\n currentId: string | undefined;\n delta: 1 | -1;\n}): string | undefined => {\n if (ids.length === 0) {\n return undefined;\n }\n\n const idx = currentId ? ids.indexOf(currentId) : -1;\n if (idx === -1) {\n return delta === 1 ? ids[0] : ids[ids.length - 1];\n }\n\n const next = Math.max(0, Math.min(ids.length - 1, idx + delta));\n return ids[next];\n};\n\nexport type UseArticleKeyboardNavigationOptions<T> = {\n /** Stable id for the article (used as the keyboard context path). */\n articleId: string;\n /** Ordered list of selectable items as they appear in the article. */\n items: readonly T[];\n /** Currently-selected id, if any. */\n currentId: string | undefined;\n /** Extracts the id from an item. Defaults to `item.id`. */\n getId?: (item: T) => string;\n /** Called with the id to select when the user presses 'j' or 'k'. */\n onSelect: (id: string) => void;\n};\n\n/**\n * Wire 'j' (next) and 'k' (previous) keyboard shortcuts for an article that\n * navigates a list of items (e.g., messages, events). Bindings are scoped to\n * the article's keyboard context so they only fire while the article has attention.\n *\n * Pass the items directly; ids are derived via `getId` (defaults to `item.id`).\n * Clamps at list boundaries. Active only when the article is attended.\n */\nexport const useArticleKeyboardNavigation: {\n <T extends { id: string }>(options: UseArticleKeyboardNavigationOptions<T>): void;\n <T>(options: UseArticleKeyboardNavigationOptions<T> & { getId: (item: T) => string }): void;\n} = <T>({ articleId, items, currentId, getId, onSelect }: UseArticleKeyboardNavigationOptions<T>): void => {\n const { hasAttention } = useAttention(articleId);\n\n // `getId` is optional only when `T extends { id: string }` (enforced by the overloads above),\n // so the fallback is sound; the cast bridges the generic erased by the implementation signature.\n const ids = useMemo(() => items.map((item) => (getId ? getId(item) : (item as { id: string }).id)), [items, getId]);\n\n useEffect(() => {\n if (!hasAttention) {\n return;\n }\n\n const contextPath = nestKeyboardContext(articleId);\n const context = Keyboard.singleton.getContext(contextPath);\n const prevContext = Keyboard.singleton.getCurrentContext();\n Keyboard.singleton.setCurrentContext(contextPath);\n\n const nextBinding = {\n shortcut: 'j',\n handler: () => {\n const target = advance({ ids, currentId, delta: 1 });\n if (target !== undefined) {\n onSelect(target);\n }\n },\n data: 'Next item',\n disableInput: true,\n };\n const prevBinding = {\n shortcut: 'k',\n handler: () => {\n const target = advance({ ids, currentId, delta: -1 });\n if (target !== undefined) {\n onSelect(target);\n }\n },\n data: 'Previous item',\n disableInput: true,\n };\n\n context.bind(nextBinding);\n context.bind(prevBinding);\n\n return () => {\n context.unbind('j');\n context.unbind('k');\n // Restore the prior context if we were the ones who set it.\n if (Keyboard.singleton.getCurrentContext() === contextPath) {\n Keyboard.singleton.setCurrentContext(prevContext);\n }\n };\n }, [articleId, ids, currentId, onSelect, hasAttention]);\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "forwardRef", "useMemo", "Icon", "mx", "attentionGlyphStyles", "presenceIconStyles", "PresenceOne", "svg", "width", "height", "viewBox", "className", "fill", "xmlns", "circle", "cx", "cy", "r", "PresenceMany", "path", "d", "Syncing", "animationProps", "animationDelay", "Date", "now", "div", "role", "icon", "size", "style", "classNames", "AttentionGlyph", "presence", "attended", "syncing", "containsAttended", "props", "forwardedRef", "data-attention", "data-contains-attended", "span", "ref", "useEffect", "useMemo", "Keyboard", "nestKeyboardContext", "advance", "ids", "currentId", "delta", "length", "undefined", "idx", "indexOf", "next", "Math", "max", "min", "useArticleKeyboardNavigation", "articleId", "items", "getId", "onSelect", "hasAttention", "useAttention", "useMemo", "map", "item", "id", "useEffect", "contextPath", "nestKeyboardContext", "context", "Keyboard", "singleton", "getContext", "prevContext", "getCurrentContext", "setCurrentContext", "nextBinding", "shortcut", "handler", "target", "data", "disableInput", "prevBinding", "bind", "unbind"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"src/attention.ts":{"bytes":25933,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true}],"format":"esm"},"src/components/AttentionGlyph/AttentionGlyph.tsx":{"bytes":9775,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/components/AttentionGlyph/index.ts":{"bytes":394,"imports":[{"path":"src/components/AttentionGlyph/AttentionGlyph.tsx","kind":"import-statement","original":"./AttentionGlyph"}],"format":"esm"},"src/components/AttentionProvider/AttentionProvider.tsx":{"bytes":18161,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"src/attention.ts","kind":"import-statement","original":"../../attention"}],"format":"esm"},"src/components/AttentionProvider/index.ts":{"bytes":401,"imports":[{"path":"src/components/AttentionProvider/AttentionProvider.tsx","kind":"import-statement","original":"./AttentionProvider"}],"format":"esm"},"src/selection.ts":{"bytes":27361,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Match","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"format":"esm"},"src/components/SelectionProvider/SelectionProvider.tsx":{"bytes":16598,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"effect/Match","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"src/selection.ts","kind":"import-statement","original":"../../selection"}],"format":"esm"},"src/components/SelectionProvider/index.ts":{"bytes":401,"imports":[{"path":"src/components/SelectionProvider/SelectionProvider.tsx","kind":"import-statement","original":"./SelectionProvider"}],"format":"esm"},"src/components/index.ts":{"bytes":616,"imports":[{"path":"src/components/AttentionGlyph/index.ts","kind":"import-statement","original":"./AttentionGlyph"},{"path":"src/components/AttentionProvider/index.ts","kind":"import-statement","original":"./AttentionProvider"},{"path":"src/components/SelectionProvider/index.ts","kind":"import-statement","original":"./SelectionProvider"}],"format":"esm"},"src/useArticleKeyboardNavigation.ts":{"bytes":11610,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"src/components/index.ts","kind":"import-statement","original":"./components"}],"format":"esm"},"src/index.ts":{"bytes":700,"imports":[{"path":"src/attention.ts","kind":"import-statement","original":"./attention"},{"path":"src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"src/selection.ts","kind":"import-statement","original":"./selection"},{"path":"src/useArticleKeyboardNavigation.ts","kind":"import-statement","original":"./useArticleKeyboardNavigation"}],"format":"esm"},"src/testing/decorators/withAttention.ts":{"bytes":3505,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/attention.ts","kind":"import-statement","original":"../../attention"},{"path":"src/components/index.ts","kind":"import-statement","original":"../../components"}],"format":"esm"},"src/testing/decorators/index.ts":{"bytes":389,"imports":[{"path":"src/testing/decorators/withAttention.ts","kind":"import-statement","original":"./withAttention"}],"format":"esm"},"src/testing/index.ts":{"bytes":382,"imports":[{"path":"src/testing/decorators/index.ts","kind":"import-statement","original":"./decorators"}],"format":"esm"},"src/types/index.ts":{"bytes":1067,"imports":[{"path":"src/attention.ts","kind":"import-statement","original":"../attention"},{"path":"src/selection.ts","kind":"import-statement","original":"../selection"}],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":11017},"dist/lib/node-esm/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-ZTUVSH4P.mjs","kind":"import-statement"},{"path":"dist/lib/node-esm/chunk-6INLBC62.mjs","kind":"import-statement"},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true}],"exports":["AttendableContainer","AttentionGlyph","AttentionManager","RootAttentionProvider","SelectionManager","SelectionProvider","SelectionSchema","Syncing","advance","defaultSelection","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment","useArticleKeyboardNavigation","useAttended","useAttention","useAttentionAttributes","useAttentionContext","useSelected","useSelectionActions","useSelectionManager"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0},"src/components/AttentionGlyph/AttentionGlyph.tsx":{"bytesInOutput":2911},"src/useArticleKeyboardNavigation.ts":{"bytesInOutput":1896}},"bytes":6058},"dist/lib/node-esm/testing/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":1876},"dist/lib/node-esm/testing/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-ZTUVSH4P.mjs","kind":"import-statement"},{"path":"dist/lib/node-esm/chunk-6INLBC62.mjs","kind":"import-statement"},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"exports":["withAttention"],"entryPoint":"src/testing/index.ts","inputs":{"src/testing/decorators/withAttention.ts":{"bytesInOutput":610},"src/testing/index.ts":{"bytesInOutput":0}},"bytes":955},"dist/lib/node-esm/chunk-ZTUVSH4P.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":17647},"dist/lib/node-esm/chunk-ZTUVSH4P.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-6INLBC62.mjs","kind":"import-statement"},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"effect/Match","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true}],"exports":["AttendableContainer","RootAttentionProvider","SelectionProvider","useAttended","useAttention","useAttentionAttributes","useAttentionContext","useSelected","useSelectionActions","useSelectionManager"],"inputs":{"src/components/AttentionProvider/AttentionProvider.tsx":{"bytesInOutput":3786},"src/components/SelectionProvider/SelectionProvider.tsx":{"bytesInOutput":3529}},"bytes":7908},"dist/lib/node-esm/types/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/lib/node-esm/types/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-6INLBC62.mjs","kind":"import-statement"}],"exports":["AttentionManager","SelectionManager","SelectionSchema","defaultSelection","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment"],"entryPoint":"src/types/index.ts","inputs":{"src/types/index.ts":{"bytesInOutput":0}},"bytes":628},"dist/lib/node-esm/chunk-6INLBC62.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":25346},"dist/lib/node-esm/chunk-6INLBC62.mjs":{"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Match","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["AttentionManager","SelectionManager","SelectionSchema","defaultSelection","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment"],"inputs":{"src/attention.ts":{"bytesInOutput":5433},"src/selection.ts":{"bytesInOutput":6966}},"bytes":12814}}}
1
+ {"inputs":{"src/attention.ts":{"bytes":25933,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true}],"format":"esm"},"src/components/AttentionGlyph/AttentionGlyph.tsx":{"bytes":9775,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/components/AttentionGlyph/index.ts":{"bytes":394,"imports":[{"path":"src/components/AttentionGlyph/AttentionGlyph.tsx","kind":"import-statement","original":"./AttentionGlyph"}],"format":"esm"},"src/components/AttentionProvider/AttentionProvider.tsx":{"bytes":18161,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"src/attention.ts","kind":"import-statement","original":"../../attention"}],"format":"esm"},"src/components/AttentionProvider/index.ts":{"bytes":401,"imports":[{"path":"src/components/AttentionProvider/AttentionProvider.tsx","kind":"import-statement","original":"./AttentionProvider"}],"format":"esm"},"src/view-state/view-state.ts":{"bytes":8199,"imports":[],"format":"esm"},"src/view-state/backends.ts":{"bytes":19210,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true}],"format":"esm"},"src/view-state/index.ts":{"bytes":470,"imports":[{"path":"src/view-state/view-state.ts","kind":"import-statement","original":"./view-state"},{"path":"src/view-state/backends.ts","kind":"import-statement","original":"./backends"}],"format":"esm"},"src/selection.ts":{"bytes":12380,"imports":[{"path":"effect/Match","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"src/view-state/index.ts","kind":"import-statement","original":"./view-state"}],"format":"esm"},"src/components/ViewStateProvider/ViewStateProvider.tsx":{"bytes":15088,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"src/selection.ts","kind":"import-statement","original":"../../selection"},{"path":"src/view-state/index.ts","kind":"import-statement","original":"../../view-state"}],"format":"esm"},"src/components/ViewStateProvider/index.ts":{"bytes":401,"imports":[{"path":"src/components/ViewStateProvider/ViewStateProvider.tsx","kind":"import-statement","original":"./ViewStateProvider"}],"format":"esm"},"src/components/index.ts":{"bytes":616,"imports":[{"path":"src/components/AttentionGlyph/index.ts","kind":"import-statement","original":"./AttentionGlyph"},{"path":"src/components/AttentionProvider/index.ts","kind":"import-statement","original":"./AttentionProvider"},{"path":"src/components/ViewStateProvider/index.ts","kind":"import-statement","original":"./ViewStateProvider"}],"format":"esm"},"src/useArticleKeyboardNavigation.ts":{"bytes":11909,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"src/components/index.ts","kind":"import-statement","original":"./components"}],"format":"esm"},"src/index.ts":{"bytes":790,"imports":[{"path":"src/attention.ts","kind":"import-statement","original":"./attention"},{"path":"src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"src/selection.ts","kind":"import-statement","original":"./selection"},{"path":"src/useArticleKeyboardNavigation.ts","kind":"import-statement","original":"./useArticleKeyboardNavigation"},{"path":"src/view-state/index.ts","kind":"import-statement","original":"./view-state"}],"format":"esm"},"src/testing/decorators/withAttention.ts":{"bytes":3505,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/attention.ts","kind":"import-statement","original":"../../attention"},{"path":"src/components/index.ts","kind":"import-statement","original":"../../components"}],"format":"esm"},"src/testing/decorators/index.ts":{"bytes":389,"imports":[{"path":"src/testing/decorators/withAttention.ts","kind":"import-statement","original":"./withAttention"}],"format":"esm"},"src/testing/index.ts":{"bytes":382,"imports":[{"path":"src/testing/decorators/index.ts","kind":"import-statement","original":"./decorators"}],"format":"esm"},"src/types/index.ts":{"bytes":1166,"imports":[{"path":"src/attention.ts","kind":"import-statement","original":"../attention"},{"path":"src/selection.ts","kind":"import-statement","original":"../selection"},{"path":"src/view-state/index.ts","kind":"import-statement","original":"../view-state"}],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":11208},"dist/lib/node-esm/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-DLBZMHST.mjs","kind":"import-statement"},{"path":"dist/lib/node-esm/chunk-HWN7KJDX.mjs","kind":"import-statement"},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true}],"exports":["AttendableContainer","AttentionGlyph","AttentionManager","LocalBackend","MemoryBackend","RootAttentionProvider","SelectionSchema","Syncing","ViewStateManager","ViewStateProvider","advance","createDefaultBackends","defaultSelection","defineViewState","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment","resolveSelection","selectionAspect","toggleSelection","useArticleKeyboardNavigation","useAttended","useAttention","useAttentionAttributes","useAttentionContext","useSelection","useSelectionActions","useViewState","useViewStateActions","useViewStateManager","useViewStateManagerOptional"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0},"src/components/AttentionGlyph/AttentionGlyph.tsx":{"bytesInOutput":2911},"src/useArticleKeyboardNavigation.ts":{"bytesInOutput":1979}},"bytes":6553},"dist/lib/node-esm/testing/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":1876},"dist/lib/node-esm/testing/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-DLBZMHST.mjs","kind":"import-statement"},{"path":"dist/lib/node-esm/chunk-HWN7KJDX.mjs","kind":"import-statement"},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"exports":["withAttention"],"entryPoint":"src/testing/index.ts","inputs":{"src/testing/decorators/withAttention.ts":{"bytesInOutput":610},"src/testing/index.ts":{"bytesInOutput":0}},"bytes":955},"dist/lib/node-esm/chunk-DLBZMHST.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15952},"dist/lib/node-esm/chunk-DLBZMHST.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-HWN7KJDX.mjs","kind":"import-statement"},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/react-hooks","kind":"import-statement","external":true}],"exports":["AttendableContainer","RootAttentionProvider","ViewStateProvider","useAttended","useAttention","useAttentionAttributes","useAttentionContext","useSelection","useSelectionActions","useViewState","useViewStateActions","useViewStateManager","useViewStateManagerOptional"],"inputs":{"src/components/AttentionProvider/AttentionProvider.tsx":{"bytesInOutput":3786},"src/components/ViewStateProvider/ViewStateProvider.tsx":{"bytesInOutput":3199}},"bytes":7712},"dist/lib/node-esm/types/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/lib/node-esm/types/index.mjs":{"imports":[{"path":"dist/lib/node-esm/chunk-HWN7KJDX.mjs","kind":"import-statement"}],"exports":["AttentionManager","LocalBackend","MemoryBackend","SelectionSchema","ViewStateManager","createDefaultBackends","defaultSelection","defineViewState","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment","resolveSelection","selectionAspect","toggleSelection"],"entryPoint":"src/types/index.ts","inputs":{"src/types/index.ts":{"bytesInOutput":0}},"bytes":898},"dist/lib/node-esm/chunk-HWN7KJDX.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":33378},"dist/lib/node-esm/chunk-HWN7KJDX.mjs":{"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"effect/Match","kind":"import-statement","external":true},{"path":"effect/Schema","kind":"import-statement","external":true}],"exports":["AttentionManager","LocalBackend","MemoryBackend","SelectionSchema","ViewStateManager","createDefaultBackends","defaultSelection","defineViewState","expandAttendableId","getAttendables","getLinkedVariant","getParentId","getSegmentId","getSelectionSet","isLinkedSegment","linkedSegment","resolveSelection","selectionAspect","toggleSelection"],"inputs":{"src/attention.ts":{"bytesInOutput":5433},"src/view-state/view-state.ts":{"bytesInOutput":1053},"src/view-state/backends.ts":{"bytesInOutput":3752},"src/selection.ts":{"bytesInOutput":2312}},"bytes":13164}}}
@@ -1,11 +1,11 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  RootAttentionProvider,
4
- SelectionProvider
5
- } from "../chunk-ZTUVSH4P.mjs";
4
+ ViewStateProvider
5
+ } from "../chunk-DLBZMHST.mjs";
6
6
  import {
7
7
  AttentionManager
8
- } from "../chunk-6INLBC62.mjs";
8
+ } from "../chunk-HWN7KJDX.mjs";
9
9
 
10
10
  // src/testing/decorators/withAttention.ts
11
11
  import { Registry, RegistryContext } from "@effect-atom/atom-react";
@@ -22,7 +22,7 @@ var withAttention = (initialAttendedId) => {
22
22
  value: registry
23
23
  }, createElement(RootAttentionProvider, {
24
24
  attention
25
- }, createElement(SelectionProvider, {}, createElement(Story))));
25
+ }, createElement(ViewStateProvider, {}, createElement(Story))));
26
26
  };
27
27
  };
28
28
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/testing/decorators/withAttention.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { Registry, RegistryContext } from '@effect-atom/atom-react';\nimport { type Decorator } from '@storybook/react';\nimport { createElement, useMemo } from 'react';\n\nimport { AttentionManager } from '../../attention';\nimport { RootAttentionProvider, SelectionProvider } from '../../components';\n\n/**\n * Storybook decorator that provides attention context.\n * @param initialAttendedId Optional ID to set as initially attended.\n */\nexport const withAttention = (initialAttendedId?: string): Decorator => {\n return (Story) => {\n const registry = useMemo(() => Registry.make(), []);\n const attention = useMemo(\n () => (initialAttendedId ? new AttentionManager(registry, [initialAttendedId]) : undefined),\n [registry],\n );\n\n return createElement(\n RegistryContext.Provider,\n { value: registry },\n createElement(RootAttentionProvider, { attention }, createElement(SelectionProvider, {}, createElement(Story))),\n );\n };\n};\n"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { Registry, RegistryContext } from '@effect-atom/atom-react';\nimport { type Decorator } from '@storybook/react';\nimport { createElement, useMemo } from 'react';\n\nimport { AttentionManager } from '../../attention';\nimport { RootAttentionProvider, ViewStateProvider } from '../../components';\n\n/**\n * Storybook decorator that provides attention context.\n * @param initialAttendedId Optional ID to set as initially attended.\n */\nexport const withAttention = (initialAttendedId?: string): Decorator => {\n return (Story) => {\n const registry = useMemo(() => Registry.make(), []);\n const attention = useMemo(\n () => (initialAttendedId ? new AttentionManager(registry, [initialAttendedId]) : undefined),\n [registry],\n );\n\n return createElement(\n RegistryContext.Provider,\n { value: registry },\n createElement(RootAttentionProvider, { attention }, createElement(ViewStateProvider, {}, createElement(Story))),\n );\n };\n};\n"],
5
5
  "mappings": ";;;;;;;;;;AAIA,SAASA,UAAUC,uBAAuB;AAE1C,SAASC,eAAeC,eAAe;AAShC,IAAMC,gBAAgB,CAACC,sBAAAA;AAC5B,SAAO,CAACC,UAAAA;AACN,UAAMC,WAAWC,QAAQ,MAAMC,SAASC,KAAI,GAAI,CAAA,CAAE;AAClD,UAAMC,YAAYH,QAChB,MAAOH,oBAAoB,IAAIO,iBAAiBL,UAAU;MAACF;KAAkB,IAAIQ,QACjF;MAACN;KAAS;AAGZ,WAAOO,cACLC,gBAAgBC,UAChB;MAAEC,OAAOV;IAAS,GAClBO,cAAcI,uBAAuB;MAAEP;IAAU,GAAGG,cAAcK,mBAAmB,CAAC,GAAGL,cAAcR,KAAAA,CAAAA,CAAAA,CAAAA;EAE3G;AACF;",
6
- "names": ["Registry", "RegistryContext", "createElement", "useMemo", "withAttention", "initialAttendedId", "Story", "registry", "useMemo", "Registry", "make", "attention", "AttentionManager", "undefined", "createElement", "RegistryContext", "Provider", "value", "RootAttentionProvider", "SelectionProvider"]
6
+ "names": ["Registry", "RegistryContext", "createElement", "useMemo", "withAttention", "initialAttendedId", "Story", "registry", "useMemo", "Registry", "make", "attention", "AttentionManager", "undefined", "createElement", "RegistryContext", "Provider", "value", "RootAttentionProvider", "ViewStateProvider"]
7
7
  }
@@ -1,9 +1,13 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  AttentionManager,
4
- SelectionManager,
4
+ LocalBackend,
5
+ MemoryBackend,
5
6
  SelectionSchema,
7
+ ViewStateManager,
8
+ createDefaultBackends,
6
9
  defaultSelection,
10
+ defineViewState,
7
11
  expandAttendableId,
8
12
  getAttendables,
9
13
  getLinkedVariant,
@@ -11,13 +15,20 @@ import {
11
15
  getSegmentId,
12
16
  getSelectionSet,
13
17
  isLinkedSegment,
14
- linkedSegment
15
- } from "../chunk-6INLBC62.mjs";
18
+ linkedSegment,
19
+ resolveSelection,
20
+ selectionAspect,
21
+ toggleSelection
22
+ } from "../chunk-HWN7KJDX.mjs";
16
23
  export {
17
24
  AttentionManager,
18
- SelectionManager,
25
+ LocalBackend,
26
+ MemoryBackend,
19
27
  SelectionSchema,
28
+ ViewStateManager,
29
+ createDefaultBackends,
20
30
  defaultSelection,
31
+ defineViewState,
21
32
  expandAttendableId,
22
33
  getAttendables,
23
34
  getLinkedVariant,
@@ -25,6 +36,9 @@ export {
25
36
  getSegmentId,
26
37
  getSelectionSet,
27
38
  isLinkedSegment,
28
- linkedSegment
39
+ linkedSegment,
40
+ resolveSelection,
41
+ selectionAspect,
42
+ toggleSelection
29
43
  };
30
44
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AttentionGlyph.d.ts","sourceRoot":"","sources":["../../../../../src/components/AttentionGlyph/AttentionGlyph.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,EAAsB,KAAK,qBAAqB,EAAuB,MAAM,OAAO,CAAC;AAEnG,OAAO,EAAQ,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAkD5D,eAAO,MAAM,OAAO,yBAmBnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;CACpC,GAAG,eAAe,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAEpF,eAAO,MAAM,cAAc,0GAkB1B,CAAC"}
1
+ {"version":3,"file":"AttentionGlyph.d.ts","sourceRoot":"","sources":["../../../../../src/components/AttentionGlyph/AttentionGlyph.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAA2C,MAAM,OAAO,CAAC;AAEnG,OAAO,EAAQ,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAkD5D,eAAO,MAAM,OAAO,yBAmBnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;CACpC,GAAG,eAAe,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAEpF,eAAO,MAAM,cAAc,0GAkB1B,CAAC"}
@@ -30,5 +30,5 @@ export type AttendableContainerProps = ThemedClassName<ComponentPropsWithRef<'di
30
30
  * or the rare cases where an attendable entity is rendered outside of either of those plugins.
31
31
  */
32
32
  declare const AttendableContainer: React.ForwardRefExoticComponent<Omit<AttendableContainerProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
33
- export { RootAttentionProvider, AttendableContainer, useAttentionContext, useAttention, useAttended, useAttentionAttributes, };
33
+ export { AttendableContainer, RootAttentionProvider, useAttended, useAttention, useAttentionAttributes, useAttentionContext, };
34
34
  //# sourceMappingURL=AttentionProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AttentionProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/AttentionProvider/AttentionProvider.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EACZ,KAAK,qBAAqB,EAE1B,KAAK,iBAAiB,EAOvB,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,KAAK,SAAS,EAAE,gBAAgB,EAAkB,MAAM,iBAAiB,CAAC;AAMnF,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAEF,QAAA,MAAiC,mBAAmB,iDAElD,CAAC;AAIH;;GAEG;AAEH,QAAA,MAAM,YAAY,kBAAmB,MAAM,KAAG,SAkB7C,CAAC;AAEF,QAAA,MAAM,WAAW,yBAgBhB,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,sBAAsB,kBAAmB,MAAM,uCAUpD,CAAC;AAEF,KAAK,0BAA0B,GAAG,iBAAiB,CAAC;IAClD,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7C,CAAC,CAAC;AAEH,QAAA,MAAM,qBAAqB,sDAAuD,0BAA0B,sBAmC3G,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,eAAe,CACpD,qBAAqB,CAAC,KAAK,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CACjE,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,8GAgBxB,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,sBAAsB,GACvB,CAAC"}
1
+ {"version":3,"file":"AttentionProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/AttentionProvider/AttentionProvider.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EACZ,KAAK,qBAAqB,EAE1B,KAAK,iBAAiB,EAOvB,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,KAAK,SAAS,EAAE,gBAAgB,EAAkB,MAAM,iBAAiB,CAAC;AAMnF,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAEF,QAAA,MAAiC,mBAAmB,iDAElD,CAAC;AAIH;;GAEG;AAEH,QAAA,MAAM,YAAY,kBAAmB,MAAM,KAAG,SAkB7C,CAAC;AAEF,QAAA,MAAM,WAAW,yBAgBhB,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,sBAAsB,kBAAmB,MAAM,uCAUpD,CAAC;AAEF,KAAK,0BAA0B,GAAG,iBAAiB,CAAC;IAClD,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7C,CAAC,CAAC;AAEH,QAAA,MAAM,qBAAqB,sDAAuD,0BAA0B,sBAmC3G,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,eAAe,CACpD,qBAAqB,CAAC,KAAK,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CACjE,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,8GAgBxB,CAAC;AAEF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,GACpB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import React, { type PropsWithChildren } from 'react';
2
+ import { type SelectionMode, type SelectionResult } from '../../selection';
3
+ import { type AspectDef, ViewStateManager } from '../../view-state';
4
+ /** Provides the per-context UI state manager. Replaces the former `SelectionProvider`. */
5
+ export declare const ViewStateProvider: ({ children, manager: managerProp, }: PropsWithChildren<{
6
+ manager?: ViewStateManager;
7
+ }>) => React.JSX.Element;
8
+ /** Access the underlying ViewStateManager from context. Throws when used outside a `ViewStateProvider`. */
9
+ export declare const useViewStateManager: () => ViewStateManager;
10
+ /** Access the ViewStateManager if a provider is present; `undefined` otherwise (e.g. isolated stories/tests). */
11
+ export declare const useViewStateManagerOptional: () => ViewStateManager | undefined;
12
+ /** Reactive read of an aspect value for a context; yields the aspect default when unset or unprovided. */
13
+ export declare const useViewState: <T>(aspect: AspectDef<T>, contextId?: string) => T;
14
+ export type UseViewStateActions<T> = {
15
+ set: (value: T) => void;
16
+ update: (fn: (prev: T) => T) => void;
17
+ clear: () => void;
18
+ };
19
+ export declare const useViewStateActions: <T>(aspect: AspectDef<T>, contextId?: string) => UseViewStateActions<T>;
20
+ /** Resolved selection value for `contextId` in the requested `mode` (default `multi`). */
21
+ export declare const useSelection: <T extends SelectionMode>(contextId?: string, mode?: T) => SelectionResult<T>;
22
+ export type UseSelectionActions = {
23
+ single: (id: string) => void;
24
+ multi: (ids: string[]) => void;
25
+ range: (from: string, to: string) => void;
26
+ toggle: (id: string) => void;
27
+ clear: () => void;
28
+ };
29
+ /** Selection mutators for a single context, built on the generic ViewState actions. */
30
+ export declare const useSelectionActions: (contextId?: string) => UseSelectionActions;
31
+ //# sourceMappingURL=ViewStateProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViewStateProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/ViewStateProvider/ViewStateProvider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAA4C,MAAM,OAAO,CAAC;AAKhG,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EAIrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,SAAS,EAAE,gBAAgB,EAAyB,MAAM,kBAAkB,CAAC;AAY3F,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,wCAG3B,iBAAiB,CAAC;IAAE,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC,sBAOnD,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,mBAAmB,QAAO,gBAItC,CAAC;AAEF,iHAAiH;AACjH,eAAO,MAAM,2BAA2B,QAAO,gBAAgB,GAAG,SAGjE,CAAC;AAEF,0GAA0G;AAC1G,eAAO,MAAM,YAAY,GAAI,CAAC,UAAW,SAAS,CAAC,CAAC,CAAC,cAAc,MAAM,KAAG,CAc3E,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;IACrC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,CAAC,UAAW,SAAS,CAAC,CAAC,CAAC,cAAc,MAAM,KAAG,mBAAmB,CAAC,CAAC,CAsBvG,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,aAAa,cAAc,MAAM,SAAQ,CAAC,KAAkB,eAAe,CAAC,CAAC,CAClD,CAAC;AAEnE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC/B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,eAAgB,MAAM,KAAG,mBAYxD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ViewStateProvider.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViewStateProvider.test.d.ts","sourceRoot":"","sources":["../../../../../src/components/ViewStateProvider/ViewStateProvider.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export * from './ViewStateProvider';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ViewStateProvider/index.ts"],"names":[],"mappings":"AAIA,cAAc,qBAAqB,CAAC"}
@@ -1,4 +1,4 @@
1
1
  export * from './AttentionGlyph';
2
2
  export * from './AttentionProvider';
3
- export * from './SelectionProvider';
3
+ export * from './ViewStateProvider';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,5 @@ export * from './attention';
2
2
  export * from './components';
3
3
  export * from './selection';
4
4
  export * from './useArticleKeyboardNavigation';
5
+ export * from './view-state';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,cAAc,CAAC"}
@@ -1,5 +1,5 @@
1
- import { Atom, type Registry } from '@effect-atom/atom-react';
2
1
  import * as Schema from 'effect/Schema';
2
+ import { type AspectDef, type ViewStateManager } from './view-state';
3
3
  export type SelectionMode = 'single' | 'multi' | 'range' | 'multi-range';
4
4
  export declare const SelectionSchema: Schema.mutable<Schema.Union<[Schema.mutable<Schema.Struct<{
5
5
  mode: Schema.Literal<["single"]>;
@@ -37,45 +37,15 @@ export type SelectionResult<T extends SelectionMode> = T extends 'single' ? stri
37
37
  from: string;
38
38
  to: string;
39
39
  }[] : never;
40
- export declare const getSelectionSet: (selectionManager: SelectionManager, contextId?: string) => Set<string>;
40
+ /** Selection state for a context, stored in memory (ephemeral, per-device session). */
41
+ export declare const selectionAspect: AspectDef<Selection>;
41
42
  /**
42
- * Manages selection state for different contexts.
43
- * Each context maintains its own selection mode and state.
43
+ * Extract the typed result for `mode` from a stored selection value, returning the requested
44
+ * mode's default when the stored value is absent or holds a different mode.
44
45
  */
45
- export declare class SelectionManager {
46
- private readonly _registry;
47
- private readonly _state;
48
- constructor(_registry: Registry.Registry, initial?: Record<string, Selection>);
49
- /**
50
- * Get the state atom for reactive access in the graph system.
51
- */
52
- get state(): Atom.Atom<{
53
- selections: Record<string, Selection>;
54
- }>;
55
- /**
56
- * Gets the current state.
57
- */
58
- getState(): {
59
- selections: Record<string, Selection>;
60
- };
61
- /**
62
- * Subscribe to changes in the selection state.
63
- */
64
- subscribe(cb: (state: {
65
- selections: Record<string, Selection>;
66
- }) => void): () => void;
67
- getSelectionContexts(): string[];
68
- getSelection(contextId: string): Selection | undefined;
69
- getSelection<T extends SelectionMode>(contextId: string, mode: T): Selection;
70
- getSelected<T extends SelectionMode>(contextId: string, mode?: T): SelectionResult<T>;
71
- updateSingle(contextId: string, id: string): void;
72
- updateMulti(contextId: string, ids: string[]): void;
73
- updateRange(contextId: string, from: string, to: string): void;
74
- updateMultiRange(contextId: string, ranges: {
75
- from: string;
76
- to: string;
77
- }[]): void;
78
- clearSelection(contextId: string): void;
79
- toggleSelection(contextId: string, id: string): void;
80
- }
46
+ export declare const resolveSelection: <T extends SelectionMode>(selection: Selection | undefined, mode: T) => SelectionResult<T>;
47
+ /** Toggle `id` within a multi selection; resets to a multi selection if the current value differs. */
48
+ export declare const toggleSelection: (selection: Selection | undefined, id: string) => Selection;
49
+ /** Union of all multi-selected ids across every selection context, plus an optional explicit id. */
50
+ export declare const getSelectionSet: (manager: ViewStateManager, contextId?: string) => Set<string>;
81
51
  //# sourceMappingURL=selection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAE9D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;AAEzE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;MAkBN,CAAC;AAEvB,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,CAAC;AAEnE,eAAO,MAAM,gBAAgB;;;;;;;;;;CAO5B,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,SAAS,QAAQ,GACrE,MAAM,GAAG,SAAS,GAClB,CAAC,SAAS,OAAO,GACf,MAAM,EAAE,GACR,CAAC,SAAS,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACxC,CAAC,SAAS,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,GAC9B,KAAK,CAAC;AAEhB,eAAO,MAAM,eAAe,qBAAsB,gBAAgB,cAAc,MAAM,gBAYrF,CAAC;AAEF;;;GAGG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAH5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2D;IAElF,YACmB,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAC7C,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAM,EAKxC;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;KAAE,CAAC,CAEhE;IAED;;OAEG;IACH,QAAQ,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;KAAE,CAEpD;IAED;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAKpF;IAED,oBAAoB,IAAI,MAAM,EAAE,CAE/B;IAED,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACvD,YAAY,CAAC,CAAC,SAAS,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IAoB7E,WAAW,CAAC,CAAC,SAAS,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,CAAgB,GAAG,eAAe,CAAC,CAAC,CAAC,CAYlG;IAED,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAShD;IAED,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAS3C;IAED,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAStD;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,QASzE;IAED,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAoBtC;IAED,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAcnD;CACF"}
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAmB,MAAM,cAAc,CAAC;AAEtF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;AAEzE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;MAkBN,CAAC;AAEvB,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,CAAC;AAEnE,eAAO,MAAM,gBAAgB;;;;;;;;;;CAO5B,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,SAAS,QAAQ,GACrE,MAAM,GAAG,SAAS,GAClB,CAAC,SAAS,OAAO,GACf,MAAM,EAAE,GACR,CAAC,SAAS,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACxC,CAAC,SAAS,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,GAC9B,KAAK,CAAC;AAEhB,uFAAuF;AACvF,eAAO,MAAM,eAAe,EAAE,SAAS,CAAC,SAAS,CAK/C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,aAAa,aAC3C,SAAS,GAAG,SAAS,QAC1B,CAAC,KACN,eAAe,CAAC,CAAC,CAUnB,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,eAAe,cAAe,SAAS,GAAG,SAAS,MAAM,MAAM,KAAG,SAG9E,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,eAAe,YAAa,gBAAgB,cAAc,MAAM,KAAG,GAAG,CAAC,MAAM,CAWzF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=selection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.test.d.ts","sourceRoot":"","sources":["../../../src/selection.test.ts"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
1
  export * from '../attention';
2
2
  export * from '../selection';
3
+ export * from '../view-state';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/types/index.ts"],"names":[],"mappings":"AAOA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/types/index.ts"],"names":[],"mappings":"AAOA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useArticleKeyboardNavigation.d.ts","sourceRoot":"","sources":["../../../src/useArticleKeyboardNavigation.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,+BAIjB;IACD,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACf,KAAG,MAAM,GAAG,SAYZ,CAAC;AAEF,MAAM,MAAM,mCAAmC,CAAC,CAAC,IAAI;IACnD,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IACpB,qCAAqC;IACrC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,EAAE;IACzC,CAAC,CAAC,SAAS;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAClF,CAAC,CAAC,EAAE,OAAO,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG;QAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAoD7F,CAAC"}
1
+ {"version":3,"file":"useArticleKeyboardNavigation.d.ts","sourceRoot":"","sources":["../../../src/useArticleKeyboardNavigation.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,+BAIjB;IACD,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACf,KAAG,MAAM,GAAG,SAYZ,CAAC;AAEF,MAAM,MAAM,mCAAmC,CAAC,CAAC,IAAI;IACnD,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IACpB,qCAAqC;IACrC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,EAAE;IACzC,CAAC,CAAC,SAAS;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAClF,CAAC,CAAC,EAAE,OAAO,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG;QAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAqD7F,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Atom, type Registry } from '@effect-atom/atom-react';
2
+ import { type AspectDef, type BackendName, type ViewStateBackend } from './view-state';
3
+ /** In-memory backend: state is ephemeral and scoped to the session (never persisted). */
4
+ export declare class MemoryBackend implements ViewStateBackend {
5
+ #private;
6
+ atom<T>(aspect: AspectDef<T>, contextId: string): Atom.Writable<T>;
7
+ contexts<T>(aspect: AspectDef<T>): string[];
8
+ }
9
+ export interface LocalBackendOptions {
10
+ readonly registry: Registry.Registry;
11
+ /** Injectable for tests; defaults to `window.localStorage`. */
12
+ readonly storage?: Storage;
13
+ }
14
+ /** localStorage-backed backend: seeds atoms from storage, persists on set, syncs across tabs. */
15
+ export declare class LocalBackend implements ViewStateBackend {
16
+ #private;
17
+ constructor({ registry, storage }: LocalBackendOptions);
18
+ atom<T>(aspect: AspectDef<T>, contextId: string): Atom.Writable<T>;
19
+ persist<T>(aspect: AspectDef<T>, contextId: string, value: T): void;
20
+ contexts<T>(aspect: AspectDef<T>): string[];
21
+ dispose(): void;
22
+ }
23
+ export declare const createDefaultBackends: (registry: Registry.Registry) => Record<BackendName, ViewStateBackend>;
24
+ //# sourceMappingURL=backends.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends.d.ts","sourceRoot":"","sources":["../../../../src/view-state/backends.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKvF,yFAAyF;AACzF,qBAAa,aAAc,YAAW,gBAAgB;;IAGpD,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CASjE;IAED,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAG1C;CACF;AAgBD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,iGAAiG;AACjG,qBAAa,YAAa,YAAW,gBAAgB;;IAUnD,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,mBAAmB,EAgBrD;IAED,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAajE;IAED,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAElE;IAED,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAe1C;IAED,OAAO,IAAI,IAAI,CAOd;CAcF;AAED,eAAO,MAAM,qBAAqB,aAAc,QAAQ,CAAC,QAAQ,KAAG,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAGtG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backends.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends.test.d.ts","sourceRoot":"","sources":["../../../../src/view-state/backends.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export * from './view-state';
2
+ export * from './backends';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/view-state/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { type Atom, type Registry } from '@effect-atom/atom-react';
2
+ import type * as Schema from 'effect/Schema';
3
+ /**
4
+ * Persistence backend identifier. `personal` (ECHO/personal-space) is reserved for a future backend.
5
+ */
6
+ export type BackendName = 'memory' | 'local';
7
+ /**
8
+ * Declares a kind of per-context UI state. The value type `T` is inferred from the schema.
9
+ */
10
+ export interface AspectDef<T> {
11
+ readonly key: string;
12
+ readonly backend: BackendName;
13
+ readonly schema: Schema.Schema<T, any>;
14
+ readonly defaultValue: () => T;
15
+ }
16
+ /**
17
+ * Identity helper that pins the value type from the schema while keeping the literal `key`/`backend`.
18
+ */
19
+ export declare const defineViewState: <T>(def: AspectDef<T>) => AspectDef<T>;
20
+ /**
21
+ * A backend produces a reactive, writable atom for each `(aspect, contextId)` pair. Backends may
22
+ * hydrate asynchronously (an ECHO backend would), yielding `aspect.defaultValue()` until loaded;
23
+ * the memory and local backends resolve synchronously.
24
+ */
25
+ export interface ViewStateBackend {
26
+ /** Stable atom for the pair; created (and seeded) on first access, cached thereafter. */
27
+ atom: <T>(aspect: AspectDef<T>, contextId: string) => Atom.Writable<T>;
28
+ /** Persist a value after the atom is updated. No-op for in-memory backends. */
29
+ persist?: <T>(aspect: AspectDef<T>, contextId: string, value: T) => void;
30
+ /** Context ids that currently hold a value for the aspect. */
31
+ contexts: <T>(aspect: AspectDef<T>) => string[];
32
+ /** Release listeners/timers (used by tests; app-lifetime managers do not call this). */
33
+ dispose?: () => void;
34
+ }
35
+ export interface ViewStateManagerOptions {
36
+ readonly registry: Registry.Registry;
37
+ readonly backends: Record<BackendName, ViewStateBackend>;
38
+ }
39
+ /**
40
+ * Routes per-context UI state to the backend declared by each aspect. Reads/writes go through the
41
+ * effect-atom registry so React hooks and graph atoms observe changes uniformly.
42
+ */
43
+ export declare class ViewStateManager {
44
+ #private;
45
+ constructor({ registry, backends }: ViewStateManagerOptions);
46
+ /** Reactive atom for `(aspect, contextId)`; pass to `registry.get` inside derived atoms/hooks. */
47
+ atom<T>(aspect: AspectDef<T>, contextId: string): Atom.Writable<T>;
48
+ get<T>(aspect: AspectDef<T>, contextId: string): T;
49
+ set<T>(aspect: AspectDef<T>, contextId: string, value: T): void;
50
+ update<T>(aspect: AspectDef<T>, contextId: string, fn: (prev: T) => T): void;
51
+ subscribe<T>(aspect: AspectDef<T>, contextId: string, cb: (value: T) => void): () => void;
52
+ contexts<T>(aspect: AspectDef<T>): string[];
53
+ }
54
+ //# sourceMappingURL=view-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-state.d.ts","sourceRoot":"","sources":["../../../../src/view-state/view-state.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAG9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,KAAG,SAAS,CAAC,CAAC,CAAQ,CAAC;AAE3E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvE,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACzE,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IAChD,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;CAC1D;AAED;;;GAGG;AACH,qBAAa,gBAAgB;;IAI3B,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,uBAAuB,EAG1D;IAED,kGAAkG;IAClG,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAEjE;IAED,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,CAEjD;IAED,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAI9D;IAED,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAE3E;IAED,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAGxF;IAED,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAE1C;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=view-state.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-state.test.d.ts","sourceRoot":"","sources":["../../../../src/view-state/view-state.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import '@testing-library/jest-dom/vitest';
2
+ //# sourceMappingURL=vitest-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest-setup.d.ts","sourceRoot":"","sources":["../../../src/vitest-setup.ts"],"names":[],"mappings":"AAKA,OAAO,kCAAkC,CAAC"}