@dxos/plugin-thread 0.7.1 → 0.7.2-staging.6d26b2a

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 (36) hide show
  1. package/dist/lib/browser/{ThreadArticle-IGDTPV3Y.mjs → ThreadArticle-Z6SU7SJW.mjs} +2 -2
  2. package/dist/lib/browser/{ThreadMain-ECGVEYNG.mjs → ThreadMain-SFTBLHNW.mjs} +2 -2
  3. package/dist/lib/browser/{chunk-OD3DA5BE.mjs → chunk-A5AARDTP.mjs} +1 -1
  4. package/dist/lib/browser/{chunk-OD3DA5BE.mjs.map → chunk-A5AARDTP.mjs.map} +1 -1
  5. package/dist/lib/browser/index.mjs +9 -16
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/node/{ThreadArticle-LV3HHHJT.cjs → ThreadArticle-QQMCCCH5.cjs} +6 -6
  9. package/dist/lib/node/{ThreadMain-ZS2PYBRX.cjs → ThreadMain-UYUGGUOM.cjs} +6 -6
  10. package/dist/lib/node/{chunk-GXREFXBX.cjs → chunk-AWJEBUB4.cjs} +4 -4
  11. package/dist/lib/node/{chunk-GXREFXBX.cjs.map → chunk-AWJEBUB4.cjs.map} +1 -1
  12. package/dist/lib/node/index.cjs +21 -28
  13. package/dist/lib/node/index.cjs.map +3 -3
  14. package/dist/lib/node/meta.json +1 -1
  15. package/dist/lib/node-esm/{ThreadArticle-3GEYBQKP.mjs → ThreadArticle-VV37UVYP.mjs} +2 -2
  16. package/dist/lib/node-esm/{ThreadMain-7ZEIVEV6.mjs → ThreadMain-RXIKQI3K.mjs} +2 -2
  17. package/dist/lib/node-esm/{chunk-7S5K2747.mjs → chunk-MANBTNSY.mjs} +1 -1
  18. package/dist/lib/node-esm/{chunk-7S5K2747.mjs.map → chunk-MANBTNSY.mjs.map} +1 -1
  19. package/dist/lib/node-esm/index.mjs +9 -16
  20. package/dist/lib/node-esm/index.mjs.map +3 -3
  21. package/dist/lib/node-esm/meta.json +1 -1
  22. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  23. package/dist/types/src/components/index.d.ts +1 -1
  24. package/dist/types/src/components/types.d.ts +2 -2
  25. package/package.json +29 -29
  26. package/src/ThreadPlugin.tsx +3 -3
  27. package/src/components/CommentsContainer.tsx +1 -1
  28. package/src/components/MessageContainer.tsx +2 -2
  29. package/src/components/ThreadComplementary.tsx +38 -49
  30. package/src/components/types.ts +2 -2
  31. /package/dist/lib/browser/{ThreadArticle-IGDTPV3Y.mjs.map → ThreadArticle-Z6SU7SJW.mjs.map} +0 -0
  32. /package/dist/lib/browser/{ThreadMain-ECGVEYNG.mjs.map → ThreadMain-SFTBLHNW.mjs.map} +0 -0
  33. /package/dist/lib/node/{ThreadArticle-LV3HHHJT.cjs.map → ThreadArticle-QQMCCCH5.cjs.map} +0 -0
  34. /package/dist/lib/node/{ThreadMain-ZS2PYBRX.cjs.map → ThreadMain-UYUGGUOM.cjs.map} +0 -0
  35. /package/dist/lib/node-esm/{ThreadArticle-3GEYBQKP.mjs.map → ThreadArticle-VV37UVYP.mjs.map} +0 -0
  36. /package/dist/lib/node-esm/{ThreadMain-7ZEIVEV6.mjs.map → ThreadMain-RXIKQI3K.mjs.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  ChatContainer
4
- } from "./chunk-7S5K2747.mjs";
4
+ } from "./chunk-MANBTNSY.mjs";
5
5
  import "./chunk-7QRGG25F.mjs";
6
6
 
7
7
  // packages/plugins/plugin-thread/src/components/ThreadArticle.tsx
@@ -16,4 +16,4 @@ var ThreadArticle_default = ThreadArticle;
16
16
  export {
17
17
  ThreadArticle_default as default
18
18
  };
19
- //# sourceMappingURL=ThreadArticle-3GEYBQKP.mjs.map
19
+ //# sourceMappingURL=ThreadArticle-VV37UVYP.mjs.map
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  ChatContainer
4
- } from "./chunk-7S5K2747.mjs";
4
+ } from "./chunk-MANBTNSY.mjs";
5
5
  import "./chunk-7QRGG25F.mjs";
6
6
 
7
7
  // packages/plugins/plugin-thread/src/components/ThreadMain.tsx
@@ -24,4 +24,4 @@ var ThreadMain_default = ThreadMain;
24
24
  export {
25
25
  ThreadMain_default as default
26
26
  };
27
- //# sourceMappingURL=ThreadMain-7ZEIVEV6.mjs.map
27
+ //# sourceMappingURL=ThreadMain-RXIKQI3K.mjs.map
@@ -408,4 +408,4 @@ export {
408
408
  ChatHeading,
409
409
  ChatContainer
410
410
  };
411
- //# sourceMappingURL=chunk-7S5K2747.mjs.map
411
+ //# sourceMappingURL=chunk-MANBTNSY.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/useStatus.ts", "../../../src/hooks/analytics.ts", "../../../src/components/ChatContainer.tsx", "../../../src/components/MessageContainer.tsx", "../../../src/components/command-extension.ts", "../../../src/util.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { type Space } from '@dxos/react-client/echo';\n\n// TODO(burdon): Generalize and factor out.\nexport const useStatus = (space?: Space, channel?: string) => {\n const [processing, setProcessing] = useState(false);\n useEffect(() => {\n if (!space || !channel) {\n return;\n }\n\n const unsubscribe = space.listen(`status/${channel}`, (status) => {\n const { event } = status.payload ?? {};\n setProcessing(event === 'processing');\n });\n\n const t = setInterval(() => {\n setProcessing((prev: any) => {\n if (typeof prev?.ts === 'number' && Date.now() - prev.ts > 30_000) {\n return undefined;\n } else {\n return prev;\n }\n });\n }, 1_000);\n\n return () => {\n unsubscribe();\n clearInterval(t);\n };\n }, [space, channel]);\n\n return processing;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useCallback } from 'react';\n\nimport { useIntentDispatcher } from '@dxos/app-framework';\nimport { type ReactiveObject } from '@dxos/echo-schema';\nimport { ObservabilityAction } from '@dxos/plugin-observability/meta';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { useOnTransition } from '@dxos/react-ui';\n\nexport const useAnalyticsCallback = (spaceId: string | undefined, name: string, meta?: any) => {\n const dispatch = useIntentDispatcher();\n\n return useCallback(\n (dynamicMeta?: any) => {\n void dispatch({\n action: ObservabilityAction.SEND_EVENT,\n data: {\n name,\n properties: { ...meta, ...dynamicMeta, spaceId },\n },\n });\n },\n [dispatch, name, meta, spaceId],\n );\n};\n\nexport const useOnEditAnalytics = (message: ReactiveObject<any>, editing: boolean) => {\n const space = getSpace(message);\n\n const onEditAnalytics = useAnalyticsCallback(space?.id, 'threads.comment-edited', {\n messageId: message.id,\n messageLength: message.text.length,\n });\n\n useOnTransition(editing, true, false, onEditAnalytics);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport { create } from '@dxos/echo-schema';\nimport { MessageType } from '@dxos/plugin-space/types';\nimport { fullyQualifiedId, getSpace, useMembers } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport { Icon, ScrollArea, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, listener } from '@dxos/react-ui-editor';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { mx } from '@dxos/react-ui-theme';\nimport { MessageTextbox, type MessageTextboxProps, Thread, ThreadFooter, threadLayout } from '@dxos/react-ui-thread';\nimport { nonNullable } from '@dxos/util';\n\nimport { MessageContainer } from './MessageContainer';\nimport { command } from './command-extension';\nimport { type ThreadContainerProps } from './types';\nimport { useStatus } from '../hooks';\nimport { THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\nexport const ChatHeading = ({ attendableId }: { attendableId?: string }) => {\n const { t } = useTranslation(THREAD_PLUGIN);\n return (\n <div role='none' className='flex items-center'>\n <StackItem.SigilButton attendableId={attendableId}>\n <Icon icon='ph--chat--regular' size={5} />\n </StackItem.SigilButton>\n <StackItem.HeadingLabel attendableId={attendableId}>{t('chat heading')}</StackItem.HeadingLabel>\n </div>\n );\n};\n\nexport const ChatContainer = ({ thread, context, current, autoFocusTextbox }: ThreadContainerProps) => {\n const identity = useIdentity()!;\n const space = getSpace(thread);\n const members = useMembers(space?.key);\n const activity = useStatus(space, fullyQualifiedId(thread));\n const { t } = useTranslation(THREAD_PLUGIN);\n // TODO(wittjosiah): This is a hack to reset the editor after a message is sent.\n const [_count, _setCount] = useState(0);\n const rerenderEditor = () => _setCount((count) => count + 1);\n const [autoFocus, setAutoFocus] = useState(autoFocusTextbox);\n const threadScrollRef = useRef<HTMLDivElement | null>(null);\n const { themeMode } = useThemeContext();\n\n const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);\n const messageRef = useRef('');\n const extensions = useMemo(\n () => [\n createBasicExtensions({ placeholder: t('message placeholder') }),\n createThemeExtensions({ themeMode }),\n listener({ onChange: (text) => (messageRef.current = text) }),\n command,\n ],\n [themeMode, _count],\n );\n\n // TODO(thure): Factor out.\n // TODO(thure): `flex-col-reverse` does not work to start the container scrolled to the end while also using\n // `ScrollArea`. This is the least-bad way I found to scroll to the end on mount. Note that 0ms was insufficient\n // for the desired effect; this is likely hardware-dependent and should be reevaluated.\n const scrollToEnd = (behavior: ScrollBehavior) =>\n setTimeout(() => threadScrollRef.current?.scrollIntoView({ behavior, block: 'end' }), 10);\n\n useLayoutEffect(() => {\n scrollToEnd('instant');\n }, []);\n\n // TODO(burdon): Change to model.\n const handleCreate: MessageTextboxProps['onSend'] = () => {\n if (!messageRef.current?.length) {\n return false;\n }\n\n thread.messages.push(\n create(MessageType, {\n sender: { identityKey: identity.identityKey.toHex() },\n timestamp: new Date().toISOString(),\n text: messageRef.current,\n context,\n }),\n );\n\n messageRef.current = '';\n setAutoFocus(true);\n scrollToEnd('smooth');\n rerenderEditor();\n return true;\n };\n\n const handleDelete = (id: string) => {\n const messageIndex = thread.messages.filter(nonNullable).findIndex((message) => message.id === id);\n if (messageIndex !== -1) {\n thread.messages.splice(messageIndex, 1);\n }\n };\n\n return (\n <Thread\n current={current}\n id={fullyQualifiedId(thread)}\n classNames='bs-full grid-rows-[1fr_min-content_min-content] overflow-hidden transition-[padding-block-end] [[data-sidebar-inline-start-state=open]_&]:lg:pbe-0'\n >\n <ScrollArea.Root classNames='col-span-2'>\n <ScrollArea.Viewport classNames='overflow-anchored after:overflow-anchor after:block after:bs-px after:-mbs-px [&>div]:min-bs-full [&>div]:!grid [&>div]:grid-rows-[1fr_0]'>\n <div role='none' className={mx(threadLayout, 'place-self-end')}>\n {thread.messages.filter(nonNullable).map((message) => (\n <MessageContainer key={message.id} message={message} members={members} onDelete={handleDelete} />\n ))}\n </div>\n {/* NOTE(thure): This can’t also be the `overflow-anchor` because `ScrollArea` injects an interceding node that contains this necessary ref’d element. */}\n <div role='none' className='bs-px -mbs-px' ref={threadScrollRef} />\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n <MessageTextbox extensions={extensions} autoFocus={autoFocus} onSend={handleCreate} {...textboxMetadata} />\n <ThreadFooter activity={activity}>{t('activity message')}</ThreadFooter>\n </Thread>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport { Check, PencilSimple, X } from '@phosphor-icons/react';\nimport React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Surface } from '@dxos/app-framework';\nimport { type MessageType } from '@dxos/plugin-space/types';\nimport { PublicKey } from '@dxos/react-client';\nimport { type EchoReactiveObject, type Expando, type SpaceMember } from '@dxos/react-client/echo';\nimport { useIdentity, type Identity } from '@dxos/react-client/halo';\nimport { Button, ButtonGroup, Tooltip, useOnTransition, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, useTextEditor } from '@dxos/react-ui-editor';\nimport { Mosaic, type MosaicTileComponent } from '@dxos/react-ui-mosaic';\nimport {\n getSize,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { MessageHeading, MessageRoot } from '@dxos/react-ui-thread';\nimport { nonNullable } from '@dxos/util';\n\nimport { command } from './command-extension';\nimport { useOnEditAnalytics } from '../hooks';\nimport { THREAD_ITEM, THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\n// TODO(thure): #8149\nconst messageControlClassNames = ['!p-1 !min-bs-0 transition-opacity', hoverableControlItem];\n\nexport const MessageContainer = ({\n message,\n members,\n onDelete,\n}: {\n message: MessageType;\n members: SpaceMember[];\n onDelete?: (id: string) => void;\n}) => {\n const senderIdentity = members.find(\n (member) => message.sender.identityKey && PublicKey.equals(member.identity.identityKey, message.sender.identityKey),\n )?.identity;\n const messageMetadata = getMessageMetadata(message.id, senderIdentity);\n const userIsAuthor = useIdentity()?.identityKey.toHex() === messageMetadata.authorId;\n const [editing, setEditing] = useState(false);\n const handleDelete = useCallback(() => onDelete?.(message.id), [message, onDelete]);\n const { t } = useTranslation(THREAD_PLUGIN);\n const editLabel = t(editing ? 'save message label' : 'edit message label');\n const deleteLabel = t('delete message label');\n\n return (\n <MessageRoot {...messageMetadata} classNames={[hoverableControls, hoverableFocusedWithinControls]}>\n <MessageHeading authorName={messageMetadata.authorName} timestamp={messageMetadata.timestamp}>\n <ButtonGroup classNames='mie-1'>\n {userIsAuthor && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}\n classNames={messageControlClassNames}\n onClick={() => setEditing((editing) => !editing)}\n >\n <span className='sr-only'>{editLabel}</span>\n {editing ? <Check className={getSize(4)} /> : <PencilSimple className={getSize(4)} />}\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content classNames='z-[21]'>\n {editLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n {onDelete && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid='thread.message.delete'\n classNames={messageControlClassNames}\n onClick={() => handleDelete()}\n >\n <span className='sr-only'>{deleteLabel}</span>\n <X className={getSize(4)} />\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content classNames='z-[21]'>\n {deleteLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n </ButtonGroup>\n </MessageHeading>\n <TextboxBlock message={message} isAuthor={userIsAuthor} editing={editing} />\n {message.parts?.filter(nonNullable).map((part, index) => <MessagePart key={index} part={part} />)}\n </MessageRoot>\n );\n};\n\nconst MessagePart = ({ part }: { part: Expando }) => {\n return (\n <Mosaic.Container id={part.id}>\n <Mosaic.DraggableTile type={THREAD_ITEM} path={part.id} item={part} Component={MessageBlockObjectTile} />\n </Mosaic.Container>\n );\n};\n\nconst TextboxBlock = ({\n message,\n isAuthor,\n editing,\n}: {\n message: MessageType;\n editing?: boolean;\n isAuthor?: boolean;\n identity?: Identity;\n}) => {\n const { themeMode } = useThemeContext();\n const inMemoryContentRef = useRef(message.text);\n\n const handleDocumentChange = useCallback((newState: string) => {\n inMemoryContentRef.current = newState;\n }, []);\n\n const saveDocumentChange = useCallback(() => {\n message.text = inMemoryContentRef.current;\n }, [message]);\n\n useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: message.text,\n extensions: [\n createBasicExtensions({ readonly: !isAuthor || !editing }),\n createThemeExtensions({ themeMode }),\n command,\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n handleDocumentChange(update.state.doc.toString());\n }\n }),\n ],\n }),\n [message.text, editing, isAuthor, themeMode, handleDocumentChange],\n );\n\n useEffect(() => {\n editing && view?.focus();\n }, [editing, view]);\n\n useOnEditAnalytics(message, !!editing);\n\n return <div role='none' ref={parentRef} className='mie-4' {...focusAttributes} />;\n};\n\nconst MessageBlockObjectTile: MosaicTileComponent<EchoReactiveObject<any>> = forwardRef(\n ({ draggableStyle, draggableProps, item, active, ref: _ref, ...props }, forwardedRef) => {\n let title = item.name ?? item.title ?? item.type ?? 'Object';\n if (typeof title !== 'string') {\n title = title?.content ?? '';\n }\n\n return (\n <div\n role='group'\n className={mx('grid col-span-3 py-1 pr-4', hoverableControls, hoverableFocusedWithinControls)}\n style={draggableStyle}\n ref={forwardedRef}\n >\n <Surface\n role='card'\n limit={1}\n data={{ content: item }}\n draggableProps={draggableProps}\n fallback={title}\n {...props}\n />\n </div>\n );\n },\n);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { type Extension } from '@codemirror/state';\n\nimport { tags } from '@dxos/react-ui-editor';\nimport { mx, tagRoot } from '@dxos/react-ui-theme';\n\n/**\n * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts\n */\nconst parser = StreamLanguage.define<{ count: number }>({\n startState: () => ({ count: 0 }),\n token: (stream, state) => {\n state.count++;\n if (stream.eatSpace()) {\n return null;\n }\n if (state.count === 1 && stream.match(/^(\\/\\w+)/)) {\n return 'tagName';\n }\n stream.next();\n return null;\n },\n});\n\nconst styles = HighlightStyle.define([\n {\n tag: tags.tagName,\n class: mx(tagRoot({ palette: 'cyan' }), 'text-baseText font-medium'),\n },\n]);\n\nexport const command: Extension = [parser, syntaxHighlighting(styles)];\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { generateName } from '@dxos/display-name';\nimport { type PublicKey } from '@dxos/react-client';\nimport { type Identity } from '@dxos/react-client/halo';\nimport { type MessageMetadata } from '@dxos/react-ui-thread';\nimport { hexToFallback } from '@dxos/util';\n\nexport type MessagePropertiesProvider = (identityKey: PublicKey | undefined) => MessageMetadata;\n\nexport const getMessageMetadata = (id: string, identity?: Identity): MessageMetadata => {\n const fallback = hexToFallback(identity?.identityKey.toHex() ?? '0');\n return {\n id,\n authorId: identity?.identityKey.toHex(),\n authorName:\n identity?.profile?.displayName ??\n (identity?.identityKey ? generateName(identity.identityKey.toHex()) : undefined),\n authorAvatarProps: {\n hue: identity?.profile?.data?.hue ?? fallback.hue,\n emoji: identity?.profile?.data?.emoji ?? fallback.emoji,\n },\n };\n};\n"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { type Space } from '@dxos/react-client/echo';\n\n// TODO(burdon): Generalize and factor out.\nexport const useStatus = (space?: Space, channel?: string) => {\n const [processing, setProcessing] = useState(false);\n useEffect(() => {\n if (!space || !channel) {\n return;\n }\n\n const unsubscribe = space.listen(`status/${channel}`, (status) => {\n const { event } = status.payload ?? {};\n setProcessing(event === 'processing');\n });\n\n const t = setInterval(() => {\n setProcessing((prev: any) => {\n if (typeof prev?.ts === 'number' && Date.now() - prev.ts > 30_000) {\n return undefined;\n } else {\n return prev;\n }\n });\n }, 1_000);\n\n return () => {\n unsubscribe();\n clearInterval(t);\n };\n }, [space, channel]);\n\n return processing;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useCallback } from 'react';\n\nimport { useIntentDispatcher } from '@dxos/app-framework';\nimport { type ReactiveObject } from '@dxos/echo-schema';\nimport { ObservabilityAction } from '@dxos/plugin-observability/meta';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { useOnTransition } from '@dxos/react-ui';\n\nexport const useAnalyticsCallback = (spaceId: string | undefined, name: string, meta?: any) => {\n const dispatch = useIntentDispatcher();\n\n return useCallback(\n (dynamicMeta?: any) => {\n void dispatch({\n action: ObservabilityAction.SEND_EVENT,\n data: {\n name,\n properties: { ...meta, ...dynamicMeta, spaceId },\n },\n });\n },\n [dispatch, name, meta, spaceId],\n );\n};\n\nexport const useOnEditAnalytics = (message: ReactiveObject<any>, editing: boolean) => {\n const space = getSpace(message);\n\n const onEditAnalytics = useAnalyticsCallback(space?.id, 'threads.comment-edited', {\n messageId: message.id,\n messageLength: message.text.length,\n });\n\n useOnTransition(editing, true, false, onEditAnalytics);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport { create } from '@dxos/echo-schema';\nimport { MessageType } from '@dxos/plugin-space/types';\nimport { fullyQualifiedId, getSpace, useMembers } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport { Icon, ScrollArea, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, listener } from '@dxos/react-ui-editor';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { mx } from '@dxos/react-ui-theme';\nimport { MessageTextbox, type MessageTextboxProps, Thread, ThreadFooter, threadLayout } from '@dxos/react-ui-thread';\nimport { nonNullable } from '@dxos/util';\n\nimport { MessageContainer } from './MessageContainer';\nimport { command } from './command-extension';\nimport { type ThreadContainerProps } from './types';\nimport { useStatus } from '../hooks';\nimport { THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\nexport const ChatHeading = ({ attendableId }: { attendableId?: string }) => {\n const { t } = useTranslation(THREAD_PLUGIN);\n return (\n <div role='none' className='flex items-center'>\n <StackItem.SigilButton attendableId={attendableId}>\n <Icon icon='ph--chat--regular' size={5} />\n </StackItem.SigilButton>\n <StackItem.HeadingLabel attendableId={attendableId}>{t('chat heading')}</StackItem.HeadingLabel>\n </div>\n );\n};\n\nexport const ChatContainer = ({ thread, context, current, autoFocusTextbox }: ThreadContainerProps) => {\n const identity = useIdentity()!;\n const space = getSpace(thread);\n const members = useMembers(space?.key);\n const activity = useStatus(space, fullyQualifiedId(thread));\n const { t } = useTranslation(THREAD_PLUGIN);\n // TODO(wittjosiah): This is a hack to reset the editor after a message is sent.\n const [_count, _setCount] = useState(0);\n const rerenderEditor = () => _setCount((count) => count + 1);\n const [autoFocus, setAutoFocus] = useState(autoFocusTextbox);\n const threadScrollRef = useRef<HTMLDivElement | null>(null);\n const { themeMode } = useThemeContext();\n\n const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);\n const messageRef = useRef('');\n const extensions = useMemo(\n () => [\n createBasicExtensions({ placeholder: t('message placeholder') }),\n createThemeExtensions({ themeMode }),\n listener({ onChange: (text) => (messageRef.current = text) }),\n command,\n ],\n [themeMode, _count],\n );\n\n // TODO(thure): Factor out.\n // TODO(thure): `flex-col-reverse` does not work to start the container scrolled to the end while also using\n // `ScrollArea`. This is the least-bad way I found to scroll to the end on mount. Note that 0ms was insufficient\n // for the desired effect; this is likely hardware-dependent and should be reevaluated.\n const scrollToEnd = (behavior: ScrollBehavior) =>\n setTimeout(() => threadScrollRef.current?.scrollIntoView({ behavior, block: 'end' }), 10);\n\n useLayoutEffect(() => {\n scrollToEnd('instant');\n }, []);\n\n // TODO(burdon): Change to model.\n const handleCreate: MessageTextboxProps['onSend'] = () => {\n if (!messageRef.current?.length) {\n return false;\n }\n\n thread.messages.push(\n create(MessageType, {\n sender: { identityKey: identity.identityKey.toHex() },\n timestamp: new Date().toISOString(),\n text: messageRef.current,\n context,\n }),\n );\n\n messageRef.current = '';\n setAutoFocus(true);\n scrollToEnd('smooth');\n rerenderEditor();\n return true;\n };\n\n const handleDelete = (id: string) => {\n const messageIndex = thread.messages.filter(nonNullable).findIndex((message) => message.id === id);\n if (messageIndex !== -1) {\n thread.messages.splice(messageIndex, 1);\n }\n };\n\n return (\n <Thread\n current={current}\n id={fullyQualifiedId(thread)}\n classNames='bs-full grid-rows-[1fr_min-content_min-content] overflow-hidden transition-[padding-block-end] [[data-sidebar-inline-start-state=open]_&]:lg:pbe-0'\n >\n <ScrollArea.Root classNames='col-span-2'>\n <ScrollArea.Viewport classNames='overflow-anchored after:overflow-anchor after:block after:bs-px after:-mbs-px [&>div]:min-bs-full [&>div]:!grid [&>div]:grid-rows-[1fr_0]'>\n <div role='none' className={mx(threadLayout, 'place-self-end')}>\n {thread.messages.filter(nonNullable).map((message) => (\n <MessageContainer key={message.id} message={message} members={members} onDelete={handleDelete} />\n ))}\n </div>\n {/* NOTE(thure): This can’t also be the `overflow-anchor` because `ScrollArea` injects an interceding node that contains this necessary ref’d element. */}\n <div role='none' className='bs-px -mbs-px' ref={threadScrollRef} />\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n <MessageTextbox extensions={extensions} autoFocus={autoFocus} onSend={handleCreate} {...textboxMetadata} />\n <ThreadFooter activity={activity}>{t('activity message')}</ThreadFooter>\n </Thread>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport { Check, PencilSimple, X } from '@phosphor-icons/react';\nimport React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Surface } from '@dxos/app-framework';\nimport { type MessageType } from '@dxos/plugin-space/types';\nimport { PublicKey } from '@dxos/react-client';\nimport { type ReactiveEchoObject, type Expando, type SpaceMember } from '@dxos/react-client/echo';\nimport { useIdentity, type Identity } from '@dxos/react-client/halo';\nimport { Button, ButtonGroup, Tooltip, useOnTransition, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, useTextEditor } from '@dxos/react-ui-editor';\nimport { Mosaic, type MosaicTileComponent } from '@dxos/react-ui-mosaic';\nimport {\n getSize,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { MessageHeading, MessageRoot } from '@dxos/react-ui-thread';\nimport { nonNullable } from '@dxos/util';\n\nimport { command } from './command-extension';\nimport { useOnEditAnalytics } from '../hooks';\nimport { THREAD_ITEM, THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\n// TODO(thure): #8149\nconst messageControlClassNames = ['!p-1 !min-bs-0 transition-opacity', hoverableControlItem];\n\nexport const MessageContainer = ({\n message,\n members,\n onDelete,\n}: {\n message: MessageType;\n members: SpaceMember[];\n onDelete?: (id: string) => void;\n}) => {\n const senderIdentity = members.find(\n (member) => message.sender.identityKey && PublicKey.equals(member.identity.identityKey, message.sender.identityKey),\n )?.identity;\n const messageMetadata = getMessageMetadata(message.id, senderIdentity);\n const userIsAuthor = useIdentity()?.identityKey.toHex() === messageMetadata.authorId;\n const [editing, setEditing] = useState(false);\n const handleDelete = useCallback(() => onDelete?.(message.id), [message, onDelete]);\n const { t } = useTranslation(THREAD_PLUGIN);\n const editLabel = t(editing ? 'save message label' : 'edit message label');\n const deleteLabel = t('delete message label');\n\n return (\n <MessageRoot {...messageMetadata} classNames={[hoverableControls, hoverableFocusedWithinControls]}>\n <MessageHeading authorName={messageMetadata.authorName} timestamp={messageMetadata.timestamp}>\n <ButtonGroup classNames='mie-1'>\n {userIsAuthor && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}\n classNames={messageControlClassNames}\n onClick={() => setEditing((editing) => !editing)}\n >\n <span className='sr-only'>{editLabel}</span>\n {editing ? <Check className={getSize(4)} /> : <PencilSimple className={getSize(4)} />}\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content classNames='z-[21]'>\n {editLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n {onDelete && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid='thread.message.delete'\n classNames={messageControlClassNames}\n onClick={() => handleDelete()}\n >\n <span className='sr-only'>{deleteLabel}</span>\n <X className={getSize(4)} />\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content classNames='z-[21]'>\n {deleteLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n </ButtonGroup>\n </MessageHeading>\n <TextboxBlock message={message} isAuthor={userIsAuthor} editing={editing} />\n {message.parts?.filter(nonNullable).map((part, index) => <MessagePart key={index} part={part} />)}\n </MessageRoot>\n );\n};\n\nconst MessagePart = ({ part }: { part: Expando }) => {\n return (\n <Mosaic.Container id={part.id}>\n <Mosaic.DraggableTile type={THREAD_ITEM} path={part.id} item={part} Component={MessageBlockObjectTile} />\n </Mosaic.Container>\n );\n};\n\nconst TextboxBlock = ({\n message,\n isAuthor,\n editing,\n}: {\n message: MessageType;\n editing?: boolean;\n isAuthor?: boolean;\n identity?: Identity;\n}) => {\n const { themeMode } = useThemeContext();\n const inMemoryContentRef = useRef(message.text);\n\n const handleDocumentChange = useCallback((newState: string) => {\n inMemoryContentRef.current = newState;\n }, []);\n\n const saveDocumentChange = useCallback(() => {\n message.text = inMemoryContentRef.current;\n }, [message]);\n\n useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: message.text,\n extensions: [\n createBasicExtensions({ readonly: !isAuthor || !editing }),\n createThemeExtensions({ themeMode }),\n command,\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n handleDocumentChange(update.state.doc.toString());\n }\n }),\n ],\n }),\n [message.text, editing, isAuthor, themeMode, handleDocumentChange],\n );\n\n useEffect(() => {\n editing && view?.focus();\n }, [editing, view]);\n\n useOnEditAnalytics(message, !!editing);\n\n return <div role='none' ref={parentRef} className='mie-4' {...focusAttributes} />;\n};\n\nconst MessageBlockObjectTile: MosaicTileComponent<ReactiveEchoObject<any>> = forwardRef(\n ({ draggableStyle, draggableProps, item, active, ref: _ref, ...props }, forwardedRef) => {\n let title = item.name ?? item.title ?? item.type ?? 'Object';\n if (typeof title !== 'string') {\n title = title?.content ?? '';\n }\n\n return (\n <div\n role='group'\n className={mx('grid col-span-3 py-1 pr-4', hoverableControls, hoverableFocusedWithinControls)}\n style={draggableStyle}\n ref={forwardedRef}\n >\n <Surface\n role='card'\n limit={1}\n data={{ content: item }}\n draggableProps={draggableProps}\n fallback={title}\n {...props}\n />\n </div>\n );\n },\n);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { type Extension } from '@codemirror/state';\n\nimport { tags } from '@dxos/react-ui-editor';\nimport { mx, tagRoot } from '@dxos/react-ui-theme';\n\n/**\n * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts\n */\nconst parser = StreamLanguage.define<{ count: number }>({\n startState: () => ({ count: 0 }),\n token: (stream, state) => {\n state.count++;\n if (stream.eatSpace()) {\n return null;\n }\n if (state.count === 1 && stream.match(/^(\\/\\w+)/)) {\n return 'tagName';\n }\n stream.next();\n return null;\n },\n});\n\nconst styles = HighlightStyle.define([\n {\n tag: tags.tagName,\n class: mx(tagRoot({ palette: 'cyan' }), 'text-baseText font-medium'),\n },\n]);\n\nexport const command: Extension = [parser, syntaxHighlighting(styles)];\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { generateName } from '@dxos/display-name';\nimport { type PublicKey } from '@dxos/react-client';\nimport { type Identity } from '@dxos/react-client/halo';\nimport { type MessageMetadata } from '@dxos/react-ui-thread';\nimport { hexToFallback } from '@dxos/util';\n\nexport type MessagePropertiesProvider = (identityKey: PublicKey | undefined) => MessageMetadata;\n\nexport const getMessageMetadata = (id: string, identity?: Identity): MessageMetadata => {\n const fallback = hexToFallback(identity?.identityKey.toHex() ?? '0');\n return {\n id,\n authorId: identity?.identityKey.toHex(),\n authorName:\n identity?.profile?.displayName ??\n (identity?.identityKey ? generateName(identity.identityKey.toHex()) : undefined),\n authorAvatarProps: {\n hue: identity?.profile?.data?.hue ?? fallback.hue,\n emoji: identity?.profile?.data?.emoji ?? fallback.emoji,\n },\n };\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["useEffect", "useState", "useStatus", "space", "channel", "processing", "setProcessing", "useState", "useEffect", "unsubscribe", "listen", "status", "event", "payload", "t", "setInterval", "prev", "ts", "Date", "now", "undefined", "clearInterval", "useCallback", "useIntentDispatcher", "ObservabilityAction", "getSpace", "useOnTransition", "useAnalyticsCallback", "spaceId", "name", "meta", "dispatch", "useIntentDispatcher", "useCallback", "dynamicMeta", "action", "ObservabilityAction", "SEND_EVENT", "data", "properties", "useOnEditAnalytics", "message", "editing", "space", "getSpace", "onEditAnalytics", "id", "messageId", "messageLength", "text", "length", "useOnTransition", "React", "useLayoutEffect", "useMemo", "useRef", "useState", "create", "MessageType", "fullyQualifiedId", "getSpace", "useMembers", "useIdentity", "Icon", "ScrollArea", "useThemeContext", "useTranslation", "createBasicExtensions", "createThemeExtensions", "listener", "StackItem", "mx", "MessageTextbox", "Thread", "ThreadFooter", "threadLayout", "nonNullable", "EditorView", "Check", "PencilSimple", "X", "React", "forwardRef", "useCallback", "useEffect", "useRef", "useState", "Surface", "PublicKey", "useIdentity", "Button", "ButtonGroup", "Tooltip", "useOnTransition", "useThemeContext", "useTranslation", "createBasicExtensions", "createThemeExtensions", "useTextEditor", "Mosaic", "getSize", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "MessageHeading", "MessageRoot", "nonNullable", "StreamLanguage", "HighlightStyle", "syntaxHighlighting", "tags", "mx", "tagRoot", "parser", "StreamLanguage", "define", "startState", "count", "token", "stream", "state", "eatSpace", "match", "next", "styles", "HighlightStyle", "tag", "tags", "tagName", "class", "mx", "tagRoot", "palette", "command", "syntaxHighlighting", "generateName", "hexToFallback", "getMessageMetadata", "id", "identity", "fallback", "hexToFallback", "identityKey", "toHex", "authorId", "authorName", "profile", "displayName", "generateName", "undefined", "authorAvatarProps", "hue", "data", "emoji", "messageControlClassNames", "hoverableControlItem", "MessageContainer", "message", "members", "onDelete", "senderIdentity", "find", "member", "sender", "identityKey", "PublicKey", "equals", "identity", "messageMetadata", "getMessageMetadata", "id", "userIsAuthor", "useIdentity", "toHex", "authorId", "editing", "setEditing", "useState", "handleDelete", "useCallback", "t", "useTranslation", "THREAD_PLUGIN", "editLabel", "deleteLabel", "MessageRoot", "classNames", "hoverableControls", "hoverableFocusedWithinControls", "MessageHeading", "authorName", "timestamp", "ButtonGroup", "Tooltip", "Root", "Trigger", "asChild", "Button", "variant", "data-testid", "onClick", "span", "className", "Check", "getSize", "PencilSimple", "Portal", "Content", "Arrow", "X", "TextboxBlock", "isAuthor", "parts", "filter", "nonNullable", "map", "part", "index", "MessagePart", "key", "Mosaic", "Container", "DraggableTile", "type", "THREAD_ITEM", "path", "item", "Component", "MessageBlockObjectTile", "themeMode", "useThemeContext", "inMemoryContentRef", "useRef", "text", "handleDocumentChange", "newState", "current", "saveDocumentChange", "useOnTransition", "parentRef", "focusAttributes", "view", "useTextEditor", "initialValue", "extensions", "createBasicExtensions", "readonly", "createThemeExtensions", "command", "EditorView", "updateListener", "of", "update", "docChanged", "state", "doc", "toString", "useEffect", "focus", "useOnEditAnalytics", "div", "role", "ref", "forwardRef", "draggableStyle", "draggableProps", "active", "_ref", "props", "forwardedRef", "title", "name", "content", "mx", "style", "Surface", "limit", "data", "fallback", "ChatHeading", "attendableId", "t", "useTranslation", "THREAD_PLUGIN", "React", "div", "role", "className", "StackItem", "SigilButton", "Icon", "icon", "size", "HeadingLabel", "ChatContainer", "thread", "context", "current", "autoFocusTextbox", "identity", "useIdentity", "space", "getSpace", "members", "useMembers", "key", "activity", "useStatus", "fullyQualifiedId", "_count", "_setCount", "useState", "rerenderEditor", "count", "autoFocus", "setAutoFocus", "threadScrollRef", "useRef", "themeMode", "useThemeContext", "textboxMetadata", "getMessageMetadata", "messageRef", "extensions", "useMemo", "createBasicExtensions", "placeholder", "createThemeExtensions", "listener", "onChange", "text", "command", "scrollToEnd", "behavior", "setTimeout", "scrollIntoView", "block", "useLayoutEffect", "handleCreate", "length", "messages", "push", "create", "MessageType", "sender", "identityKey", "toHex", "timestamp", "Date", "toISOString", "handleDelete", "id", "messageIndex", "filter", "nonNullable", "findIndex", "message", "splice", "Thread", "classNames", "ScrollArea", "Root", "Viewport", "mx", "threadLayout", "map", "MessageContainer", "onDelete", "ref", "Scrollbar", "Thumb", "MessageTextbox", "onSend", "ThreadFooter"]
7
7
  }
@@ -11,7 +11,7 @@ import {
11
11
  useAnalyticsCallback,
12
12
  useOnEditAnalytics,
13
13
  useStatus
14
- } from "./chunk-7S5K2747.mjs";
14
+ } from "./chunk-MANBTNSY.mjs";
15
15
  import {
16
16
  THREAD_ITEM,
17
17
  THREAD_PLUGIN,
@@ -229,7 +229,7 @@ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showReso
229
229
  });
230
230
  }) : /* @__PURE__ */ React2.createElement("div", {
231
231
  role: "alert",
232
- className: mx2(descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
232
+ className: mx2(descriptionText, "place-self-center border border-dashed border-unAccent rounded-lg text-center p-4 m-4")
233
233
  }, /* @__PURE__ */ React2.createElement("h2", {
234
234
  className: "mbe-2 font-medium text-baseText"
235
235
  }, t("no comments title")), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement(Trans, {
@@ -247,7 +247,6 @@ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showReso
247
247
  import React3, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
248
248
  import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
249
249
  import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
250
- import { ScrollArea } from "@dxos/react-ui";
251
250
  import { useAttended } from "@dxos/react-ui-attention";
252
251
  import { nonNullable as nonNullable2 } from "@dxos/util";
253
252
  var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
@@ -287,12 +286,7 @@ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads
287
286
  ]);
288
287
  const attended = useAttended();
289
288
  const qualifiedSubjectId = fullyQualifiedId3(subject);
290
- return /* @__PURE__ */ React3.createElement("div", {
291
- role: "none",
292
- className: "contents"
293
- }, /* @__PURE__ */ React3.createElement(ScrollArea.Root, {
294
- classNames: "row-span-2"
295
- }, /* @__PURE__ */ React3.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React3.createElement(CommentsContainer, {
289
+ return /* @__PURE__ */ React3.createElement(CommentsContainer, {
296
290
  threads: threads2,
297
291
  detached: detachedIds,
298
292
  currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
@@ -348,10 +342,7 @@ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads
348
342
  }
349
343
  });
350
344
  }
351
- }), /* @__PURE__ */ React3.createElement("div", {
352
- role: "none",
353
- className: "bs-10"
354
- }), /* @__PURE__ */ React3.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React3.createElement(ScrollArea.Thumb, null)))));
345
+ });
355
346
  };
356
347
 
357
348
  // packages/plugins/plugin-thread/src/components/ThreadSettings.tsx
@@ -369,8 +360,8 @@ var ThreadSettings = ({ settings }) => {
369
360
  };
370
361
 
371
362
  // packages/plugins/plugin-thread/src/components/index.ts
372
- var ThreadMain = lazy(() => import("./ThreadMain-7ZEIVEV6.mjs"));
373
- var ThreadArticle = lazy(() => import("./ThreadArticle-3GEYBQKP.mjs"));
363
+ var ThreadMain = lazy(() => import("./ThreadMain-RXIKQI3K.mjs"));
364
+ var ThreadArticle = lazy(() => import("./ThreadArticle-VV37UVYP.mjs"));
374
365
 
375
366
  // packages/plugins/plugin-thread/src/extensions/threads.ts
376
367
  import { EditorView } from "@codemirror/view";
@@ -645,7 +636,9 @@ var ThreadPlugin = () => {
645
636
  }
646
637
  const object = toSignal((onChange) => {
647
638
  const timeout = setTimeout(async () => {
648
- await space?.db.loadObjectById(objectId);
639
+ await space?.db.query({
640
+ id: objectId
641
+ }).first();
649
642
  onChange();
650
643
  });
651
644
  return () => clearTimeout(timeout);