From 8a3e0f718b04c6ba42bd43039df1dbc89da67615 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 25 Nov 2024 12:04:48 -0600 Subject: [PATCH 01/61] Component APIs initial pass --- specs/chat-components/README.md | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 specs/chat-components/README.md diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md new file mode 100644 index 0000000000..bc50535ac5 --- /dev/null +++ b/specs/chat-components/README.md @@ -0,0 +1,55 @@ +spright-ai-chat-text-bubble + Props/Attrs + actor: AIChatActor - controls corner rounding, expected by conversation. Always 'user', not settable + value: string (support newlines) + timestamp: date string? (not yet, might belong to conversation) + Slots + not needed yet, could use for label/a11y + +spright-ai-chat-rich-text-bubble? + Props/Attrs + actor - Always 'bot', not settable + markdown? + +spright-ai-chat-content-bubble? + Props/Attrs + actor - Always 'bot', not settable + Slots + content - arbitrary HTML + +spright-ai-chat-prompt-buttons - lays out buttons + Props/Attrs + actor: always 'system', not settable + Slots + buttons + +spright-ai-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner + Props/Attrs + spinner-visible + Slots + child order and 'actor' attribute determine layout + +spright-ai-chat-toolbar - top toolbar with buttons + +spright-ai-chat-input-toolbar - bottom toolbar with buttons, text input + Props/Attrs + add-chat-button-disabled + add-chat-button-disabled + text-prompt-button-hidden + text-prompt-button-hidden + text-input-field-disabled + text-input-field-hidden + text-input-field-placeholder + text-input-button-disabled + text-input-button-hidden + attach-button-disabled + attach-button-hidden + Events + text-input-change + text-input-button-click + +spright-ai-chat-window - lays out conversation and toolbar. Probably no logic + Slots + default slot for toolbar, conversation, bottom toolbar? + +AIChatActor = 'user' | 'bot' | 'system' \ No newline at end of file From 53d8a8301ca11506b05db0f9e325e77efa11305e Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 25 Nov 2024 12:10:24 -0600 Subject: [PATCH 02/61] Copy rectange and rename ai-chat-text-bubble --- .../src/ai-chat-text-bubble/index.ts | 23 +++++++++++++ .../src/ai-chat-text-bubble/styles.ts | 34 +++++++++++++++++++ .../src/ai-chat-text-bubble/template.ts | 3 ++ .../tests/ai-chat-text-bubble.spec.ts | 34 +++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 packages/spright-components/src/ai-chat-text-bubble/index.ts create mode 100644 packages/spright-components/src/ai-chat-text-bubble/styles.ts create mode 100644 packages/spright-components/src/ai-chat-text-bubble/template.ts create mode 100644 packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts diff --git a/packages/spright-components/src/ai-chat-text-bubble/index.ts b/packages/spright-components/src/ai-chat-text-bubble/index.ts new file mode 100644 index 0000000000..3579f24ea2 --- /dev/null +++ b/packages/spright-components/src/ai-chat-text-bubble/index.ts @@ -0,0 +1,23 @@ +import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; +import { styles } from './styles'; +import { template } from './template'; + +declare global { + interface HTMLElementTagNameMap { + 'spright-ai-chat-text-bubble': AIChatTextBubble; + } +} + +/** + * A Spright demo component (not for production use) + */ +export class AIChatTextBubble extends FoundationElement {} + +const sprightAIChatTextBubble = Rectangle.compose({ + baseName: 'ai-chat-text-bubble', + template, + styles +}); + +DesignSystem.getOrCreate().withPrefix('spright').register(sprightAIChatTextBubble()); +export const aiChatTextBubbleTag = 'spright-ai-chat-text-bubble'; diff --git a/packages/spright-components/src/ai-chat-text-bubble/styles.ts b/packages/spright-components/src/ai-chat-text-bubble/styles.ts new file mode 100644 index 0000000000..be412771ca --- /dev/null +++ b/packages/spright-components/src/ai-chat-text-bubble/styles.ts @@ -0,0 +1,34 @@ +import { css } from '@microsoft/fast-element'; +import { + bodyDisabledFontColor, + bodyFont, + bodyFontColor, + borderHoverColor, + borderRgbPartialColor +} from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; +import { display } from '../utilities/style/display'; + +export const styles = css` + ${display('inline-block')} + + :host { + border: 2px solid ${borderHoverColor}; + } + + :host(:hover) { + border-width: 4px; + } + + :host([disabled]) { + border-color: rgba(${borderRgbPartialColor}, 0.2); + } + + slot { + font: ${bodyFont}; + color: ${bodyFontColor}; + } + + :host([disabled]) slot { + color: ${bodyDisabledFontColor}; + } +`; diff --git a/packages/spright-components/src/ai-chat-text-bubble/template.ts b/packages/spright-components/src/ai-chat-text-bubble/template.ts new file mode 100644 index 0000000000..3a853b0864 --- /dev/null +++ b/packages/spright-components/src/ai-chat-text-bubble/template.ts @@ -0,0 +1,3 @@ +import { html } from '@microsoft/fast-element'; + +export const template = html``; diff --git a/packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts b/packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts new file mode 100644 index 0000000000..616d95e986 --- /dev/null +++ b/packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts @@ -0,0 +1,34 @@ +import { html } from '@microsoft/fast-element'; +import { AIChatTextBubble, aiChatTextBubbleTag } from '..'; +import { fixture, Fixture } from '../../utilities/tests/fixture'; + +async function setup(): Promise> { + return await fixture( + html`<${aiChatTextBubbleTag}>` + ); +} + +describe('AIChatTextBubble', () => { + let element: AIChatTextBubble; + let connect: () => Promise; + let disconnect: () => Promise; + + beforeEach(async () => { + ({ element, connect, disconnect } = await setup()); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('can construct an element instance', () => { + expect(document.createElement(aiChatTextBubbleTag)).toBeInstanceOf(AIChatTextBubble); + }); + + it('should have a slot element in the shadow DOM', async () => { + await connect(); + expect( + (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName + ).toBe('SLOT'); + }); +}); From dde0e41e845e24eeac25bec5e4cac25cb3dc27d6 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 25 Nov 2024 12:20:03 -0600 Subject: [PATCH 03/61] Fix build --- packages/spright-components/src/ai-chat-text-bubble/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/spright-components/src/ai-chat-text-bubble/index.ts b/packages/spright-components/src/ai-chat-text-bubble/index.ts index 3579f24ea2..46cb670285 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/index.ts +++ b/packages/spright-components/src/ai-chat-text-bubble/index.ts @@ -13,7 +13,7 @@ declare global { */ export class AIChatTextBubble extends FoundationElement {} -const sprightAIChatTextBubble = Rectangle.compose({ +const sprightAIChatTextBubble = AIChatTextBubble.compose({ baseName: 'ai-chat-text-bubble', template, styles From ff03a9e87c4108ce9d16713236919c96cb165597 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 25 Nov 2024 12:21:05 -0600 Subject: [PATCH 04/61] Copy rectangle docs for AI Chat text bubble --- .../ai-chat-text-bubble-matrix.stories.ts | 59 +++++++++++++++++++ .../ai-chat-text-bubble.mdx | 19 ++++++ .../ai-chat-text-bubble.react.tsx | 4 ++ .../ai-chat-text-bubble.stories.ts | 43 ++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts create mode 100644 packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx create mode 100644 packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx create mode 100644 packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts new file mode 100644 index 0000000000..e8e69d9e7b --- /dev/null +++ b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts @@ -0,0 +1,59 @@ +import type { StoryFn, Meta } from '@storybook/html'; +import { html, ViewTemplate } from '@microsoft/fast-element'; +import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { + createMatrix, + sharedMatrixParameters, + createMatrixThemeStory, + cartesianProduct, + createMatrixInteractionsFromStates +} from '../../utilities/matrix'; +import { createStory } from '../../utilities/storybook'; +import { hiddenWrapper } from '../../utilities/hidden'; +import { + disabledStates, + type DisabledState, + disabledStateIsEnabled +} from '../../utilities/states'; + +const metadata: Meta = { + title: 'Tests Spright/AI Chat Text Bubble', + parameters: { + ...sharedMatrixParameters() + } +}; + +export default metadata; + +const component = ([ + disabledName, + disabled +]: DisabledState): ViewTemplate => html` + <${aiChatTextBubbleTag} + ?disabled=${() => disabled} + style="margin-right: 8px;"> + ${() => `${disabledName} AI Chat Text Bubble`} +`; + +export const aiChatTextBubbleThemeMatrix: StoryFn = createMatrixThemeStory( + createMatrix(component, [disabledStates]) +); + +const interactionStatesHover = cartesianProduct([disabledStates] as const); + +const interactionStates = cartesianProduct([[disabledStateIsEnabled]] as const); + +export const aiChatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( + createMatrixInteractionsFromStates(component, { + hover: interactionStatesHover, + hoverActive: interactionStates, + active: interactionStates, + focus: interactionStates + }) +); + +export const hiddenAIChatTextBubble: StoryFn = createStory( + hiddenWrapper( + html`<${aiChatTextBubbleTag} hidden>Hidden AI Chat Text Bubble` + ) +); diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx new file mode 100644 index 0000000000..8373c4d29f --- /dev/null +++ b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx @@ -0,0 +1,19 @@ +import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; +import * as aiChatTextBubbleStories from './ai-chat-text-bubble.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; + + + + +The AI chat text bubble displays text as an element of a larger conversation. + +<Canvas of={aiChatTextBubbleStories.aiChatTextBubble} /> + +## API + +<Controls of={aiChatTextBubbleStories.aiChatTextBubble} /> +<ComponentApisLink /> + +## Usage + +Don't. diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx new file mode 100644 index 0000000000..939c0e1286 --- /dev/null +++ b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx @@ -0,0 +1,4 @@ +import { AIChatTextBubble } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { wrap } from '../../utilities/react-wrapper'; + +export const SprightAIChatTextBubble = wrap(AIChatTextBubble); diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts new file mode 100644 index 0000000000..b2e3dacb56 --- /dev/null +++ b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from '@storybook/html'; +import { html } from '@microsoft/fast-element'; +import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { + apiCategory, + createUserSelectedThemeStory, + disabledDescription +} from '../../utilities/storybook'; + +interface AIChatTextBubbleArgs { + text: string; + disabled: boolean; +} + +const metadata: Meta<AIChatTextBubbleArgs> = { + title: 'Spright/AI Chat Text Bubble', + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${aiChatTextBubbleTag} + ?disabled="${x => x.disabled}" + >${x => x.text}</${aiChatTextBubbleTag}> + `), + argTypes: { + text: { + description: 'The text to display in the AI chat text bubble.', + table: { category: apiCategory.slots } + }, + disabled: { + description: disabledDescription({ componentName: 'AI chat text bubble' }), + table: { category: apiCategory.attributes } + } + }, + args: { + text: 'Spright', + disabled: false + } +}; + +export default metadata; + +export const aiChatTextBubble: StoryObj<AIChatTextBubbleArgs> = {}; From f318f031d637983f63bbdee8eca7c27fc2d9d7b3 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:39:44 -0600 Subject: [PATCH 05/61] Refactor into single MDX for all AI Chat components --- .../ai-chat-text-bubble.mdx | 19 ---------- .../ai-chat-text-bubble-matrix.stories.ts | 0 .../ai-chat-text-bubble.react.tsx | 0 .../storybook/src/spright/ai-chat/ai-chat.mdx | 35 +++++++++++++++++++ .../ai-chat.stories.ts} | 2 +- 5 files changed, 36 insertions(+), 20 deletions(-) delete mode 100644 packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx rename packages/storybook/src/spright/{ai-chat-text-bubble => ai-chat}/ai-chat-text-bubble-matrix.stories.ts (100%) rename packages/storybook/src/spright/{ai-chat-text-bubble => ai-chat}/ai-chat-text-bubble.react.tsx (100%) create mode 100644 packages/storybook/src/spright/ai-chat/ai-chat.mdx rename packages/storybook/src/spright/{ai-chat-text-bubble/ai-chat-text-bubble.stories.ts => ai-chat/ai-chat.stories.ts} (96%) diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx b/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx deleted file mode 100644 index 8373c4d29f..0000000000 --- a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.mdx +++ /dev/null @@ -1,19 +0,0 @@ -import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; -import * as aiChatTextBubbleStories from './ai-chat-text-bubble.stories'; -import ComponentApisLink from '../../docs/component-apis-link.mdx'; - -<Meta of={aiChatTextBubbleStories} /> -<Title of={aiChatTextBubbleStories} /> - -The AI chat text bubble displays text as an element of a larger conversation. - -<Canvas of={aiChatTextBubbleStories.aiChatTextBubble} /> - -## API - -<Controls of={aiChatTextBubbleStories.aiChatTextBubble} /> -<ComponentApisLink /> - -## Usage - -Don't. diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts b/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble-matrix.stories.ts similarity index 100% rename from packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble-matrix.stories.ts rename to packages/storybook/src/spright/ai-chat/ai-chat-text-bubble-matrix.stories.ts diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx b/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx similarity index 100% rename from packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.react.tsx rename to packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx diff --git a/packages/storybook/src/spright/ai-chat/ai-chat.mdx b/packages/storybook/src/spright/ai-chat/ai-chat.mdx new file mode 100644 index 0000000000..5cff83b981 --- /dev/null +++ b/packages/storybook/src/spright/ai-chat/ai-chat.mdx @@ -0,0 +1,35 @@ +import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; +import * as aiChatStories from './ai-chat.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; +import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; + +<Meta of={aiChatStories} /> +<Title of={aiChatStories} /> + +AI chat components are used to conduct and display a conversation with an AI chat bot. +The components can collect user input and display responses; the application is responsible +for connecting them to a source of data. + +Components include low level chat bubbles and input fields and higher level composite components +representing an entire conversation or chat window. + +<Canvas of={aiChatStories.aiChatTextBubble} /> + +## API + +TODO higher level window example + +<ComponentApisLink /> + +### AI Chat Text Bubble + +Use the <Tag name={aiChatTextBubbleTag} /> element to display text in a cute little bubble. + +<Canvas of={aiChatStories.aiChatTextBubble} /> +<Controls of={aiChatStories.aiChatTextBubble} /> + +{/* ## Usage */} + +{/* ## Accessibility */} + +{/* ## Resources */} \ No newline at end of file diff --git a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts b/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts similarity index 96% rename from packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts rename to packages/storybook/src/spright/ai-chat/ai-chat.stories.ts index b2e3dacb56..801e54241b 100644 --- a/packages/storybook/src/spright/ai-chat-text-bubble/ai-chat-text-bubble.stories.ts +++ b/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts @@ -13,7 +13,7 @@ interface AIChatTextBubbleArgs { } const metadata: Meta<AIChatTextBubbleArgs> = { - title: 'Spright/AI Chat Text Bubble', + title: 'Spright/AI Chat', parameters: { actions: {} }, From 39968464a7f864c02c0cb7a992342b772fc42666 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:17:59 -0600 Subject: [PATCH 06/61] Start implementing chat bubble --- .../src/ai-chat-text-bubble/index.ts | 23 ++++++++++++++-- .../src/ai-chat-text-bubble/styles.ts | 26 ++++++++----------- .../src/ai-chat-text-bubble/template.ts | 12 ++++++++- .../spright-components/src/ai-chat/types.ts | 12 +++++++++ .../src/spright/ai-chat/ai-chat.stories.ts | 13 +++------- specs/chat-components/README.md | 2 +- 6 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 packages/spright-components/src/ai-chat/types.ts diff --git a/packages/spright-components/src/ai-chat-text-bubble/index.ts b/packages/spright-components/src/ai-chat-text-bubble/index.ts index 46cb670285..44b35da380 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/index.ts +++ b/packages/spright-components/src/ai-chat-text-bubble/index.ts @@ -1,6 +1,8 @@ +import { attr, observable } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; +import { AIChatActor } from '../ai-chat/types'; declare global { interface HTMLElementTagNameMap { @@ -9,9 +11,26 @@ declare global { } /** - * A Spright demo component (not for production use) + * A Spright component for displaying AI chat text in a bubble */ -export class AIChatTextBubble extends FoundationElement {} +export class AIChatTextBubble extends FoundationElement { + /** + * @public + * The actor responsible for this conversation contribution + * @remarks + * HTML Attribute: actor + */ + @attr + public readonly actor: AIChatActor = AIChatActor.user; + + /** + * + * @public + * Text to render within the bubble. + */ + @observable + public text = ''; +} const sprightAIChatTextBubble = AIChatTextBubble.compose({ baseName: 'ai-chat-text-bubble', diff --git a/packages/spright-components/src/ai-chat-text-bubble/styles.ts b/packages/spright-components/src/ai-chat-text-bubble/styles.ts index be412771ca..fb9fbaae81 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/styles.ts +++ b/packages/spright-components/src/ai-chat-text-bubble/styles.ts @@ -1,34 +1,30 @@ import { css } from '@microsoft/fast-element'; import { - bodyDisabledFontColor, bodyFont, bodyFontColor, borderHoverColor, - borderRgbPartialColor + borderWidth, + fillSelectedColor } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../utilities/style/display'; export const styles = css` - ${display('inline-block')} + ${display('block')} :host { - border: 2px solid ${borderHoverColor}; + min-width: 8px; + min-height: 8px; } - :host(:hover) { - border-width: 4px; - } - - :host([disabled]) { - border-color: rgba(${borderRgbPartialColor}, 0.2); - } - - slot { + div { font: ${bodyFont}; color: ${bodyFontColor}; + background: ${fillSelectedColor}; + border: ${borderWidth} solid ${borderHoverColor}; + border-radius: 8px; } - :host([disabled]) slot { - color: ${bodyDisabledFontColor}; + :host[actor='user'] div { + border-radius: 8px 8px 8px 0px } `; diff --git a/packages/spright-components/src/ai-chat-text-bubble/template.ts b/packages/spright-components/src/ai-chat-text-bubble/template.ts index 3a853b0864..88700e2780 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/template.ts +++ b/packages/spright-components/src/ai-chat-text-bubble/template.ts @@ -1,3 +1,13 @@ import { html } from '@microsoft/fast-element'; +import type { AIChatTextBubble } from '.'; -export const template = html`<slot></slot>`; +/* eslint-disable @typescript-eslint/indent */ +// prettier-ignore +export const template = html<AIChatTextBubble>` + <template> + <div> + ${x => x.text} + </div> + </template> +`; +/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/ai-chat/types.ts b/packages/spright-components/src/ai-chat/types.ts new file mode 100644 index 0000000000..9a0d9abfd7 --- /dev/null +++ b/packages/spright-components/src/ai-chat/types.ts @@ -0,0 +1,12 @@ +/** + * An actor in an AI chat conversation. + * @public + */ +export const AIChatActor = { + bot: 'bot', + system: 'system', + user: 'user', +} as const; + +export type AIChatActor = + (typeof AIChatActor)[keyof typeof AIChatActor]; diff --git a/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts b/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts index 801e54241b..780196c4dc 100644 --- a/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts +++ b/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts @@ -4,12 +4,10 @@ import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat- import { apiCategory, createUserSelectedThemeStory, - disabledDescription } from '../../utilities/storybook'; interface AIChatTextBubbleArgs { text: string; - disabled: boolean; } const metadata: Meta<AIChatTextBubbleArgs> = { @@ -19,22 +17,17 @@ const metadata: Meta<AIChatTextBubbleArgs> = { }, render: createUserSelectedThemeStory(html` <${aiChatTextBubbleTag} - ?disabled="${x => x.disabled}" - >${x => x.text}</${aiChatTextBubbleTag}> + text="${x => x.text}" + ></${aiChatTextBubbleTag}> `), argTypes: { text: { description: 'The text to display in the AI chat text bubble.', table: { category: apiCategory.slots } }, - disabled: { - description: disabledDescription({ componentName: 'AI chat text bubble' }), - table: { category: apiCategory.attributes } - } }, args: { - text: 'Spright', - disabled: false + text: 'Hi, how are you?', } }; diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md index bc50535ac5..539291d221 100644 --- a/specs/chat-components/README.md +++ b/specs/chat-components/README.md @@ -1,7 +1,7 @@ spright-ai-chat-text-bubble Props/Attrs actor: AIChatActor - controls corner rounding, expected by conversation. Always 'user', not settable - value: string (support newlines) + text: string (support newlines) timestamp: date string? (not yet, might belong to conversation) Slots not needed yet, could use for label/a11y From f31ed38da23c5bf22b14a6d62c7fac8d4915c573 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:49:03 -0600 Subject: [PATCH 07/61] Remove "AI" from names --- .../spright-components/src/ai-chat/types.ts | 12 ------- .../index.ts | 18 +++++----- .../styles.ts | 0 .../template.ts | 4 +-- .../tests/chat-text-bubble.spec.ts} | 14 ++++---- packages/spright-components/src/chat/types.ts | 12 +++++++ .../ai-chat/ai-chat-text-bubble.react.tsx | 4 --- .../chat-text-bubble-matrix.stories.ts} | 16 ++++----- .../spright/chat/chat-text-bubble.react.tsx | 4 +++ .../{ai-chat/ai-chat.mdx => chat/chat.mdx} | 20 +++++------ .../chat.stories.ts} | 16 ++++----- specs/chat-components/README.md | 35 +++++++++++++------ 12 files changed, 84 insertions(+), 71 deletions(-) delete mode 100644 packages/spright-components/src/ai-chat/types.ts rename packages/spright-components/src/{ai-chat-text-bubble => chat-text-bubble}/index.ts (58%) rename packages/spright-components/src/{ai-chat-text-bubble => chat-text-bubble}/styles.ts (100%) rename packages/spright-components/src/{ai-chat-text-bubble => chat-text-bubble}/template.ts (73%) rename packages/spright-components/src/{ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts => chat-text-bubble/tests/chat-text-bubble.spec.ts} (62%) create mode 100644 packages/spright-components/src/chat/types.ts delete mode 100644 packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx rename packages/storybook/src/spright/{ai-chat/ai-chat-text-bubble-matrix.stories.ts => chat/chat-text-bubble-matrix.stories.ts} (68%) create mode 100644 packages/storybook/src/spright/chat/chat-text-bubble.react.tsx rename packages/storybook/src/spright/{ai-chat/ai-chat.mdx => chat/chat.mdx} (50%) rename packages/storybook/src/spright/{ai-chat/ai-chat.stories.ts => chat/chat.stories.ts} (56%) diff --git a/packages/spright-components/src/ai-chat/types.ts b/packages/spright-components/src/ai-chat/types.ts deleted file mode 100644 index 9a0d9abfd7..0000000000 --- a/packages/spright-components/src/ai-chat/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * An actor in an AI chat conversation. - * @public - */ -export const AIChatActor = { - bot: 'bot', - system: 'system', - user: 'user', -} as const; - -export type AIChatActor = - (typeof AIChatActor)[keyof typeof AIChatActor]; diff --git a/packages/spright-components/src/ai-chat-text-bubble/index.ts b/packages/spright-components/src/chat-text-bubble/index.ts similarity index 58% rename from packages/spright-components/src/ai-chat-text-bubble/index.ts rename to packages/spright-components/src/chat-text-bubble/index.ts index 44b35da380..2cf2dc53b0 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/index.ts +++ b/packages/spright-components/src/chat-text-bubble/index.ts @@ -2,18 +2,18 @@ import { attr, observable } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import { AIChatActor } from '../ai-chat/types'; +import { ChatActor } from '../chat/types'; declare global { interface HTMLElementTagNameMap { - 'spright-ai-chat-text-bubble': AIChatTextBubble; + 'spright-chat-text-bubble': ChatTextBubble; } } /** - * A Spright component for displaying AI chat text in a bubble + * A Spright component for displaying chat text in a bubble */ -export class AIChatTextBubble extends FoundationElement { +export class ChatTextBubble extends FoundationElement { /** * @public * The actor responsible for this conversation contribution @@ -21,7 +21,7 @@ export class AIChatTextBubble extends FoundationElement { * HTML Attribute: actor */ @attr - public readonly actor: AIChatActor = AIChatActor.user; + public readonly actor: ChatActor = ChatActor.user; /** * @@ -32,11 +32,11 @@ export class AIChatTextBubble extends FoundationElement { public text = ''; } -const sprightAIChatTextBubble = AIChatTextBubble.compose({ - baseName: 'ai-chat-text-bubble', +const sprightChatTextBubble = ChatTextBubble.compose({ + baseName: 'chat-text-bubble', template, styles }); -DesignSystem.getOrCreate().withPrefix('spright').register(sprightAIChatTextBubble()); -export const aiChatTextBubbleTag = 'spright-ai-chat-text-bubble'; +DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatTextBubble()); +export const chatTextBubbleTag = 'spright-chat-text-bubble'; diff --git a/packages/spright-components/src/ai-chat-text-bubble/styles.ts b/packages/spright-components/src/chat-text-bubble/styles.ts similarity index 100% rename from packages/spright-components/src/ai-chat-text-bubble/styles.ts rename to packages/spright-components/src/chat-text-bubble/styles.ts diff --git a/packages/spright-components/src/ai-chat-text-bubble/template.ts b/packages/spright-components/src/chat-text-bubble/template.ts similarity index 73% rename from packages/spright-components/src/ai-chat-text-bubble/template.ts rename to packages/spright-components/src/chat-text-bubble/template.ts index 88700e2780..afac18b466 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/template.ts +++ b/packages/spright-components/src/chat-text-bubble/template.ts @@ -1,9 +1,9 @@ import { html } from '@microsoft/fast-element'; -import type { AIChatTextBubble } from '.'; +import type { ChatTextBubble } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore -export const template = html<AIChatTextBubble>` +export const template = html<ChatTextBubble>` <template> <div> ${x => x.text} diff --git a/packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts b/packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts similarity index 62% rename from packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts rename to packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts index 616d95e986..2944b3bebb 100644 --- a/packages/spright-components/src/ai-chat-text-bubble/tests/ai-chat-text-bubble.spec.ts +++ b/packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts @@ -1,15 +1,15 @@ import { html } from '@microsoft/fast-element'; -import { AIChatTextBubble, aiChatTextBubbleTag } from '..'; +import { ChatTextBubble, chatTextBubbleTag } from '..'; import { fixture, Fixture } from '../../utilities/tests/fixture'; -async function setup(): Promise<Fixture<AIChatTextBubble>> { - return await fixture<AIChatTextBubble>( - html`<${aiChatTextBubbleTag}></${aiChatTextBubbleTag}>` +async function setup(): Promise<Fixture<ChatTextBubble>> { + return await fixture<ChatTextBubble>( + html`<${chatTextBubbleTag}></${chatTextBubbleTag}>` ); } -describe('AIChatTextBubble', () => { - let element: AIChatTextBubble; +describe('ChatTextBubble', () => { + let element: ChatTextBubble; let connect: () => Promise<void>; let disconnect: () => Promise<void>; @@ -22,7 +22,7 @@ describe('AIChatTextBubble', () => { }); it('can construct an element instance', () => { - expect(document.createElement(aiChatTextBubbleTag)).toBeInstanceOf(AIChatTextBubble); + expect(document.createElement(chatTextBubbleTag)).toBeInstanceOf(ChatTextBubble); }); it('should have a slot element in the shadow DOM', async () => { diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts new file mode 100644 index 0000000000..dea794c0e0 --- /dev/null +++ b/packages/spright-components/src/chat/types.ts @@ -0,0 +1,12 @@ +/** + * An actor in a chat conversation. + * @public + */ +export const ChatActor = { + bot: 'bot', + system: 'system', + user: 'user', +} as const; + +export type ChatActor = + (typeof ChatActor)[keyof typeof ChatActor]; diff --git a/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx b/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx deleted file mode 100644 index 939c0e1286..0000000000 --- a/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble.react.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { AIChatTextBubble } from '../../../../spright-components/src/ai-chat-text-bubble'; -import { wrap } from '../../utilities/react-wrapper'; - -export const SprightAIChatTextBubble = wrap(AIChatTextBubble); diff --git a/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts similarity index 68% rename from packages/storybook/src/spright/ai-chat/ai-chat-text-bubble-matrix.stories.ts rename to packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts index e8e69d9e7b..44f93feb97 100644 --- a/packages/storybook/src/spright/ai-chat/ai-chat-text-bubble-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts @@ -1,6 +1,6 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; -import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; import { createMatrix, sharedMatrixParameters, @@ -17,7 +17,7 @@ import { } from '../../utilities/states'; const metadata: Meta = { - title: 'Tests Spright/AI Chat Text Bubble', + title: 'Tests Spright/Chat Text Bubble', parameters: { ...sharedMatrixParameters() } @@ -29,13 +29,13 @@ const component = ([ disabledName, disabled ]: DisabledState): ViewTemplate => html` - <${aiChatTextBubbleTag} + <${chatTextBubbleTag} ?disabled=${() => disabled} style="margin-right: 8px;"> - ${() => `${disabledName} AI Chat Text Bubble`}</${aiChatTextBubbleTag}> + ${() => `${disabledName} Chat Text Bubble`}</${chatTextBubbleTag}> `; -export const aiChatTextBubbleThemeMatrix: StoryFn = createMatrixThemeStory( +export const chatTextBubbleThemeMatrix: StoryFn = createMatrixThemeStory( createMatrix(component, [disabledStates]) ); @@ -43,7 +43,7 @@ const interactionStatesHover = cartesianProduct([disabledStates] as const); const interactionStates = cartesianProduct([[disabledStateIsEnabled]] as const); -export const aiChatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( +export const chatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( createMatrixInteractionsFromStates(component, { hover: interactionStatesHover, hoverActive: interactionStates, @@ -52,8 +52,8 @@ export const aiChatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThem }) ); -export const hiddenAIChatTextBubble: StoryFn = createStory( +export const hiddenChatTextBubble: StoryFn = createStory( hiddenWrapper( - html`<${aiChatTextBubbleTag} hidden>Hidden AI Chat Text Bubble</${aiChatTextBubbleTag}>` + html`<${chatTextBubbleTag} hidden>Hidden Chat Text Bubble</${chatTextBubbleTag}>` ) ); diff --git a/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx b/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx new file mode 100644 index 0000000000..8570bd4107 --- /dev/null +++ b/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx @@ -0,0 +1,4 @@ +import { ChatTextBubble } from '../../../../spright-components/src/chat-text-bubble'; +import { wrap } from '../../utilities/react-wrapper'; + +export const SprightChatTextBubble = wrap(ChatTextBubble); diff --git a/packages/storybook/src/spright/ai-chat/ai-chat.mdx b/packages/storybook/src/spright/chat/chat.mdx similarity index 50% rename from packages/storybook/src/spright/ai-chat/ai-chat.mdx rename to packages/storybook/src/spright/chat/chat.mdx index 5cff83b981..92b28b6feb 100644 --- a/packages/storybook/src/spright/ai-chat/ai-chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -1,19 +1,19 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; -import * as aiChatStories from './ai-chat.stories'; +import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; -import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; -<Meta of={aiChatStories} /> -<Title of={aiChatStories} /> +<Meta of={chatStories} /> +<Title of={chatStories} /> -AI chat components are used to conduct and display a conversation with an AI chat bot. +Chat components are used to conduct and display a conversation with a chat bot or other users. The components can collect user input and display responses; the application is responsible for connecting them to a source of data. Components include low level chat bubbles and input fields and higher level composite components representing an entire conversation or chat window. -<Canvas of={aiChatStories.aiChatTextBubble} /> +<Canvas of={chatStories.chatTextBubble} /> ## API @@ -21,12 +21,12 @@ TODO higher level window example <ComponentApisLink /> -### AI Chat Text Bubble +### Chat Text Bubble -Use the <Tag name={aiChatTextBubbleTag} /> element to display text in a cute little bubble. +Use the <Tag name={chatTextBubbleTag} /> element to display text in a cute little bubble. -<Canvas of={aiChatStories.aiChatTextBubble} /> -<Controls of={aiChatStories.aiChatTextBubble} /> +<Canvas of={chatStories.chatTextBubble} /> +<Controls of={chatStories.chatTextBubble} /> {/* ## Usage */} diff --git a/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts similarity index 56% rename from packages/storybook/src/spright/ai-chat/ai-chat.stories.ts rename to packages/storybook/src/spright/chat/chat.stories.ts index 780196c4dc..d1c5cf9202 100644 --- a/packages/storybook/src/spright/ai-chat/ai-chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,28 +1,28 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { aiChatTextBubbleTag } from '../../../../spright-components/src/ai-chat-text-bubble'; +import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; import { apiCategory, createUserSelectedThemeStory, } from '../../utilities/storybook'; -interface AIChatTextBubbleArgs { +interface ChatTextBubbleArgs { text: string; } -const metadata: Meta<AIChatTextBubbleArgs> = { - title: 'Spright/AI Chat', +const metadata: Meta<ChatTextBubbleArgs> = { + title: 'Spright/Chat', parameters: { actions: {} }, render: createUserSelectedThemeStory(html` - <${aiChatTextBubbleTag} + <${chatTextBubbleTag} text="${x => x.text}" - ></${aiChatTextBubbleTag}> + ></${chatTextBubbleTag}> `), argTypes: { text: { - description: 'The text to display in the AI chat text bubble.', + description: 'The text to display in the chat text bubble.', table: { category: apiCategory.slots } }, }, @@ -33,4 +33,4 @@ const metadata: Meta<AIChatTextBubbleArgs> = { export default metadata; -export const aiChatTextBubble: StoryObj<AIChatTextBubbleArgs> = {}; +export const chatTextBubble: StoryObj<ChatTextBubbleArgs> = {}; diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md index 539291d221..8435e3ce31 100644 --- a/specs/chat-components/README.md +++ b/specs/chat-components/README.md @@ -1,37 +1,39 @@ -spright-ai-chat-text-bubble +spright-chat-text-bubble Props/Attrs - actor: AIChatActor - controls corner rounding, expected by conversation. Always 'user', not settable + actor: ChatActor - controls corner rounding, expected by conversation. Always 'user', not settable text: string (support newlines) timestamp: date string? (not yet, might belong to conversation) Slots not needed yet, could use for label/a11y -spright-ai-chat-rich-text-bubble? +spright-chat-rich-text-bubble? Props/Attrs actor - Always 'bot', not settable markdown? -spright-ai-chat-content-bubble? +spright-chat-content-bubble? Props/Attrs actor - Always 'bot', not settable Slots content - arbitrary HTML -spright-ai-chat-prompt-buttons - lays out buttons +spright-chat-prompt-buttons - lays out buttons Props/Attrs actor: always 'system', not settable Slots buttons -spright-ai-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner +spright-chat-load-more-button - button at top or bottom of conversation to "virtualize" + +spright-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner Props/Attrs - spinner-visible + order = newest-top or newest-bottom (or use DOM order?) Slots child order and 'actor' attribute determine layout -spright-ai-chat-toolbar - top toolbar with buttons +spright-chat-toolbar - top toolbar with buttons -spright-ai-chat-input-toolbar - bottom toolbar with buttons, text input +spright-chat-input-toolbar - bottom toolbar with buttons, text input Props/Attrs add-chat-button-disabled add-chat-button-disabled @@ -48,8 +50,19 @@ spright-ai-chat-input-toolbar - bottom toolbar with buttons, text input text-input-change text-input-button-click -spright-ai-chat-window - lays out conversation and toolbar. Probably no logic +spright-chat-window - lays out conversation and toolbar. Probably no logic Slots default slot for toolbar, conversation, bottom toolbar? -AIChatActor = 'user' | 'bot' | 'system' \ No newline at end of file +ChatActor = 'user' | 'bot' | 'system' + + +Notes: + - remove "AI", "bot", "user" + - appearance (or variant) for color and position, remove "actor" + - bubble is responsible for layout, conversation just does vertical layout + - single chat bubble, slot in content, use rich text viewer for MD if needed + - rich text viewer would need more features for links, images + - research a11y patterns for chat widgets + - mention plugins for links + - \ No newline at end of file From 2ba3b860c0cb9e539dc4bda3eea5afcc51157fbc Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:40:36 -0600 Subject: [PATCH 08/61] Rename bubbles to messages --- .../index.ts | 14 ++++---- .../styles.ts | 0 .../template.ts | 4 +-- .../tests/chat-message.spec.ts} | 14 ++++---- ...ries.ts => chat-message-matrix.stories.ts} | 16 ++++----- .../src/spright/chat/chat-message.react.tsx | 4 +++ .../spright/chat/chat-text-bubble.react.tsx | 4 --- packages/storybook/src/spright/chat/chat.mdx | 14 ++++---- .../src/spright/chat/chat.stories.ts | 12 +++---- specs/chat-components/README.md | 36 ++++++++----------- 10 files changed, 55 insertions(+), 63 deletions(-) rename packages/spright-components/src/{chat-text-bubble => chat-message}/index.ts (68%) rename packages/spright-components/src/{chat-text-bubble => chat-message}/styles.ts (100%) rename packages/spright-components/src/{chat-text-bubble => chat-message}/template.ts (74%) rename packages/spright-components/src/{chat-text-bubble/tests/chat-text-bubble.spec.ts => chat-message/tests/chat-message.spec.ts} (63%) rename packages/storybook/src/spright/chat/{chat-text-bubble-matrix.stories.ts => chat-message-matrix.stories.ts} (69%) create mode 100644 packages/storybook/src/spright/chat/chat-message.react.tsx delete mode 100644 packages/storybook/src/spright/chat/chat-text-bubble.react.tsx diff --git a/packages/spright-components/src/chat-text-bubble/index.ts b/packages/spright-components/src/chat-message/index.ts similarity index 68% rename from packages/spright-components/src/chat-text-bubble/index.ts rename to packages/spright-components/src/chat-message/index.ts index 2cf2dc53b0..38e81bacc4 100644 --- a/packages/spright-components/src/chat-text-bubble/index.ts +++ b/packages/spright-components/src/chat-message/index.ts @@ -6,14 +6,14 @@ import { ChatActor } from '../chat/types'; declare global { interface HTMLElementTagNameMap { - 'spright-chat-text-bubble': ChatTextBubble; + 'spright-chat-message': ChatMessage; } } /** - * A Spright component for displaying chat text in a bubble + * A Spright component for displaying a chat message */ -export class ChatTextBubble extends FoundationElement { +export class ChatMessage extends FoundationElement { /** * @public * The actor responsible for this conversation contribution @@ -32,11 +32,11 @@ export class ChatTextBubble extends FoundationElement { public text = ''; } -const sprightChatTextBubble = ChatTextBubble.compose({ - baseName: 'chat-text-bubble', +const sprightChatMessage = ChatMessage.compose({ + baseName: 'chat-message', template, styles }); -DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatTextBubble()); -export const chatTextBubbleTag = 'spright-chat-text-bubble'; +DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatMessage()); +export const chatMessageTag = 'spright-chat-message'; diff --git a/packages/spright-components/src/chat-text-bubble/styles.ts b/packages/spright-components/src/chat-message/styles.ts similarity index 100% rename from packages/spright-components/src/chat-text-bubble/styles.ts rename to packages/spright-components/src/chat-message/styles.ts diff --git a/packages/spright-components/src/chat-text-bubble/template.ts b/packages/spright-components/src/chat-message/template.ts similarity index 74% rename from packages/spright-components/src/chat-text-bubble/template.ts rename to packages/spright-components/src/chat-message/template.ts index afac18b466..01933157be 100644 --- a/packages/spright-components/src/chat-text-bubble/template.ts +++ b/packages/spright-components/src/chat-message/template.ts @@ -1,9 +1,9 @@ import { html } from '@microsoft/fast-element'; -import type { ChatTextBubble } from '.'; +import type { ChatMessage } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore -export const template = html<ChatTextBubble>` +export const template = html<ChatMessage>` <template> <div> ${x => x.text} diff --git a/packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts b/packages/spright-components/src/chat-message/tests/chat-message.spec.ts similarity index 63% rename from packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts rename to packages/spright-components/src/chat-message/tests/chat-message.spec.ts index 2944b3bebb..ec63d1a2f3 100644 --- a/packages/spright-components/src/chat-text-bubble/tests/chat-text-bubble.spec.ts +++ b/packages/spright-components/src/chat-message/tests/chat-message.spec.ts @@ -1,15 +1,15 @@ import { html } from '@microsoft/fast-element'; -import { ChatTextBubble, chatTextBubbleTag } from '..'; +import { ChatMessage, chatMessageTag } from '..'; import { fixture, Fixture } from '../../utilities/tests/fixture'; -async function setup(): Promise<Fixture<ChatTextBubble>> { - return await fixture<ChatTextBubble>( - html`<${chatTextBubbleTag}></${chatTextBubbleTag}>` +async function setup(): Promise<Fixture<ChatMessage>> { + return await fixture<ChatMessage>( + html`<${chatMessageTag}></${chatMessageTag}>` ); } -describe('ChatTextBubble', () => { - let element: ChatTextBubble; +describe('ChatMessage', () => { + let element: ChatMessage; let connect: () => Promise<void>; let disconnect: () => Promise<void>; @@ -22,7 +22,7 @@ describe('ChatTextBubble', () => { }); it('can construct an element instance', () => { - expect(document.createElement(chatTextBubbleTag)).toBeInstanceOf(ChatTextBubble); + expect(document.createElement(chatMessageTag)).toBeInstanceOf(ChatMessage); }); it('should have a slot element in the shadow DOM', async () => { diff --git a/packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts similarity index 69% rename from packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts rename to packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index 44f93feb97..d16928413f 100644 --- a/packages/storybook/src/spright/chat/chat-text-bubble-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -1,6 +1,6 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; -import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; +import { chatMessageTag } from '../../../../spright-components/src/chat-message'; import { createMatrix, sharedMatrixParameters, @@ -17,7 +17,7 @@ import { } from '../../utilities/states'; const metadata: Meta = { - title: 'Tests Spright/Chat Text Bubble', + title: 'Tests Spright/Chat Message', parameters: { ...sharedMatrixParameters() } @@ -29,13 +29,13 @@ const component = ([ disabledName, disabled ]: DisabledState): ViewTemplate => html` - <${chatTextBubbleTag} + <${chatMessageTag} ?disabled=${() => disabled} style="margin-right: 8px;"> - ${() => `${disabledName} Chat Text Bubble`}</${chatTextBubbleTag}> + ${() => `${disabledName} Chat Message`}</${chatMessageTag}> `; -export const chatTextBubbleThemeMatrix: StoryFn = createMatrixThemeStory( +export const chatMessageThemeMatrix: StoryFn = createMatrixThemeStory( createMatrix(component, [disabledStates]) ); @@ -43,7 +43,7 @@ const interactionStatesHover = cartesianProduct([disabledStates] as const); const interactionStates = cartesianProduct([[disabledStateIsEnabled]] as const); -export const chatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( +export const chatMessageInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( createMatrixInteractionsFromStates(component, { hover: interactionStatesHover, hoverActive: interactionStates, @@ -52,8 +52,8 @@ export const chatTextBubbleInteractionsThemeMatrix: StoryFn = createMatrixThemeS }) ); -export const hiddenChatTextBubble: StoryFn = createStory( +export const hiddenChatMessage: StoryFn = createStory( hiddenWrapper( - html`<${chatTextBubbleTag} hidden>Hidden Chat Text Bubble</${chatTextBubbleTag}>` + html`<${chatMessageTag} hidden>Hidden Chat Message</${chatMessageTag}>` ) ); diff --git a/packages/storybook/src/spright/chat/chat-message.react.tsx b/packages/storybook/src/spright/chat/chat-message.react.tsx new file mode 100644 index 0000000000..41b76a3bab --- /dev/null +++ b/packages/storybook/src/spright/chat/chat-message.react.tsx @@ -0,0 +1,4 @@ +import { ChatMessage } from '../../../../spright-components/src/chat-message'; +import { wrap } from '../../utilities/react-wrapper'; + +export const SprightChatMessage = wrap(ChatMessage); diff --git a/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx b/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx deleted file mode 100644 index 8570bd4107..0000000000 --- a/packages/storybook/src/spright/chat/chat-text-bubble.react.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ChatTextBubble } from '../../../../spright-components/src/chat-text-bubble'; -import { wrap } from '../../utilities/react-wrapper'; - -export const SprightChatTextBubble = wrap(ChatTextBubble); diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 92b28b6feb..11348fbaac 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -1,7 +1,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; -import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; +import { chatMessageTag } from '../../../../spright-components/src/chat-message'; <Meta of={chatStories} /> <Title of={chatStories} /> @@ -10,10 +10,10 @@ Chat components are used to conduct and display a conversation with a chat bot o The components can collect user input and display responses; the application is responsible for connecting them to a source of data. -Components include low level chat bubbles and input fields and higher level composite components +Components include low level chat messages and input fields and higher level composite components representing an entire conversation or chat window. -<Canvas of={chatStories.chatTextBubble} /> +<Canvas of={chatStories.chatMessage} /> ## API @@ -21,12 +21,12 @@ TODO higher level window example <ComponentApisLink /> -### Chat Text Bubble +### Chat Message -Use the <Tag name={chatTextBubbleTag} /> element to display text in a cute little bubble. +Use the <Tag name={chatMessageTag} /> element to display content in a message. -<Canvas of={chatStories.chatTextBubble} /> -<Controls of={chatStories.chatTextBubble} /> +<Canvas of={chatStories.chatMessage} /> +<Controls of={chatStories.chatMessage} /> {/* ## Usage */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index d1c5cf9202..6738415100 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,24 +1,24 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { chatTextBubbleTag } from '../../../../spright-components/src/chat-text-bubble'; +import { chatMessageTag } from '../../../../spright-components/src/chat-message'; import { apiCategory, createUserSelectedThemeStory, } from '../../utilities/storybook'; -interface ChatTextBubbleArgs { +interface ChatMessageArgs { text: string; } -const metadata: Meta<ChatTextBubbleArgs> = { +const metadata: Meta<ChatMessageArgs> = { title: 'Spright/Chat', parameters: { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatTextBubbleTag} + <${chatMessageTag} text="${x => x.text}" - ></${chatTextBubbleTag}> + ></${chatMessageTag}> `), argTypes: { text: { @@ -33,4 +33,4 @@ const metadata: Meta<ChatTextBubbleArgs> = { export default metadata; -export const chatTextBubble: StoryObj<ChatTextBubbleArgs> = {}; +export const chatMessage: StoryObj<ChatMessageArgs> = {}; diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md index 8435e3ce31..31e4161b5f 100644 --- a/specs/chat-components/README.md +++ b/specs/chat-components/README.md @@ -1,35 +1,28 @@ -spright-chat-text-bubble +spright-chat-message - draws outline/bg, sizes its content Props/Attrs - actor: ChatActor - controls corner rounding, expected by conversation. Always 'user', not settable - text: string (support newlines) + source: ChatMessageSource - controls corner rounding. timestamp: date string? (not yet, might belong to conversation) Slots - not needed yet, could use for label/a11y + any content: + plain text, including new lines + rich text viewer populated via markdown + styled HTML -spright-chat-rich-text-bubble? - Props/Attrs - actor - Always 'bot', not settable - markdown? - -spright-chat-content-bubble? - Props/Attrs - actor - Always 'bot', not settable - Slots - content - arbitrary HTML +ChatMessageSource = +'me' | 'them' | 'system' +'outgoing' | 'incoming' | 'status' +'right' | 'left' | 'center' +'this-user' | 'other-user' | 'system' -spright-chat-prompt-buttons - lays out buttons - Props/Attrs - actor: always 'system', not settable - Slots - buttons +appearance='ghost' | 'block' and location = 'start' | 'end' | 'middle' spright-chat-load-more-button - button at top or bottom of conversation to "virtualize" -spright-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner +spright-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner vertically with 100% width Props/Attrs order = newest-top or newest-bottom (or use DOM order?) Slots - child order and 'actor' attribute determine layout + child order determine layout spright-chat-toolbar - top toolbar with buttons @@ -54,7 +47,6 @@ spright-chat-window - lays out conversation and toolbar. Probably no logic Slots default slot for toolbar, conversation, bottom toolbar? -ChatActor = 'user' | 'bot' | 'system' Notes: From 3f94aa5f44648e5d7c073229c8da71acd3a6a527 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:09:38 -0600 Subject: [PATCH 09/61] Slot message content --- packages/spright-components/src/chat-message/index.ts | 8 -------- .../spright-components/src/chat-message/styles.ts | 11 ++++++++--- .../spright-components/src/chat-message/template.ts | 8 +++----- packages/storybook/src/spright/chat/chat.stories.ts | 6 +++--- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/spright-components/src/chat-message/index.ts b/packages/spright-components/src/chat-message/index.ts index 38e81bacc4..c63cd367cc 100644 --- a/packages/spright-components/src/chat-message/index.ts +++ b/packages/spright-components/src/chat-message/index.ts @@ -22,14 +22,6 @@ export class ChatMessage extends FoundationElement { */ @attr public readonly actor: ChatActor = ChatActor.user; - - /** - * - * @public - * Text to render within the bubble. - */ - @observable - public text = ''; } const sprightChatMessage = ChatMessage.compose({ diff --git a/packages/spright-components/src/chat-message/styles.ts b/packages/spright-components/src/chat-message/styles.ts index fb9fbaae81..c97bf47780 100644 --- a/packages/spright-components/src/chat-message/styles.ts +++ b/packages/spright-components/src/chat-message/styles.ts @@ -4,7 +4,8 @@ import { bodyFontColor, borderHoverColor, borderWidth, - fillSelectedColor + fillSelectedColor, + mediumPadding, } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../utilities/style/display'; @@ -12,11 +13,15 @@ export const styles = css` ${display('block')} :host { - min-width: 8px; - min-height: 8px; + min-width: 16px; + min-height: 16px; } div { + max-width: calc(100%-20px); + width: fit-content; + height: fit-content; + padding: ${mediumPadding}; font: ${bodyFont}; color: ${bodyFontColor}; background: ${fillSelectedColor}; diff --git a/packages/spright-components/src/chat-message/template.ts b/packages/spright-components/src/chat-message/template.ts index 01933157be..a746e3567e 100644 --- a/packages/spright-components/src/chat-message/template.ts +++ b/packages/spright-components/src/chat-message/template.ts @@ -4,10 +4,8 @@ import type { ChatMessage } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore export const template = html<ChatMessage>` - <template> - <div> - ${x => x.text} - </div> - </template> + <div> + <slot></slot> + </div> `; /* eslint-enable @typescript-eslint/indent */ diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 6738415100..b9e5936600 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -16,9 +16,9 @@ const metadata: Meta<ChatMessageArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} - text="${x => x.text}" - ></${chatMessageTag}> + <${chatMessageTag}> + ${x => x.text} + </${chatMessageTag}> `), argTypes: { text: { From 2837ba359ea3cbefb83d2a505ee6b1b93ebc1f1d Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:29:21 -0600 Subject: [PATCH 10/61] Markdown example --- packages/storybook/src/spright/chat/chat.mdx | 9 ++-- .../src/spright/chat/chat.stories.ts | 48 ++++++++++++++++--- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 11348fbaac..28e79de443 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -13,7 +13,7 @@ for connecting them to a source of data. Components include low level chat messages and input fields and higher level composite components representing an entire conversation or chat window. -<Canvas of={chatStories.chatMessage} /> +<Canvas of={chatStories.chatMessageText} /> ## API @@ -25,8 +25,11 @@ TODO higher level window example Use the <Tag name={chatMessageTag} /> element to display content in a message. -<Canvas of={chatStories.chatMessage} /> -<Controls of={chatStories.chatMessage} /> +<Canvas of={chatStories.chatMessageText} /> +<Controls of={chatStories.chatMessageText} /> + +<Canvas of={chatStories.chatMessageRichText} /> +<Controls of={chatStories.chatMessageRichText} /> {/* ## Usage */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index b9e5936600..21bcb1c8bb 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,17 +1,23 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; import { chatMessageTag } from '../../../../spright-components/src/chat-message'; +import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { apiCategory, createUserSelectedThemeStory, } from '../../utilities/storybook'; -interface ChatMessageArgs { +const metadata: Meta<ChatMessageTextArgs> = { + title: 'Spright/Chat' +}; + +export default metadata; + +interface ChatMessageTextArgs { text: string; } -const metadata: Meta<ChatMessageArgs> = { - title: 'Spright/Chat', +export const chatMessageText: StoryObj<ChatMessageTextArgs> = { parameters: { actions: {} }, @@ -22,15 +28,43 @@ const metadata: Meta<ChatMessageArgs> = { `), argTypes: { text: { - description: 'The text to display in the chat text bubble.', + description: 'The text to display in the chat message.', table: { category: apiCategory.slots } }, }, args: { - text: 'Hi, how are you?', + text: 'How do I choose which version of Python to execute my script?', } }; -export default metadata; +interface ChatMessageRichTextArgs { + markdown: string; +} +export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag}> + <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> + </${chatMessageTag}> + `), + argTypes: { + markdown: { + description: 'Markdown text for the rich text viewer', + table: { category: apiCategory.slots } + }, + }, + args: { + markdown: + `To configure your Python version: -export const chatMessage: StoryObj<ChatMessageArgs> = {}; + 1. Select **Adapters...** from the **Configure** menu. + + 2. Configure the Python adapter. + + 3. Choose the desired version from the **Version** dropdown. + + You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`, + } +}; From 9b5866c5043a25d6672bb0e0335c6119e3a8aff0 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:33:33 -0600 Subject: [PATCH 11/61] positioning based on who sent message --- .../src/chat-message/index.ts | 8 +++--- .../src/chat-message/styles.ts | 23 +++++++++++++--- packages/spright-components/src/chat/types.ts | 12 ++++----- .../src/spright/chat/chat.stories.ts | 27 ++++++++++++++++--- specs/chat-components/README.md | 9 ++++++- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/packages/spright-components/src/chat-message/index.ts b/packages/spright-components/src/chat-message/index.ts index c63cd367cc..d56adcae5e 100644 --- a/packages/spright-components/src/chat-message/index.ts +++ b/packages/spright-components/src/chat-message/index.ts @@ -2,7 +2,7 @@ import { attr, observable } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import { ChatActor } from '../chat/types'; +import { ChatMessageStatus } from '../chat/types'; declare global { interface HTMLElementTagNameMap { @@ -16,12 +16,12 @@ declare global { export class ChatMessage extends FoundationElement { /** * @public - * The actor responsible for this conversation contribution + * The status of this message in the chat conversation * @remarks - * HTML Attribute: actor + * HTML Attribute: status */ @attr - public readonly actor: ChatActor = ChatActor.user; + public readonly status: ChatMessageStatus = ChatMessageStatus.outgoing; } const sprightChatMessage = ChatMessage.compose({ diff --git a/packages/spright-components/src/chat-message/styles.ts b/packages/spright-components/src/chat-message/styles.ts index c97bf47780..21fc4a0136 100644 --- a/packages/spright-components/src/chat-message/styles.ts +++ b/packages/spright-components/src/chat-message/styles.ts @@ -10,15 +10,26 @@ import { import { display } from '../utilities/style/display'; export const styles = css` - ${display('block')} + ${display('flex')} :host { min-width: 16px; min-height: 16px; + + flex-direction: row; + justify-content: center; + } + + :host([status='outgoing']) { + justify-content: flex-end; + } + + :host([status='incoming']) { + justify-content: flex-start; } div { - max-width: calc(100%-20px); + max-width: calc(100% - 200px); width: fit-content; height: fit-content; padding: ${mediumPadding}; @@ -29,7 +40,11 @@ export const styles = css` border-radius: 8px; } - :host[actor='user'] div { - border-radius: 8px 8px 8px 0px + :host([status='outgoing']) div { + border-radius: 8px 8px 0px 8px; + } + + :host([status='incoming']) div { + border-radius: 8px 8px 8px 0px; } `; diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index dea794c0e0..cadc0bc6b9 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -1,12 +1,12 @@ /** - * An actor in a chat conversation. + * A message status in a chat conversation. * @public */ -export const ChatActor = { - bot: 'bot', +export const ChatMessageStatus = { + outgoing: 'outgoing', + incoming: 'incoming', system: 'system', - user: 'user', } as const; -export type ChatActor = - (typeof ChatActor)[keyof typeof ChatActor]; +export type ChatMessageStatus = + (typeof ChatMessageStatus)[keyof typeof ChatMessageStatus]; diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 21bcb1c8bb..8a8be7b406 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; import { chatMessageTag } from '../../../../spright-components/src/chat-message'; +import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { apiCategory, @@ -11,9 +12,13 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; +interface ChatMessageArgs { + status: ChatMessageStatus; +} + export default metadata; -interface ChatMessageTextArgs { +interface ChatMessageTextArgs extends ChatMessageArgs { text: string; } @@ -22,7 +27,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag}> + <${chatMessageTag} status=${x => x.status}> ${x => x.text} </${chatMessageTag}> `), @@ -31,13 +36,20 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { description: 'The text to display in the chat message.', table: { category: apiCategory.slots } }, + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } }, args: { text: 'How do I choose which version of Python to execute my script?', + status: ChatMessageStatus.incoming } }; -interface ChatMessageRichTextArgs { +interface ChatMessageRichTextArgs extends ChatMessageArgs { markdown: string; } export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { @@ -45,7 +57,7 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag}> + <${chatMessageTag} status=${x => x.status}> <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> </${chatMessageTag}> `), @@ -54,6 +66,12 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { description: 'Markdown text for the rich text viewer', table: { category: apiCategory.slots } }, + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } }, args: { markdown: @@ -66,5 +84,6 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { 3. Choose the desired version from the **Version** dropdown. You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`, + status: ChatMessageStatus.incoming } }; diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md index 31e4161b5f..cd5cfffe24 100644 --- a/specs/chat-components/README.md +++ b/specs/chat-components/README.md @@ -10,6 +10,7 @@ spright-chat-message - draws outline/bg, sizes its content ChatMessageSource = 'me' | 'them' | 'system' +'sent' | 'received' | 'status' 'outgoing' | 'incoming' | 'status' 'right' | 'left' | 'center' 'this-user' | 'other-user' | 'system' @@ -57,4 +58,10 @@ Notes: - rich text viewer would need more features for links, images - research a11y patterns for chat widgets - mention plugins for links - - \ No newline at end of file + - + + + Other examples + https://daisyui.com/components/chat/ + https://www.telerik.com/design-system/docs/components/chat/ + https://carbondesignsystem.com/community/patterns/chatbot/usage/ From 20f73fc4dce287ab274de9151976852984b22943 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:36:33 -0600 Subject: [PATCH 12/61] Move message under chat folder --- .../src/{chat-message => chat/message}/index.ts | 2 +- .../src/{chat-message => chat/message}/styles.ts | 2 +- .../src/{chat-message => chat/message}/template.ts | 0 .../{chat-message => chat/message}/tests/chat-message.spec.ts | 2 +- .../storybook/src/spright/chat/chat-message-matrix.stories.ts | 2 +- packages/storybook/src/spright/chat/chat-message.react.tsx | 2 +- packages/storybook/src/spright/chat/chat.mdx | 2 +- packages/storybook/src/spright/chat/chat.stories.ts | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) rename packages/spright-components/src/{chat-message => chat/message}/index.ts (94%) rename packages/spright-components/src/{chat-message => chat/message}/styles.ts (95%) rename packages/spright-components/src/{chat-message => chat/message}/template.ts (100%) rename packages/spright-components/src/{chat-message => chat/message}/tests/chat-message.spec.ts (93%) diff --git a/packages/spright-components/src/chat-message/index.ts b/packages/spright-components/src/chat/message/index.ts similarity index 94% rename from packages/spright-components/src/chat-message/index.ts rename to packages/spright-components/src/chat/message/index.ts index d56adcae5e..6c54a0f53c 100644 --- a/packages/spright-components/src/chat-message/index.ts +++ b/packages/spright-components/src/chat/message/index.ts @@ -2,7 +2,7 @@ import { attr, observable } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import { ChatMessageStatus } from '../chat/types'; +import { ChatMessageStatus } from '../types'; declare global { interface HTMLElementTagNameMap { diff --git a/packages/spright-components/src/chat-message/styles.ts b/packages/spright-components/src/chat/message/styles.ts similarity index 95% rename from packages/spright-components/src/chat-message/styles.ts rename to packages/spright-components/src/chat/message/styles.ts index 21fc4a0136..3ef48df61d 100644 --- a/packages/spright-components/src/chat-message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -7,7 +7,7 @@ import { fillSelectedColor, mediumPadding, } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; -import { display } from '../utilities/style/display'; +import { display } from '../../utilities/style/display'; export const styles = css` ${display('flex')} diff --git a/packages/spright-components/src/chat-message/template.ts b/packages/spright-components/src/chat/message/template.ts similarity index 100% rename from packages/spright-components/src/chat-message/template.ts rename to packages/spright-components/src/chat/message/template.ts diff --git a/packages/spright-components/src/chat-message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts similarity index 93% rename from packages/spright-components/src/chat-message/tests/chat-message.spec.ts rename to packages/spright-components/src/chat/message/tests/chat-message.spec.ts index ec63d1a2f3..c50363df92 100644 --- a/packages/spright-components/src/chat-message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import { ChatMessage, chatMessageTag } from '..'; -import { fixture, Fixture } from '../../utilities/tests/fixture'; +import { fixture, Fixture } from '../../../utilities/tests/fixture'; async function setup(): Promise<Fixture<ChatMessage>> { return await fixture<ChatMessage>( diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index d16928413f..b413d625c4 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -1,6 +1,6 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; -import { chatMessageTag } from '../../../../spright-components/src/chat-message'; +import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { createMatrix, sharedMatrixParameters, diff --git a/packages/storybook/src/spright/chat/chat-message.react.tsx b/packages/storybook/src/spright/chat/chat-message.react.tsx index 41b76a3bab..7ce30eba84 100644 --- a/packages/storybook/src/spright/chat/chat-message.react.tsx +++ b/packages/storybook/src/spright/chat/chat-message.react.tsx @@ -1,4 +1,4 @@ -import { ChatMessage } from '../../../../spright-components/src/chat-message'; +import { ChatMessage } from '../../../../spright-components/src/chat/message'; import { wrap } from '../../utilities/react-wrapper'; export const SprightChatMessage = wrap(ChatMessage); diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 28e79de443..59403c9347 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -1,7 +1,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; -import { chatMessageTag } from '../../../../spright-components/src/chat-message'; +import { chatMessageTag } from '../../../../spright-components/src/chat/message'; <Meta of={chatStories} /> <Title of={chatStories} /> diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 8a8be7b406..249f284988 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { chatMessageTag } from '../../../../spright-components/src/chat-message'; +import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { From 0b15993afae214889fccfedf39a26855a1d092fc Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:42:38 -0600 Subject: [PATCH 13/61] Initial conversation component --- .../src/chat/conversation/index.ts | 25 ++++++++++++++ .../src/chat/conversation/styles.ts | 19 +++++++++++ .../src/chat/conversation/template.ts | 11 ++++++ .../tests/chat-conversation.spec.ts | 34 +++++++++++++++++++ .../src/chat/message/index.ts | 2 +- 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 packages/spright-components/src/chat/conversation/index.ts create mode 100644 packages/spright-components/src/chat/conversation/styles.ts create mode 100644 packages/spright-components/src/chat/conversation/template.ts create mode 100644 packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts diff --git a/packages/spright-components/src/chat/conversation/index.ts b/packages/spright-components/src/chat/conversation/index.ts new file mode 100644 index 0000000000..eea28345d2 --- /dev/null +++ b/packages/spright-components/src/chat/conversation/index.ts @@ -0,0 +1,25 @@ +import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; +import { styles } from './styles'; +import { template } from './template'; + +declare global { + interface HTMLElementTagNameMap { + 'spright-chat-conversation': ChatConversation; + } +} + +/** + * A Spright component for displaying a series of chat messages + */ +export class ChatConversation extends FoundationElement { + +} + +const sprightChatConversation = ChatConversation.compose({ + baseName: 'chat-conversation', + template, + styles +}); + +DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatConversation()); +export const chatConversationTag = 'spright-chat-conversation'; diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts new file mode 100644 index 0000000000..8fd72aea60 --- /dev/null +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -0,0 +1,19 @@ +import { css } from '@microsoft/fast-element'; +import { + bodyFont, + bodyFontColor, + borderHoverColor, + borderWidth, + fillSelectedColor, + mediumPadding, +} from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; +import { display } from '../../utilities/style/display'; + +export const styles = css` + ${display('flex')} + + :host { + flex-direction: column; + justify-content: flex-start; + } +`; diff --git a/packages/spright-components/src/chat/conversation/template.ts b/packages/spright-components/src/chat/conversation/template.ts new file mode 100644 index 0000000000..b361fa3262 --- /dev/null +++ b/packages/spright-components/src/chat/conversation/template.ts @@ -0,0 +1,11 @@ +import { html } from '@microsoft/fast-element'; +import type { ChatConversation } from '.'; + +/* eslint-disable @typescript-eslint/indent */ +// prettier-ignore +export const template = html<ChatConversation>` + <div> + <slot></slot> + </div> +`; +/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts new file mode 100644 index 0000000000..b8b73c0c84 --- /dev/null +++ b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts @@ -0,0 +1,34 @@ +import { html } from '@microsoft/fast-element'; +import { ChatConversation, chatConversationTag } from '..'; +import { fixture, Fixture } from '../../../utilities/tests/fixture'; + +async function setup(): Promise<Fixture<ChatConversation>> { + return await fixture<ChatConversation>( + html`<${chatConversationTag}></${chatConversationTag}>` + ); +} + +describe('ChatConversation', () => { + let element: ChatConversation; + let connect: () => Promise<void>; + let disconnect: () => Promise<void>; + + beforeEach(async () => { + ({ element, connect, disconnect } = await setup()); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('can construct an element instance', () => { + expect(document.createElement(chatConversationTag)).toBeInstanceOf(ChatConversation); + }); + + it('should have a slot element in the shadow DOM', async () => { + await connect(); + expect( + (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName + ).toBe('SLOT'); + }); +}); diff --git a/packages/spright-components/src/chat/message/index.ts b/packages/spright-components/src/chat/message/index.ts index 6c54a0f53c..d031918dd4 100644 --- a/packages/spright-components/src/chat/message/index.ts +++ b/packages/spright-components/src/chat/message/index.ts @@ -1,4 +1,4 @@ -import { attr, observable } from '@microsoft/fast-element'; +import { attr } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; From badb124f9cbe31049d7e8459868838a261186c38 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:56:46 -0600 Subject: [PATCH 14/61] Docs for conversation --- packages/storybook/src/spright/chat/chat.mdx | 8 +++ .../src/spright/chat/chat.stories.ts | 64 ++++++++++++++++--- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 59403c9347..f0393ea4f2 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -1,6 +1,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; +import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; <Meta of={chatStories} /> @@ -21,6 +22,13 @@ TODO higher level window example <ComponentApisLink /> +### Chat conversation + +Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. + +<Canvas of={chatStories.chatConversation} /> +<Controls of={chatStories.chatConversation} /> + ### Chat Message Use the <Tag name={chatMessageTag} /> element to display content in a message. diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 249f284988..2487b99a55 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; +import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; @@ -12,6 +13,58 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; +interface ChatConversation { +} + +const markdownExample = `To configure your Python version: + +1. Select **Adapters...** from the **Configure** menu. + +2. Configure the Python adapter. + +3. Choose the desired version from the **Version** dropdown. + +You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; + +export const chatConversation: StoryObj<ChatConversation> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatConversationTag}> + <${chatMessageTag} status='outgoing'> + Hi, can you please help me? + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + Yeah sure, what do you need help with? + </${chatMessageTag}> + <${chatMessageTag} status='outgoing'> + Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> + </${chatMessageTag}> + </${chatConversationTag}> + + `), + argTypes: { + text: { + description: 'The text to display in the chat message.', + table: { category: apiCategory.slots } + }, + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + text: 'How do I choose which version of Python to execute my script?', + status: ChatMessageStatus.incoming + } +}; + interface ChatMessageArgs { status: ChatMessageStatus; } @@ -74,16 +127,7 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { } }, args: { - markdown: - `To configure your Python version: - - 1. Select **Adapters...** from the **Configure** menu. - - 2. Configure the Python adapter. - - 3. Choose the desired version from the **Version** dropdown. - - You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`, + markdown: markdownExample, status: ChatMessageStatus.incoming } }; From 5aaf44d4b31f91143c2639e448626dc734a51ed2 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:14:02 -0600 Subject: [PATCH 15/61] Padding between messages --- .../spright-components/src/chat/conversation/styles.ts | 8 ++------ .../spright-components/src/chat/conversation/template.ts | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts index 8fd72aea60..fb68c3e9f0 100644 --- a/packages/spright-components/src/chat/conversation/styles.ts +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -1,11 +1,6 @@ import { css } from '@microsoft/fast-element'; import { - bodyFont, - bodyFontColor, - borderHoverColor, - borderWidth, - fillSelectedColor, - mediumPadding, + standardPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../../utilities/style/display'; @@ -15,5 +10,6 @@ export const styles = css` :host { flex-direction: column; justify-content: flex-start; + row-gap: ${standardPadding} } `; diff --git a/packages/spright-components/src/chat/conversation/template.ts b/packages/spright-components/src/chat/conversation/template.ts index b361fa3262..3867b2710d 100644 --- a/packages/spright-components/src/chat/conversation/template.ts +++ b/packages/spright-components/src/chat/conversation/template.ts @@ -4,8 +4,6 @@ import type { ChatConversation } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore export const template = html<ChatConversation>` - <div> - <slot></slot> - </div> + <slot></slot> `; /* eslint-enable @typescript-eslint/indent */ From ecddda6f7bb53bbb7fb69047c986d6f0346539d8 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:48:32 -0600 Subject: [PATCH 16/61] Only outgoing messages in bubbles --- packages/spright-components/src/chat/message/styles.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 3ef48df61d..7851fe7a63 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -35,12 +35,11 @@ export const styles = css` padding: ${mediumPadding}; font: ${bodyFont}; color: ${bodyFontColor}; - background: ${fillSelectedColor}; - border: ${borderWidth} solid ${borderHoverColor}; - border-radius: 8px; } :host([status='outgoing']) div { + background: ${fillSelectedColor}; + border: ${borderWidth} solid ${borderHoverColor}; border-radius: 8px 8px 0px 8px; } From d232c8ed86df962f5481e6bac1522c9a5be06b11 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:48:41 -0600 Subject: [PATCH 17/61] background color --- packages/spright-components/src/chat/conversation/styles.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts index fb68c3e9f0..de11289f02 100644 --- a/packages/spright-components/src/chat/conversation/styles.ts +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -1,5 +1,6 @@ import { css } from '@microsoft/fast-element'; import { + applicationBackgroundColor, standardPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../../utilities/style/display'; @@ -10,6 +11,7 @@ export const styles = css` :host { flex-direction: column; justify-content: flex-start; - row-gap: ${standardPadding} + row-gap: ${standardPadding}; + background: ${applicationBackgroundColor}; } `; From df26a483b3fecb1e48ab1ec06bdc3b5721a05bad Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:49:08 -0600 Subject: [PATCH 18/61] More example message types --- packages/storybook/src/spright/chat/chat.mdx | 8 +- .../src/spright/chat/chat.stories.ts | 75 ++++++++++++++++++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index f0393ea4f2..31c077c4d4 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -29,7 +29,7 @@ Use the <Tag name={chatConversationTag} /> element to display a series of messag <Canvas of={chatStories.chatConversation} /> <Controls of={chatStories.chatConversation} /> -### Chat Message +### Chat message Use the <Tag name={chatMessageTag} /> element to display content in a message. @@ -39,6 +39,12 @@ Use the <Tag name={chatMessageTag} /> element to display content in a message. <Canvas of={chatStories.chatMessageRichText} /> <Controls of={chatStories.chatMessageRichText} /> +<Canvas of={chatStories.chatMessageSpinner} /> +<Controls of={chatStories.chatMessageSpinner} /> + +<Canvas of={chatStories.chatMessagePrompts} /> +<Controls of={chatStories.chatMessagePrompts} /> + {/* ## Usage */} {/* ## Accessibility */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 2487b99a55..c00ab46ca1 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,9 +1,11 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; +import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; +import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { apiCategory, createUserSelectedThemeStory, @@ -44,6 +46,13 @@ export const chatConversation: StoryObj<ChatConversation> = { <${chatMessageTag} status='incoming'> <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${spinnerTag} appearance='accent'></${spinnerTag}> + </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> + <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> + </${chatMessageTag}> </${chatConversationTag}> `), @@ -61,7 +70,7 @@ export const chatConversation: StoryObj<ChatConversation> = { }, args: { text: 'How do I choose which version of Python to execute my script?', - status: ChatMessageStatus.incoming + status: ChatMessageStatus.outgoing } }; @@ -98,7 +107,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { }, args: { text: 'How do I choose which version of Python to execute my script?', - status: ChatMessageStatus.incoming + status: ChatMessageStatus.outgoing } }; @@ -128,6 +137,66 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { }, args: { markdown: markdownExample, - status: ChatMessageStatus.incoming + status: ChatMessageStatus.outgoing + } +}; + +export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} status=${x => x.status}> + <${spinnerTag} appearance='accent'></${spinnerTag}> + </${chatMessageTag}> + `), + argTypes: { + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + status: ChatMessageStatus.system + } +}; + +interface ChatMessagePrompts extends ChatMessageArgs { + prompt1: string; + prompt2: string; +} +export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} status=${x => x.status}> + <${buttonTag} appearance='block'>${x => x.prompt1}</${buttonTag}> + <${buttonTag} appearance='block'>${x => x.prompt2}</${buttonTag}> + </${chatMessageTag}> + `), + argTypes: { + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + }, + prompt1: { + description: 'The first prompt text', + table: { category: apiCategory.slots } + }, + prompt2: { + description: 'The second prompt text', + table: { category: apiCategory.slots } + } + + }, + args: { + status: ChatMessageStatus.system, + prompt1: 'Explain how to do my job', + prompt2: 'Help me with my childhood trauma' } }; From ad64243911b897435c80a6b8d54ae2daa80ddadc Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:37:36 -0600 Subject: [PATCH 19/61] Conversation vertical scroll --- packages/spright-components/src/chat/conversation/styles.ts | 1 + packages/spright-components/src/chat/message/styles.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts index de11289f02..323dede369 100644 --- a/packages/spright-components/src/chat/conversation/styles.ts +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -13,5 +13,6 @@ export const styles = css` justify-content: flex-start; row-gap: ${standardPadding}; background: ${applicationBackgroundColor}; + overflow-y: scroll; } `; diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 7851fe7a63..56e9052ef2 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -18,6 +18,7 @@ export const styles = css` flex-direction: row; justify-content: center; + flex-shrink: 0; } :host([status='outgoing']) { From dd13b5964533090eadb8d71e6de11fc6d9d01a98 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:55:37 -0600 Subject: [PATCH 20/61] Add window component (initially copied from conversation) --- .../src/chat/window/index.ts | 25 +++++++++++++ .../src/chat/window/styles.ts | 35 +++++++++++++++++++ .../src/chat/window/template.ts | 9 +++++ .../src/chat/window/tests/chat-window.spec.ts | 34 ++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 packages/spright-components/src/chat/window/index.ts create mode 100644 packages/spright-components/src/chat/window/styles.ts create mode 100644 packages/spright-components/src/chat/window/template.ts create mode 100644 packages/spright-components/src/chat/window/tests/chat-window.spec.ts diff --git a/packages/spright-components/src/chat/window/index.ts b/packages/spright-components/src/chat/window/index.ts new file mode 100644 index 0000000000..3cf5162780 --- /dev/null +++ b/packages/spright-components/src/chat/window/index.ts @@ -0,0 +1,25 @@ +import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; +import { styles } from './styles'; +import { template } from './template'; + +declare global { + interface HTMLElementTagNameMap { + 'spright-chat-window': ChatWindow; + } +} + +/** + * A Spright component for displaying a chat window + */ +export class ChatWindow extends FoundationElement { + +} + +const sprightChatWindow = ChatWindow.compose({ + baseName: 'chat-window', + template, + styles +}); + +DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatWindow()); +export const chatWindowTag = 'spright-chat-window'; diff --git a/packages/spright-components/src/chat/window/styles.ts b/packages/spright-components/src/chat/window/styles.ts new file mode 100644 index 0000000000..047343185c --- /dev/null +++ b/packages/spright-components/src/chat/window/styles.ts @@ -0,0 +1,35 @@ +import { css } from '@microsoft/fast-element'; +import { + applicationBackgroundColor, + standardPadding +} from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; +import { display } from '../../utilities/style/display'; +import { chatMessageTag } from '../message'; + +export const styles = css` + ${display('flex')} + + :host { + flex-direction: column; + justify-content: flex-start; + row-gap: ${standardPadding}; + background: ${applicationBackgroundColor}; + overflow-y: scroll; + } + + ${chatMessageTag} { + animation: show 600ms 100ms cubic-bezier(0.38, 0.97, 0.56, 0.76) forwards; + + opacity: 0; + + transform: rotateX(-90deg); + transform-origin: top center; + } + + @keyframes show { + 100% { + opacity: 1; + transform: none; + } + } +`; diff --git a/packages/spright-components/src/chat/window/template.ts b/packages/spright-components/src/chat/window/template.ts new file mode 100644 index 0000000000..11c8529ed6 --- /dev/null +++ b/packages/spright-components/src/chat/window/template.ts @@ -0,0 +1,9 @@ +import { html } from '@microsoft/fast-element'; +import type { ChatWindow } from '.'; + +/* eslint-disable @typescript-eslint/indent */ +// prettier-ignore +export const template = html<ChatWindow>` + <slot></slot> +`; +/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/window/tests/chat-window.spec.ts b/packages/spright-components/src/chat/window/tests/chat-window.spec.ts new file mode 100644 index 0000000000..e9551298e8 --- /dev/null +++ b/packages/spright-components/src/chat/window/tests/chat-window.spec.ts @@ -0,0 +1,34 @@ +import { html } from '@microsoft/fast-element'; +import { ChatWindow, chatWindowTag } from '..'; +import { fixture, Fixture } from '../../../utilities/tests/fixture'; + +async function setup(): Promise<Fixture<ChatWindow>> { + return await fixture<ChatWindow>( + html`<${chatWindowTag}></${chatWindowTag}>` + ); +} + +describe('ChatWindow', () => { + let element: ChatWindow; + let connect: () => Promise<void>; + let disconnect: () => Promise<void>; + + beforeEach(async () => { + ({ element, connect, disconnect } = await setup()); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('can construct an element instance', () => { + expect(document.createElement(chatWindowTag)).toBeInstanceOf(ChatWindow); + }); + + it('should have a slot element in the shadow DOM', async () => { + await connect(); + expect( + (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName + ).toBe('SLOT'); + }); +}); From 3649d591d68dbf64d30f6ff26df4bffc93392bb9 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:43:38 -0600 Subject: [PATCH 21/61] Window toolbars --- .../src/chat/window/styles.ts | 26 +------- .../src/chat/window/template.ts | 59 ++++++++++++++++++- packages/storybook/src/spright/chat/chat.mdx | 4 +- .../src/spright/chat/chat.stories.ts | 48 +++++++++++++++ 4 files changed, 112 insertions(+), 25 deletions(-) diff --git a/packages/spright-components/src/chat/window/styles.ts b/packages/spright-components/src/chat/window/styles.ts index 047343185c..1ff4a17533 100644 --- a/packages/spright-components/src/chat/window/styles.ts +++ b/packages/spright-components/src/chat/window/styles.ts @@ -1,35 +1,15 @@ import { css } from '@microsoft/fast-element'; -import { - applicationBackgroundColor, - standardPadding -} from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; +import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; import { display } from '../../utilities/style/display'; -import { chatMessageTag } from '../message'; export const styles = css` ${display('flex')} :host { flex-direction: column; - justify-content: flex-start; - row-gap: ${standardPadding}; - background: ${applicationBackgroundColor}; - overflow-y: scroll; } - ${chatMessageTag} { - animation: show 600ms 100ms cubic-bezier(0.38, 0.97, 0.56, 0.76) forwards; - - opacity: 0; - - transform: rotateX(-90deg); - transform-origin: top center; - } - - @keyframes show { - 100% { - opacity: 1; - transform: none; - } + ${textFieldTag} { + flex-grow: 1; } `; diff --git a/packages/spright-components/src/chat/window/template.ts b/packages/spright-components/src/chat/window/template.ts index 11c8529ed6..d0a6c0d949 100644 --- a/packages/spright-components/src/chat/window/template.ts +++ b/packages/spright-components/src/chat/window/template.ts @@ -1,9 +1,66 @@ import { html } from '@microsoft/fast-element'; +import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; +import { buttonTag } from '@ni/nimble-components/dist/esm/button'; +import { iconAddTag } from '@ni/nimble-components/dist/esm/icons/add'; +import { iconBarsTag } from '@ni/nimble-components/dist/esm/icons/bars'; +import { iconDownloadTag } from '@ni/nimble-components/dist/esm/icons/download'; +import { iconLightbulbTag } from '@ni/nimble-components/dist/esm/icons/lightbulb'; +import { iconPaperPlaneTag } from '@ni/nimble-components/dist/esm/icons/paper-plane'; +import { iconPaperclipTag } from '@ni/nimble-components/dist/esm/icons/paperclip'; +import { iconShareNodesTag } from '@ni/nimble-components/dist/esm/icons/share-nodes'; +import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; +import { TextFieldAppearance } from '@ni/nimble-components/dist/esm/text-field/types'; +import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; +import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; +import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; + import type { ChatWindow } from '.'; +import { chatConversationTag } from '../conversation'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore export const template = html<ChatWindow>` - <slot></slot> + <${toolbarTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> + Download + <${iconDownloadTag} slot='start'></${iconDownloadTag}> + </${buttonTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> + Share + <${iconShareNodesTag} slot='start'></${iconShareNodesTag}> + </${buttonTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> + Menu + <${iconBarsTag} slot='start'></${iconBarsTag}> + </${buttonTag}> + </${toolbarTag}> + <${chatConversationTag}> + <slot></slot> + </${chatConversationTag}> + <${themeProviderTag} theme='${Theme.color}'> + <${toolbarTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> + Add chat + <${iconAddTag} slot='start'></${iconAddTag}> + </${buttonTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> + Text prompt + <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> + </${buttonTag}> + <${textFieldTag} + placeholder='How can I assist you today?' + appearance=${TextFieldAppearance.block} + > + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='actions'> + Submit + <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> + </${buttonTag}> + </${textFieldTag}> + <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> + Attach + <${iconPaperclipTag} slot='start'></${iconPaperclipTag}> + </${buttonTag}> + </${toolbarTag}> + </${themeProviderTag}> `; /* eslint-enable @typescript-eslint/indent */ diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 31c077c4d4..f04e647506 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -14,7 +14,7 @@ for connecting them to a source of data. Components include low level chat messages and input fields and higher level composite components representing an entire conversation or chat window. -<Canvas of={chatStories.chatMessageText} /> +<Canvas of={chatStories.chatWindow} /> ## API @@ -22,6 +22,8 @@ TODO higher level window example <ComponentApisLink /> +### Chat window + ### Chat conversation Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index c00ab46ca1..6c30dc8a9a 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -4,6 +4,7 @@ import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; +import { chatWindowTag } from '../../../../spright-components/src/chat/window'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { @@ -28,6 +29,53 @@ const markdownExample = `To configure your Python version: You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; +export const chatWindow: StoryObj<ChatConversation> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatWindowTag}> + <${chatConversationTag}> + <${chatMessageTag} status='outgoing'> + Hi, can you please help me? + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + Yeah sure, what do you need help with? + </${chatMessageTag}> + <${chatMessageTag} status='outgoing'> + Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> + </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${spinnerTag} appearance='accent'></${spinnerTag}> + </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> + <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> + </${chatMessageTag}> + </${chatConversationTag}> + </${chatWindowTag}> + `), + argTypes: { + text: { + description: 'The text to display in the chat message.', + table: { category: apiCategory.slots } + }, + status: { + options: Object.keys(ChatMessageStatus), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + text: 'How do I choose which version of Python to execute my script?', + status: ChatMessageStatus.outgoing + } +}; + export const chatConversation: StoryObj<ChatConversation> = { parameters: { actions: {} From 81b81aa21bdeb4d5c42bf382f153be53eb50c589 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:50:19 -0600 Subject: [PATCH 22/61] Chat input toolbar --- .../src/chat/input-toolbar/index.ts | 69 +++++++++++++++++++ .../src/chat/input-toolbar/styles.ts | 16 +++++ .../src/chat/input-toolbar/template.ts | 39 +++++++++++ .../tests/chat-input-toolbar.spec.ts | 34 +++++++++ packages/spright-components/src/chat/types.ts | 8 +++ packages/storybook/src/spright/chat/chat.mdx | 10 ++- .../src/spright/chat/chat.stories.ts | 12 ++++ 7 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 packages/spright-components/src/chat/input-toolbar/index.ts create mode 100644 packages/spright-components/src/chat/input-toolbar/styles.ts create mode 100644 packages/spright-components/src/chat/input-toolbar/template.ts create mode 100644 packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts diff --git a/packages/spright-components/src/chat/input-toolbar/index.ts b/packages/spright-components/src/chat/input-toolbar/index.ts new file mode 100644 index 0000000000..01c0973705 --- /dev/null +++ b/packages/spright-components/src/chat/input-toolbar/index.ts @@ -0,0 +1,69 @@ +import { attr } from '@microsoft/fast-element'; +import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; +import type { TextField } from '@ni/nimble-components/dist/esm/text-field'; +import { styles } from './styles'; +import { template } from './template'; +import type { ChatInputToolbarSubmitMessageEventDetail } from '../types'; + +declare global { + interface HTMLElementTagNameMap { + 'spright-chat-input-toolbar': ChatInputToolbar; + } +} + +/** + * A Spright component for collecting user chat input + */ +export class ChatInputToolbar extends FoundationElement { + // TODO: + // DISABLED + // PLACEHOLDER + // INPUT TEXT + // TEST SLOTS + + /** + * The placeholder text for the input field + * + * @public + * @remarks + * HTML Attribute: error-text + */ + @attr({ attribute: 'placeholder' }) + public placeholder?: string; + + public textField?: TextField; + + /** + * @internal + */ + public onTextFieldKeyUp(event: KeyboardEvent): void { + if (event.key === 'Enter') { + this.submitMessage(); + } + } + + /** + * @internal + */ + public submitMessage(): void { + if (!this.textField) { + return; + } + const message = this.textField.value; + const eventDetail: ChatInputToolbarSubmitMessageEventDetail = { + message + }; + this.textField.value = ''; + this.textField.focus(); + this.$emit('submit', eventDetail); + } +} + +const sprightChatInputToolbar = ChatInputToolbar.compose({ + baseName: 'chat-input-toolbar', + template, + styles +}); + +DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatInputToolbar()); +export const chatInputToolbarTag = 'spright-chat-input-toolbar'; diff --git a/packages/spright-components/src/chat/input-toolbar/styles.ts b/packages/spright-components/src/chat/input-toolbar/styles.ts new file mode 100644 index 0000000000..e75691ca98 --- /dev/null +++ b/packages/spright-components/src/chat/input-toolbar/styles.ts @@ -0,0 +1,16 @@ +import { css } from '@microsoft/fast-element'; +import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; +import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; +import { display } from '../../utilities/style/display'; + +export const styles = css` + ${display('flex')} + + ${toolbarTag} { + width: 100%; + } + + ${textFieldTag} { + flex-grow: 1; + } +`; diff --git a/packages/spright-components/src/chat/input-toolbar/template.ts b/packages/spright-components/src/chat/input-toolbar/template.ts new file mode 100644 index 0000000000..fdbcd8c978 --- /dev/null +++ b/packages/spright-components/src/chat/input-toolbar/template.ts @@ -0,0 +1,39 @@ +import { html, ref } from '@microsoft/fast-element'; +import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; +import { buttonTag } from '@ni/nimble-components/dist/esm/button'; +import { iconPaperPlaneTag } from '@ni/nimble-components/dist/esm/icons/paper-plane'; +import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; +import { TextFieldAppearance } from '@ni/nimble-components/dist/esm/text-field/types'; +import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; +import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; +import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; + +import type { ChatInputToolbar } from '.'; + +/* eslint-disable @typescript-eslint/indent */ +// prettier-ignore +export const template = html<ChatInputToolbar>` + <${themeProviderTag} theme='${Theme.color}'> + <${toolbarTag}> + <slot name="start"></slot> + <${textFieldTag} + placeholder='How can I assist you today?' + appearance=${TextFieldAppearance.block} + @keyup="${(x, c) => x.onTextFieldKeyUp(c.event as KeyboardEvent)}" + ${ref('textField')} + > + <${buttonTag} + appearance='${ButtonAppearance.ghost}' + content-hidden + slot='actions' + @click="${x => x.submitMessage()}" + > + Submit + <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> + </${buttonTag}> + </${textFieldTag}> + <slot name="end"></slot> + </${toolbarTag}> + </${themeProviderTag}> +`; +/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts b/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts new file mode 100644 index 0000000000..f71759c8b3 --- /dev/null +++ b/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts @@ -0,0 +1,34 @@ +import { html } from '@microsoft/fast-element'; +import { ChatInputToolbar, chatInputToolbarTag } from '..'; +import { fixture, Fixture } from '../../../utilities/tests/fixture'; + +async function setup(): Promise<Fixture<ChatInputToolbar>> { + return await fixture<ChatInputToolbar>( + html`<${chatInputToolbarTag}></${chatInputToolbarTag}>` + ); +} + +describe('ChatInputToolbar', () => { + let element: ChatInputToolbar; + let connect: () => Promise<void>; + let disconnect: () => Promise<void>; + + beforeEach(async () => { + ({ element, connect, disconnect } = await setup()); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('can construct an element instance', () => { + expect(document.createElement(chatInputToolbarTag)).toBeInstanceOf(ChatInputToolbar); + }); + + it('should have a slot element in the shadow DOM', async () => { + await connect(); + expect( + (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName + ).toBe('SLOT'); + }); +}); diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index cadc0bc6b9..e79ee007d4 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -10,3 +10,11 @@ export const ChatMessageStatus = { export type ChatMessageStatus = (typeof ChatMessageStatus)[keyof typeof ChatMessageStatus]; + +/** + * The type of the detail associated with the `submit` + * event on the input toolbar. + */ +export interface ChatInputToolbarSubmitMessageEventDetail { + message: string; +} \ No newline at end of file diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index f04e647506..9e96da34b3 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -2,6 +2,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; +import { chatInputToolbarTag } from '../../../../spright-components/src/chat/input-toolbar'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; <Meta of={chatStories} /> @@ -18,12 +19,17 @@ representing an entire conversation or chat window. ## API -TODO higher level window example - <ComponentApisLink /> ### Chat window +### Chat input toolbar + +Use the <Tag name={chatInputToolbarTag} /> element to collect user input for a chat conversation. + +<Canvas of={chatStories.chatInputToolbar} /> +<Controls of={chatStories.chatInputToolbar} /> + ### Chat conversation Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 6c30dc8a9a..4e1794691e 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; +import { chatInputToolbarTag } from '../../../../spright-components/src/chat/input-toolbar'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { chatWindowTag } from '../../../../spright-components/src/chat/window'; @@ -248,3 +249,14 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { prompt2: 'Help me with my childhood trauma' } }; + +export const chatInputToolbar: StoryObj<ChatConversation> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatInputToolbarTag}> + + </${chatInputToolbarTag}> + `), +}; \ No newline at end of file From 0eb06b559b9085f895e1fb3c308b371252e819ea Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:19:10 -0600 Subject: [PATCH 23/61] Type in chat window --- packages/storybook/src/spright/chat/chat.mdx | 2 - .../src/spright/chat/chat.stories.ts | 97 +++++++++++-------- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 9e96da34b3..da90aba236 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -21,8 +21,6 @@ representing an entire conversation or chat window. <ComponentApisLink /> -### Chat window - ### Chat input toolbar Use the <Tag name={chatInputToolbarTag} /> element to collect user input for a chat conversation. diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 4e1794691e..3f18cd886a 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,11 +1,10 @@ import type { Meta, StoryObj } from '@storybook/html'; -import { html } from '@microsoft/fast-element'; +import { html, ref } from '@microsoft/fast-element'; import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatInputToolbarTag } from '../../../../spright-components/src/chat/input-toolbar'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; -import { chatWindowTag } from '../../../../spright-components/src/chat/window'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { @@ -17,7 +16,11 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; -interface ChatConversation { +interface ChatWindow { + inputToolbarRef: ChatInputToolbar; + submitChatMessage: ( + inputToolbarRef: ChatInputToolbar, + ) => void; } const markdownExample = `To configure your Python version: @@ -30,53 +33,57 @@ const markdownExample = `To configure your Python version: You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; -export const chatWindow: StoryObj<ChatConversation> = { +export const chatWindow: StoryObj<ChatWindow> = { parameters: { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatWindowTag}> - <${chatConversationTag}> - <${chatMessageTag} status='outgoing'> - Hi, can you please help me? - </${chatMessageTag}> - <${chatMessageTag} status='incoming'> - Yeah sure, what do you need help with? - </${chatMessageTag}> - <${chatMessageTag} status='outgoing'> - Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. - </${chatMessageTag}> - <${chatMessageTag} status='incoming'> - <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> - </${chatMessageTag}> - <${chatMessageTag} status='system'> - <${spinnerTag} appearance='accent'></${spinnerTag}> - </${chatMessageTag}> - <${chatMessageTag} status='system'> - <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> - <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> - </${chatMessageTag}> - </${chatConversationTag}> - </${chatWindowTag}> - `), + <${chatConversationTag}> + <${chatMessageTag} status='outgoing'> + Hi, can you please help me? + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + Yeah sure, what do you need help with? + </${chatMessageTag}> + <${chatMessageTag} status='outgoing'> + Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. + </${chatMessageTag}> + <${chatMessageTag} status='incoming'> + <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> + </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${spinnerTag} appearance='accent'></${spinnerTag}> + </${chatMessageTag}> + <${chatMessageTag} status='system'> + <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> + <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> + </${chatMessageTag}> + </${chatConversationTag}> + <${chatInputToolbarTag} + ${ref('inputToolbarRef')} + @submit="${x => x.submitChatMessage(x.inputToolbarRef)}" + > + </${chatInputToolbarTag}>`), argTypes: { - text: { - description: 'The text to display in the chat message.', - table: { category: apiCategory.slots } - }, - status: { - options: Object.keys(ChatMessageStatus), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } + submitChatMessage: { + table: { + disable: true + } } }, args: { - text: 'How do I choose which version of Python to execute my script?', - status: ChatMessageStatus.outgoing + submitChatMessage: (inputToolbarRef) => { + const chatMessage = document.createElement(chatMessageTag); + chatMessage.textContent = 'this is a test'; + + const chatConversationElement = document.querySelector(chatConversationTag)!; + chatConversationElement.appendChild(chatMessage); + } } }; +interface ChatConversation { +} export const chatConversation: StoryObj<ChatConversation> = { parameters: { actions: {} @@ -250,13 +257,21 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { } }; -export const chatInputToolbar: StoryObj<ChatConversation> = { +interface ChatInputToolbar { +} + +export const chatInputToolbar: StoryObj<ChatInputToolbar> = { parameters: { actions: {} }, render: createUserSelectedThemeStory(html` <${chatInputToolbarTag}> - </${chatInputToolbarTag}> `), + argTypes: { + + }, + args: { + + } }; \ No newline at end of file From a67499ccbd26d54314a160ecd4cdbe6b89248da1 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:36:13 -0600 Subject: [PATCH 24/61] Padding around conversation --- packages/spright-components/src/chat/conversation/styles.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts index 323dede369..e87cfdde11 100644 --- a/packages/spright-components/src/chat/conversation/styles.ts +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -1,6 +1,7 @@ import { css } from '@microsoft/fast-element'; import { applicationBackgroundColor, + mediumPadding, standardPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../../utilities/style/display'; @@ -12,6 +13,7 @@ export const styles = css` flex-direction: column; justify-content: flex-start; row-gap: ${standardPadding}; + padding: ${mediumPadding}; background: ${applicationBackgroundColor}; overflow-y: scroll; } From 08ad3397eadd057f2ffe00919ed730ec0eb77b32 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:13:12 -0600 Subject: [PATCH 25/61] Work around theme provider conflict in build --- .../src/chat/input-toolbar/template.ts | 17 +++++++--- .../src/chat/window/template.ts | 33 ------------------- 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/packages/spright-components/src/chat/input-toolbar/template.ts b/packages/spright-components/src/chat/input-toolbar/template.ts index fdbcd8c978..dea02e63ae 100644 --- a/packages/spright-components/src/chat/input-toolbar/template.ts +++ b/packages/spright-components/src/chat/input-toolbar/template.ts @@ -1,11 +1,12 @@ import { html, ref } from '@microsoft/fast-element'; import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; import { buttonTag } from '@ni/nimble-components/dist/esm/button'; +import { iconLightbulbTag } from '@ni/nimble-components/dist/esm/icons/lightbulb'; import { iconPaperPlaneTag } from '@ni/nimble-components/dist/esm/icons/paper-plane'; import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; import { TextFieldAppearance } from '@ni/nimble-components/dist/esm/text-field/types'; -import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; -import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; +// import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; +// import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; import type { ChatInputToolbar } from '.'; @@ -13,7 +14,7 @@ import type { ChatInputToolbar } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore export const template = html<ChatInputToolbar>` - <${themeProviderTag} theme='${Theme.color}'> + <ni-nimble-theme-provider theme='color'> <${toolbarTag}> <slot name="start"></slot> <${textFieldTag} @@ -22,6 +23,14 @@ export const template = html<ChatInputToolbar>` @keyup="${(x, c) => x.onTextFieldKeyUp(c.event as KeyboardEvent)}" ${ref('textField')} > + <${buttonTag} + appearance='${ButtonAppearance.ghost}' + content-hidden + slot='start' + > + Prompt + <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> + </${buttonTag}> <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden @@ -34,6 +43,6 @@ export const template = html<ChatInputToolbar>` </${textFieldTag}> <slot name="end"></slot> </${toolbarTag}> - </${themeProviderTag}> + </ni-nimble-theme-provider> `; /* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/window/template.ts b/packages/spright-components/src/chat/window/template.ts index d0a6c0d949..dc49c5d5e3 100644 --- a/packages/spright-components/src/chat/window/template.ts +++ b/packages/spright-components/src/chat/window/template.ts @@ -1,17 +1,9 @@ import { html } from '@microsoft/fast-element'; import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; import { buttonTag } from '@ni/nimble-components/dist/esm/button'; -import { iconAddTag } from '@ni/nimble-components/dist/esm/icons/add'; import { iconBarsTag } from '@ni/nimble-components/dist/esm/icons/bars'; import { iconDownloadTag } from '@ni/nimble-components/dist/esm/icons/download'; -import { iconLightbulbTag } from '@ni/nimble-components/dist/esm/icons/lightbulb'; -import { iconPaperPlaneTag } from '@ni/nimble-components/dist/esm/icons/paper-plane'; -import { iconPaperclipTag } from '@ni/nimble-components/dist/esm/icons/paperclip'; import { iconShareNodesTag } from '@ni/nimble-components/dist/esm/icons/share-nodes'; -import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; -import { TextFieldAppearance } from '@ni/nimble-components/dist/esm/text-field/types'; -import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; -import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; import type { ChatWindow } from '.'; @@ -37,30 +29,5 @@ export const template = html<ChatWindow>` <${chatConversationTag}> <slot></slot> </${chatConversationTag}> - <${themeProviderTag} theme='${Theme.color}'> - <${toolbarTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> - Add chat - <${iconAddTag} slot='start'></${iconAddTag}> - </${buttonTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> - Text prompt - <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> - </${buttonTag}> - <${textFieldTag} - placeholder='How can I assist you today?' - appearance=${TextFieldAppearance.block} - > - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='actions'> - Submit - <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> - </${buttonTag}> - </${textFieldTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden> - Attach - <${iconPaperclipTag} slot='start'></${iconPaperclipTag}> - </${buttonTag}> - </${toolbarTag}> - </${themeProviderTag}> `; /* eslint-enable @typescript-eslint/indent */ From e23117e19e130297410eab361def15afaf9abd6e Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:41:21 -0600 Subject: [PATCH 26/61] work around theme provider styles --- packages/spright-components/src/chat/input-toolbar/styles.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/spright-components/src/chat/input-toolbar/styles.ts b/packages/spright-components/src/chat/input-toolbar/styles.ts index e75691ca98..b7c4452024 100644 --- a/packages/spright-components/src/chat/input-toolbar/styles.ts +++ b/packages/spright-components/src/chat/input-toolbar/styles.ts @@ -6,6 +6,11 @@ import { display } from '../../utilities/style/display'; export const styles = css` ${display('flex')} + /* TODO: Inline theme provider styles to work around build issue */ + ni-nimble-theme-provider { + display: contents; + } + ${toolbarTag} { width: 100%; } From 2207d4f2d0b0856477b0fde143d9e2825b5faaf9 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:53:20 -0600 Subject: [PATCH 27/61] Fixture errors --- .../src/chat/conversation/tests/chat-conversation.spec.ts | 2 +- .../src/chat/message/tests/chat-message.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts index b8b73c0c84..f9869cb59b 100644 --- a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts +++ b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import { ChatConversation, chatConversationTag } from '..'; -import { fixture, Fixture } from '../../../utilities/tests/fixture'; +import { fixture, type Fixture } from '../../../utilities/tests/fixture'; async function setup(): Promise<Fixture<ChatConversation>> { return await fixture<ChatConversation>( diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index c50363df92..02749a951b 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import { ChatMessage, chatMessageTag } from '..'; -import { fixture, Fixture } from '../../../utilities/tests/fixture'; +import { fixture, type Fixture } from '../../../utilities/tests/fixture'; async function setup(): Promise<Fixture<ChatMessage>> { return await fixture<ChatMessage>( From 463a99f733ce876a9025ab6f6fa041651528f8c8 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 21 Jan 2025 16:00:17 -0600 Subject: [PATCH 28/61] More Fixture build errors --- .../src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts | 2 +- .../src/chat/window/tests/chat-window.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts b/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts index f71759c8b3..2c72249181 100644 --- a/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts +++ b/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import { ChatInputToolbar, chatInputToolbarTag } from '..'; -import { fixture, Fixture } from '../../../utilities/tests/fixture'; +import { fixture, type Fixture } from '../../../utilities/tests/fixture'; async function setup(): Promise<Fixture<ChatInputToolbar>> { return await fixture<ChatInputToolbar>( diff --git a/packages/spright-components/src/chat/window/tests/chat-window.spec.ts b/packages/spright-components/src/chat/window/tests/chat-window.spec.ts index e9551298e8..a72dc30acc 100644 --- a/packages/spright-components/src/chat/window/tests/chat-window.spec.ts +++ b/packages/spright-components/src/chat/window/tests/chat-window.spec.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import { ChatWindow, chatWindowTag } from '..'; -import { fixture, Fixture } from '../../../utilities/tests/fixture'; +import { fixture, type Fixture } from '../../../utilities/tests/fixture'; async function setup(): Promise<Fixture<ChatWindow>> { return await fixture<ChatWindow>( From a57c93426a6a3a1921b8153f4831f4b408a38ec9 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 21 Jan 2025 17:20:51 -0600 Subject: [PATCH 29/61] Fix build --- .../src/chat/input-toolbar/index.ts | 69 ----------------- .../src/chat/input-toolbar/styles.ts | 21 ----- .../src/chat/input-toolbar/template.ts | 48 ------------ .../tests/chat-input-toolbar.spec.ts | 34 --------- packages/spright-components/src/chat/types.ts | 8 -- packages/storybook/src/spright/chat/chat.mdx | 8 -- .../src/spright/chat/chat.stories.ts | 76 +++++++++---------- 7 files changed, 37 insertions(+), 227 deletions(-) delete mode 100644 packages/spright-components/src/chat/input-toolbar/index.ts delete mode 100644 packages/spright-components/src/chat/input-toolbar/styles.ts delete mode 100644 packages/spright-components/src/chat/input-toolbar/template.ts delete mode 100644 packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts diff --git a/packages/spright-components/src/chat/input-toolbar/index.ts b/packages/spright-components/src/chat/input-toolbar/index.ts deleted file mode 100644 index 01c0973705..0000000000 --- a/packages/spright-components/src/chat/input-toolbar/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { attr } from '@microsoft/fast-element'; -import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; -import type { TextField } from '@ni/nimble-components/dist/esm/text-field'; -import { styles } from './styles'; -import { template } from './template'; -import type { ChatInputToolbarSubmitMessageEventDetail } from '../types'; - -declare global { - interface HTMLElementTagNameMap { - 'spright-chat-input-toolbar': ChatInputToolbar; - } -} - -/** - * A Spright component for collecting user chat input - */ -export class ChatInputToolbar extends FoundationElement { - // TODO: - // DISABLED - // PLACEHOLDER - // INPUT TEXT - // TEST SLOTS - - /** - * The placeholder text for the input field - * - * @public - * @remarks - * HTML Attribute: error-text - */ - @attr({ attribute: 'placeholder' }) - public placeholder?: string; - - public textField?: TextField; - - /** - * @internal - */ - public onTextFieldKeyUp(event: KeyboardEvent): void { - if (event.key === 'Enter') { - this.submitMessage(); - } - } - - /** - * @internal - */ - public submitMessage(): void { - if (!this.textField) { - return; - } - const message = this.textField.value; - const eventDetail: ChatInputToolbarSubmitMessageEventDetail = { - message - }; - this.textField.value = ''; - this.textField.focus(); - this.$emit('submit', eventDetail); - } -} - -const sprightChatInputToolbar = ChatInputToolbar.compose({ - baseName: 'chat-input-toolbar', - template, - styles -}); - -DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatInputToolbar()); -export const chatInputToolbarTag = 'spright-chat-input-toolbar'; diff --git a/packages/spright-components/src/chat/input-toolbar/styles.ts b/packages/spright-components/src/chat/input-toolbar/styles.ts deleted file mode 100644 index b7c4452024..0000000000 --- a/packages/spright-components/src/chat/input-toolbar/styles.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { css } from '@microsoft/fast-element'; -import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; -import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; -import { display } from '../../utilities/style/display'; - -export const styles = css` - ${display('flex')} - - /* TODO: Inline theme provider styles to work around build issue */ - ni-nimble-theme-provider { - display: contents; - } - - ${toolbarTag} { - width: 100%; - } - - ${textFieldTag} { - flex-grow: 1; - } -`; diff --git a/packages/spright-components/src/chat/input-toolbar/template.ts b/packages/spright-components/src/chat/input-toolbar/template.ts deleted file mode 100644 index dea02e63ae..0000000000 --- a/packages/spright-components/src/chat/input-toolbar/template.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { html, ref } from '@microsoft/fast-element'; -import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; -import { buttonTag } from '@ni/nimble-components/dist/esm/button'; -import { iconLightbulbTag } from '@ni/nimble-components/dist/esm/icons/lightbulb'; -import { iconPaperPlaneTag } from '@ni/nimble-components/dist/esm/icons/paper-plane'; -import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; -import { TextFieldAppearance } from '@ni/nimble-components/dist/esm/text-field/types'; -// import { themeProviderTag } from '@ni/nimble-components/dist/esm/theme-provider'; -// import { Theme } from '@ni/nimble-components/dist/esm/theme-provider/types'; -import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; - -import type { ChatInputToolbar } from '.'; - -/* eslint-disable @typescript-eslint/indent */ -// prettier-ignore -export const template = html<ChatInputToolbar>` - <ni-nimble-theme-provider theme='color'> - <${toolbarTag}> - <slot name="start"></slot> - <${textFieldTag} - placeholder='How can I assist you today?' - appearance=${TextFieldAppearance.block} - @keyup="${(x, c) => x.onTextFieldKeyUp(c.event as KeyboardEvent)}" - ${ref('textField')} - > - <${buttonTag} - appearance='${ButtonAppearance.ghost}' - content-hidden - slot='start' - > - Prompt - <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> - </${buttonTag}> - <${buttonTag} - appearance='${ButtonAppearance.ghost}' - content-hidden - slot='actions' - @click="${x => x.submitMessage()}" - > - Submit - <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> - </${buttonTag}> - </${textFieldTag}> - <slot name="end"></slot> - </${toolbarTag}> - </ni-nimble-theme-provider> -`; -/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts b/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts deleted file mode 100644 index 2c72249181..0000000000 --- a/packages/spright-components/src/chat/input-toolbar/tests/chat-input-toolbar.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { html } from '@microsoft/fast-element'; -import { ChatInputToolbar, chatInputToolbarTag } from '..'; -import { fixture, type Fixture } from '../../../utilities/tests/fixture'; - -async function setup(): Promise<Fixture<ChatInputToolbar>> { - return await fixture<ChatInputToolbar>( - html`<${chatInputToolbarTag}></${chatInputToolbarTag}>` - ); -} - -describe('ChatInputToolbar', () => { - let element: ChatInputToolbar; - let connect: () => Promise<void>; - let disconnect: () => Promise<void>; - - beforeEach(async () => { - ({ element, connect, disconnect } = await setup()); - }); - - afterEach(async () => { - await disconnect(); - }); - - it('can construct an element instance', () => { - expect(document.createElement(chatInputToolbarTag)).toBeInstanceOf(ChatInputToolbar); - }); - - it('should have a slot element in the shadow DOM', async () => { - await connect(); - expect( - (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName - ).toBe('SLOT'); - }); -}); diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index e79ee007d4..cadc0bc6b9 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -10,11 +10,3 @@ export const ChatMessageStatus = { export type ChatMessageStatus = (typeof ChatMessageStatus)[keyof typeof ChatMessageStatus]; - -/** - * The type of the detail associated with the `submit` - * event on the input toolbar. - */ -export interface ChatInputToolbarSubmitMessageEventDetail { - message: string; -} \ No newline at end of file diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index da90aba236..50941d72fd 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -2,7 +2,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as chatStories from './chat.stories'; import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; -import { chatInputToolbarTag } from '../../../../spright-components/src/chat/input-toolbar'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; <Meta of={chatStories} /> @@ -21,13 +20,6 @@ representing an entire conversation or chat window. <ComponentApisLink /> -### Chat input toolbar - -Use the <Tag name={chatInputToolbarTag} /> element to collect user input for a chat conversation. - -<Canvas of={chatStories.chatInputToolbar} /> -<Controls of={chatStories.chatInputToolbar} /> - ### Chat conversation Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 3f18cd886a..c4bc552fc7 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,8 +1,15 @@ import type { Meta, StoryObj } from '@storybook/html'; -import { html, ref } from '@microsoft/fast-element'; +import { html } from '@microsoft/fast-element'; import { buttonTag } from '../../../../nimble-components/src/button'; +import { ButtonAppearance } from '../../../../nimble-components/src/button/types'; +import { textFieldTag } from '../../../../nimble-components/src/text-field'; +import { TextFieldAppearance } from '../../../../nimble-components/src/text-field/types'; +import { themeProviderTag } from '../../../../nimble-components/src/theme-provider'; +import { Theme } from '../../../../nimble-components/src/theme-provider/types'; +import { toolbarTag } from '../../../../nimble-components/src/toolbar'; +import { iconLightbulbTag } from '../../../../nimble-components/src/icons/lightbulb'; +import { iconPaperPlaneTag } from '../../../../nimble-components/src/icons/paper-plane'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; -import { chatInputToolbarTag } from '../../../../spright-components/src/chat/input-toolbar'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; @@ -17,10 +24,6 @@ const metadata: Meta<ChatMessageTextArgs> = { }; interface ChatWindow { - inputToolbarRef: ChatInputToolbar; - submitChatMessage: ( - inputToolbarRef: ChatInputToolbar, - ) => void; } const markdownExample = `To configure your Python version: @@ -59,26 +62,40 @@ export const chatWindow: StoryObj<ChatWindow> = { <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> </${chatMessageTag}> </${chatConversationTag}> - <${chatInputToolbarTag} - ${ref('inputToolbarRef')} - @submit="${x => x.submitChatMessage(x.inputToolbarRef)}" - > - </${chatInputToolbarTag}>`), + <${themeProviderTag} theme='${Theme.color}'> + <${toolbarTag} style="width: 100%;"> + <slot name="start"></slot> + <${textFieldTag} + placeholder='How can I assist you today?' + appearance=${TextFieldAppearance.block} + style="width: 100%;" + > + <${buttonTag} + appearance='${ButtonAppearance.ghost}' + content-hidden + slot='start' + > + Prompt + <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> + </${buttonTag}> + <${buttonTag} + appearance='${ButtonAppearance.ghost}' + content-hidden + slot='actions' + > + Submit + <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> + </${buttonTag}> + </${textFieldTag}> + <slot name="end"></slot> + </${toolbarTag}> + </${themeProviderTag}>`), argTypes: { submitChatMessage: { table: { disable: true } } - }, - args: { - submitChatMessage: (inputToolbarRef) => { - const chatMessage = document.createElement(chatMessageTag); - chatMessage.textContent = 'this is a test'; - - const chatConversationElement = document.querySelector(chatConversationTag)!; - chatConversationElement.appendChild(chatMessage); - } } }; @@ -256,22 +273,3 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { prompt2: 'Help me with my childhood trauma' } }; - -interface ChatInputToolbar { -} - -export const chatInputToolbar: StoryObj<ChatInputToolbar> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatInputToolbarTag}> - </${chatInputToolbarTag}> - `), - argTypes: { - - }, - args: { - - } -}; \ No newline at end of file From cc8a9b28d36d8f878bafadb92111ccf7ad88a8b1 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Thu, 30 Jan 2025 16:53:00 -0600 Subject: [PATCH 30/61] Productize ChatConversation and ChatMessage elements I productized the Spright ChatConversion and ChatMessage elements Jesse prototyped. --- .../spright-components/src/all-components.ts | 2 + .../src/chat/conversation/index.ts | 4 +- .../src/chat/conversation/template.ts | 4 +- .../tests/chat-conversation.spec.ts | 4 +- .../src/chat/message/index.ts | 10 +- .../src/chat/message/styles.ts | 8 +- .../chat/message/tests/chat-message.spec.ts | 12 +- packages/spright-components/src/chat/types.ts | 12 +- .../src/chat/window/index.ts | 25 --- .../src/chat/window/styles.ts | 15 -- .../src/chat/window/template.ts | 33 ---- .../src/chat/window/tests/chat-window.spec.ts | 34 ---- .../chat/chat-message-matrix.stories.ts | 43 ++---- packages/storybook/src/spright/chat/chat.mdx | 2 - .../src/spright/chat/chat.stories.ts | 145 ++++-------------- specs/chat-components/README.md | 43 +----- 16 files changed, 82 insertions(+), 314 deletions(-) delete mode 100644 packages/spright-components/src/chat/window/index.ts delete mode 100644 packages/spright-components/src/chat/window/styles.ts delete mode 100644 packages/spright-components/src/chat/window/template.ts delete mode 100644 packages/spright-components/src/chat/window/tests/chat-window.spec.ts diff --git a/packages/spright-components/src/all-components.ts b/packages/spright-components/src/all-components.ts index 888b09c6cd..2ed36d88e2 100644 --- a/packages/spright-components/src/all-components.ts +++ b/packages/spright-components/src/all-components.ts @@ -6,4 +6,6 @@ import '@ni/nimble-components/dist/esm/all-components'; +import './chat/conversation'; +import './chat/message'; import './rectangle'; diff --git a/packages/spright-components/src/chat/conversation/index.ts b/packages/spright-components/src/chat/conversation/index.ts index eea28345d2..6b5f4c080c 100644 --- a/packages/spright-components/src/chat/conversation/index.ts +++ b/packages/spright-components/src/chat/conversation/index.ts @@ -11,9 +11,7 @@ declare global { /** * A Spright component for displaying a series of chat messages */ -export class ChatConversation extends FoundationElement { - -} +export class ChatConversation extends FoundationElement {} const sprightChatConversation = ChatConversation.compose({ baseName: 'chat-conversation', diff --git a/packages/spright-components/src/chat/conversation/template.ts b/packages/spright-components/src/chat/conversation/template.ts index 3867b2710d..0c74fc268b 100644 --- a/packages/spright-components/src/chat/conversation/template.ts +++ b/packages/spright-components/src/chat/conversation/template.ts @@ -3,7 +3,5 @@ import type { ChatConversation } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore -export const template = html<ChatConversation>` - <slot></slot> -`; +export const template = html<ChatConversation>`<slot></slot>`; /* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts index f9869cb59b..e7ad070f57 100644 --- a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts +++ b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts @@ -28,7 +28,7 @@ describe('ChatConversation', () => { it('should have a slot element in the shadow DOM', async () => { await connect(); expect( - (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName - ).toBe('SLOT'); + (element.shadowRoot?.querySelector('SLOT')) + ).not.toBeNull(); }); }); diff --git a/packages/spright-components/src/chat/message/index.ts b/packages/spright-components/src/chat/message/index.ts index d031918dd4..0645dcad5b 100644 --- a/packages/spright-components/src/chat/message/index.ts +++ b/packages/spright-components/src/chat/message/index.ts @@ -2,7 +2,7 @@ import { attr } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import { ChatMessageStatus } from '../types'; +import { ChatMessageType } from '../types'; declare global { interface HTMLElementTagNameMap { @@ -16,12 +16,12 @@ declare global { export class ChatMessage extends FoundationElement { /** * @public - * The status of this message in the chat conversation + * The message type of this message in the chat conversation * @remarks - * HTML Attribute: status + * HTML Attribute: message-type */ - @attr - public readonly status: ChatMessageStatus = ChatMessageStatus.outgoing; + @attr({ attribute: 'message-type' }) + public readonly messageType: ChatMessageType = ChatMessageType.outbound; } const sprightChatMessage = ChatMessage.compose({ diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 56e9052ef2..85f9c26540 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -21,11 +21,11 @@ export const styles = css` flex-shrink: 0; } - :host([status='outgoing']) { + :host([message-type='outbound']) { justify-content: flex-end; } - :host([status='incoming']) { + :host([message-type='inbound']) { justify-content: flex-start; } @@ -38,13 +38,13 @@ export const styles = css` color: ${bodyFontColor}; } - :host([status='outgoing']) div { + :host([message-type='outbound']) div { background: ${fillSelectedColor}; border: ${borderWidth} solid ${borderHoverColor}; border-radius: 8px 8px 0px 8px; } - :host([status='incoming']) div { + :host([message-type='inbound']) div { border-radius: 8px 8px 8px 0px; } `; diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index 02749a951b..a5d0150ec9 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -1,10 +1,11 @@ import { html } from '@microsoft/fast-element'; import { ChatMessage, chatMessageTag } from '..'; import { fixture, type Fixture } from '../../../utilities/tests/fixture'; +import { ChatMessageType } from '../../types'; async function setup(): Promise<Fixture<ChatMessage>> { return await fixture<ChatMessage>( - html`<${chatMessageTag}></${chatMessageTag}>` + html`<${chatMessageTag}>Some message</${chatMessageTag}>` ); } @@ -28,7 +29,12 @@ describe('ChatMessage', () => { it('should have a slot element in the shadow DOM', async () => { await connect(); expect( - (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName - ).toBe('SLOT'); + (element.shadowRoot?.querySelector('SLOT')) + ).not.toBeNull(); + }); + + it("should initialize 'message-type' to default", async () => { + await connect(); + expect(element.messageType).toBe(ChatMessageType.outbound); }); }); diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index cadc0bc6b9..8f22fba5e1 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -1,12 +1,12 @@ /** - * A message status in a chat conversation. + * A message type in a chat conversation. * @public */ -export const ChatMessageStatus = { - outgoing: 'outgoing', - incoming: 'incoming', +export const ChatMessageType = { + outbound: 'outbound', + inbound: 'inbound', system: 'system', } as const; -export type ChatMessageStatus = - (typeof ChatMessageStatus)[keyof typeof ChatMessageStatus]; +export type ChatMessageType = + (typeof ChatMessageType)[keyof typeof ChatMessageType]; diff --git a/packages/spright-components/src/chat/window/index.ts b/packages/spright-components/src/chat/window/index.ts deleted file mode 100644 index 3cf5162780..0000000000 --- a/packages/spright-components/src/chat/window/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; -import { styles } from './styles'; -import { template } from './template'; - -declare global { - interface HTMLElementTagNameMap { - 'spright-chat-window': ChatWindow; - } -} - -/** - * A Spright component for displaying a chat window - */ -export class ChatWindow extends FoundationElement { - -} - -const sprightChatWindow = ChatWindow.compose({ - baseName: 'chat-window', - template, - styles -}); - -DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatWindow()); -export const chatWindowTag = 'spright-chat-window'; diff --git a/packages/spright-components/src/chat/window/styles.ts b/packages/spright-components/src/chat/window/styles.ts deleted file mode 100644 index 1ff4a17533..0000000000 --- a/packages/spright-components/src/chat/window/styles.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { css } from '@microsoft/fast-element'; -import { textFieldTag } from '@ni/nimble-components/dist/esm/text-field'; -import { display } from '../../utilities/style/display'; - -export const styles = css` - ${display('flex')} - - :host { - flex-direction: column; - } - - ${textFieldTag} { - flex-grow: 1; - } -`; diff --git a/packages/spright-components/src/chat/window/template.ts b/packages/spright-components/src/chat/window/template.ts deleted file mode 100644 index dc49c5d5e3..0000000000 --- a/packages/spright-components/src/chat/window/template.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { html } from '@microsoft/fast-element'; -import { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; -import { buttonTag } from '@ni/nimble-components/dist/esm/button'; -import { iconBarsTag } from '@ni/nimble-components/dist/esm/icons/bars'; -import { iconDownloadTag } from '@ni/nimble-components/dist/esm/icons/download'; -import { iconShareNodesTag } from '@ni/nimble-components/dist/esm/icons/share-nodes'; -import { toolbarTag } from '@ni/nimble-components/dist/esm/toolbar'; - -import type { ChatWindow } from '.'; -import { chatConversationTag } from '../conversation'; - -/* eslint-disable @typescript-eslint/indent */ -// prettier-ignore -export const template = html<ChatWindow>` - <${toolbarTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> - Download - <${iconDownloadTag} slot='start'></${iconDownloadTag}> - </${buttonTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> - Share - <${iconShareNodesTag} slot='start'></${iconShareNodesTag}> - </${buttonTag}> - <${buttonTag} appearance='${ButtonAppearance.ghost}' content-hidden slot='end'> - Menu - <${iconBarsTag} slot='start'></${iconBarsTag}> - </${buttonTag}> - </${toolbarTag}> - <${chatConversationTag}> - <slot></slot> - </${chatConversationTag}> -`; -/* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/window/tests/chat-window.spec.ts b/packages/spright-components/src/chat/window/tests/chat-window.spec.ts deleted file mode 100644 index a72dc30acc..0000000000 --- a/packages/spright-components/src/chat/window/tests/chat-window.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { html } from '@microsoft/fast-element'; -import { ChatWindow, chatWindowTag } from '..'; -import { fixture, type Fixture } from '../../../utilities/tests/fixture'; - -async function setup(): Promise<Fixture<ChatWindow>> { - return await fixture<ChatWindow>( - html`<${chatWindowTag}></${chatWindowTag}>` - ); -} - -describe('ChatWindow', () => { - let element: ChatWindow; - let connect: () => Promise<void>; - let disconnect: () => Promise<void>; - - beforeEach(async () => { - ({ element, connect, disconnect } = await setup()); - }); - - afterEach(async () => { - await disconnect(); - }); - - it('can construct an element instance', () => { - expect(document.createElement(chatWindowTag)).toBeInstanceOf(ChatWindow); - }); - - it('should have a slot element in the shadow DOM', async () => { - await connect(); - expect( - (element.shadowRoot?.childNodes.item(0) as HTMLElement).tagName - ).toBe('SLOT'); - }); -}); diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index b413d625c4..e2ceed2917 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -1,20 +1,21 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; +import { ChatMessageType } from '../../../../spright-components/src/chat/types'; import { createMatrix, sharedMatrixParameters, - createMatrixThemeStory, - cartesianProduct, - createMatrixInteractionsFromStates + createMatrixThemeStory } from '../../utilities/matrix'; import { createStory } from '../../utilities/storybook'; import { hiddenWrapper } from '../../utilities/hidden'; -import { - disabledStates, - type DisabledState, - disabledStateIsEnabled -} from '../../utilities/states'; + +const chatMessageTypes = [ + ['outbound', ChatMessageType.outbound], + ['inbound', ChatMessageType.inbound], + ['system', ChatMessageType.system] +] as const; +type ChatMessageTypeState = (typeof chatMessageTypes)[number]; const metadata: Meta = { title: 'Tests Spright/Chat Message', @@ -25,31 +26,17 @@ const metadata: Meta = { export default metadata; -const component = ([ - disabledName, - disabled -]: DisabledState): ViewTemplate => html` +const component = ( + [chatMessageTypeName, messageType]: ChatMessageTypeState, +): ViewTemplate => html` <${chatMessageTag} - ?disabled=${() => disabled} + message-type=${() => messageType} style="margin-right: 8px;"> - ${() => `${disabledName} Chat Message`}</${chatMessageTag}> + ${() => `${chatMessageTypeName} Chat Message`}</${chatMessageTag}> `; export const chatMessageThemeMatrix: StoryFn = createMatrixThemeStory( - createMatrix(component, [disabledStates]) -); - -const interactionStatesHover = cartesianProduct([disabledStates] as const); - -const interactionStates = cartesianProduct([[disabledStateIsEnabled]] as const); - -export const chatMessageInteractionsThemeMatrix: StoryFn = createMatrixThemeStory( - createMatrixInteractionsFromStates(component, { - hover: interactionStatesHover, - hoverActive: interactionStates, - active: interactionStates, - focus: interactionStates - }) + createMatrix(component, [chatMessageTypes]) ); export const hiddenChatMessage: StoryFn = createStory( diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 50941d72fd..b16245b197 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -14,8 +14,6 @@ for connecting them to a source of data. Components include low level chat messages and input fields and higher level composite components representing an entire conversation or chat window. -<Canvas of={chatStories.chatWindow} /> - ## API <ComponentApisLink /> diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index c4bc552fc7..7eaef256a4 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,17 +1,9 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; import { buttonTag } from '../../../../nimble-components/src/button'; -import { ButtonAppearance } from '../../../../nimble-components/src/button/types'; -import { textFieldTag } from '../../../../nimble-components/src/text-field'; -import { TextFieldAppearance } from '../../../../nimble-components/src/text-field/types'; -import { themeProviderTag } from '../../../../nimble-components/src/theme-provider'; -import { Theme } from '../../../../nimble-components/src/theme-provider/types'; -import { toolbarTag } from '../../../../nimble-components/src/toolbar'; -import { iconLightbulbTag } from '../../../../nimble-components/src/icons/lightbulb'; -import { iconPaperPlaneTag } from '../../../../nimble-components/src/icons/paper-plane'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; -import { ChatMessageStatus } from '../../../../spright-components/src/chat/types'; +import { ChatMessageType as ChatMessageType } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { @@ -23,9 +15,6 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; -interface ChatWindow { -} - const markdownExample = `To configure your Python version: 1. Select **Adapters...** from the **Configure** menu. @@ -36,69 +25,6 @@ const markdownExample = `To configure your Python version: You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; -export const chatWindow: StoryObj<ChatWindow> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatConversationTag}> - <${chatMessageTag} status='outgoing'> - Hi, can you please help me? - </${chatMessageTag}> - <${chatMessageTag} status='incoming'> - Yeah sure, what do you need help with? - </${chatMessageTag}> - <${chatMessageTag} status='outgoing'> - Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. - </${chatMessageTag}> - <${chatMessageTag} status='incoming'> - <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> - </${chatMessageTag}> - <${chatMessageTag} status='system'> - <${spinnerTag} appearance='accent'></${spinnerTag}> - </${chatMessageTag}> - <${chatMessageTag} status='system'> - <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> - <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> - </${chatMessageTag}> - </${chatConversationTag}> - <${themeProviderTag} theme='${Theme.color}'> - <${toolbarTag} style="width: 100%;"> - <slot name="start"></slot> - <${textFieldTag} - placeholder='How can I assist you today?' - appearance=${TextFieldAppearance.block} - style="width: 100%;" - > - <${buttonTag} - appearance='${ButtonAppearance.ghost}' - content-hidden - slot='start' - > - Prompt - <${iconLightbulbTag} slot='start'></${iconLightbulbTag}> - </${buttonTag}> - <${buttonTag} - appearance='${ButtonAppearance.ghost}' - content-hidden - slot='actions' - > - Submit - <${iconPaperPlaneTag} slot='start'></${iconPaperPlaneTag}> - </${buttonTag}> - </${textFieldTag}> - <slot name="end"></slot> - </${toolbarTag}> - </${themeProviderTag}>`), - argTypes: { - submitChatMessage: { - table: { - disable: true - } - } - } -}; - interface ChatConversation { } export const chatConversation: StoryObj<ChatConversation> = { @@ -107,48 +33,35 @@ export const chatConversation: StoryObj<ChatConversation> = { }, render: createUserSelectedThemeStory(html` <${chatConversationTag}> - <${chatMessageTag} status='outgoing'> + <${chatMessageTag}> + Using default message-type attribute which is outbound. + </${chatMessageTag}> + <${chatMessageTag} message-type='outbound'> Hi, can you please help me? </${chatMessageTag}> - <${chatMessageTag} status='incoming'> + <${chatMessageTag} message-type='inbound'> Yeah sure, what do you need help with? </${chatMessageTag}> - <${chatMessageTag} status='outgoing'> + <${chatMessageTag} message-type='outbound'> Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. </${chatMessageTag}> - <${chatMessageTag} status='incoming'> + <${chatMessageTag} message-type='inbound'> <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> </${chatMessageTag}> - <${chatMessageTag} status='system'> + <${chatMessageTag} message-type='system'> <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> - <${chatMessageTag} status='system'> + <${chatMessageTag} message-type='system'> <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> </${chatMessageTag}> </${chatConversationTag}> - `), - argTypes: { - text: { - description: 'The text to display in the chat message.', - table: { category: apiCategory.slots } - }, - status: { - options: Object.keys(ChatMessageStatus), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - text: 'How do I choose which version of Python to execute my script?', - status: ChatMessageStatus.outgoing - } + `) }; interface ChatMessageArgs { - status: ChatMessageStatus; + messageType: ChatMessageType; } export default metadata; @@ -162,7 +75,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} status=${x => x.status}> + <${chatMessageTag} message-type=${x => x.messageType}> ${x => x.text} </${chatMessageTag}> `), @@ -171,8 +84,8 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { description: 'The text to display in the chat message.', table: { category: apiCategory.slots } }, - status: { - options: Object.keys(ChatMessageStatus), + messageType: { + options: Object.keys(ChatMessageType), control: { type: 'radio' }, description: 'The status of the chat message.', table: { category: apiCategory.attributes } @@ -180,7 +93,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { }, args: { text: 'How do I choose which version of Python to execute my script?', - status: ChatMessageStatus.outgoing + messageType: ChatMessageType.outbound } }; @@ -192,7 +105,7 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} status=${x => x.status}> + <${chatMessageTag} message-type=${x => x.messageType}> <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> </${chatMessageTag}> `), @@ -201,8 +114,8 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { description: 'Markdown text for the rich text viewer', table: { category: apiCategory.slots } }, - status: { - options: Object.keys(ChatMessageStatus), + messageType: { + options: Object.keys(ChatMessageType), control: { type: 'radio' }, description: 'The status of the chat message.', table: { category: apiCategory.attributes } @@ -210,7 +123,7 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { }, args: { markdown: markdownExample, - status: ChatMessageStatus.outgoing + messageType: ChatMessageType.outbound } }; @@ -219,20 +132,20 @@ export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} status=${x => x.status}> + <${chatMessageTag} message-type=${x => x.messageType}> <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> `), argTypes: { - status: { - options: Object.keys(ChatMessageStatus), + messageType: { + options: Object.keys(ChatMessageType), control: { type: 'radio' }, description: 'The status of the chat message.', table: { category: apiCategory.attributes } } }, args: { - status: ChatMessageStatus.system + messageType: ChatMessageType.system } }; @@ -245,14 +158,14 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { actions: {} }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} status=${x => x.status}> + <${chatMessageTag} message-type=${x => x.messageType}> <${buttonTag} appearance='block'>${x => x.prompt1}</${buttonTag}> <${buttonTag} appearance='block'>${x => x.prompt2}</${buttonTag}> </${chatMessageTag}> `), argTypes: { - status: { - options: Object.keys(ChatMessageStatus), + messageType: { + options: Object.keys(ChatMessageType), control: { type: 'radio' }, description: 'The status of the chat message.', table: { category: apiCategory.attributes } @@ -268,8 +181,8 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { }, args: { - status: ChatMessageStatus.system, + messageType: ChatMessageType.system, prompt1: 'Explain how to do my job', - prompt2: 'Help me with my childhood trauma' + prompt2: 'What is the meaning of life?' } }; diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md index cd5cfffe24..680736c9f0 100644 --- a/specs/chat-components/README.md +++ b/specs/chat-components/README.md @@ -9,7 +9,7 @@ spright-chat-message - draws outline/bg, sizes its content styled HTML ChatMessageSource = -'me' | 'them' | 'system' +'me' | 'them' | 'system' 'sent' | 'received' | 'status' 'outgoing' | 'incoming' | 'status' 'right' | 'left' | 'center' @@ -25,41 +25,14 @@ spright-chat-conversation - lays out text bubbles, rich text bubbles, prompt but Slots child order determine layout -spright-chat-toolbar - top toolbar with buttons - -spright-chat-input-toolbar - bottom toolbar with buttons, text input - Props/Attrs - add-chat-button-disabled - add-chat-button-disabled - text-prompt-button-hidden - text-prompt-button-hidden - text-input-field-disabled - text-input-field-hidden - text-input-field-placeholder - text-input-button-disabled - text-input-button-hidden - attach-button-disabled - attach-button-hidden - Events - text-input-change - text-input-button-click - -spright-chat-window - lays out conversation and toolbar. Probably no logic - Slots - default slot for toolbar, conversation, bottom toolbar? - - - Notes: - - remove "AI", "bot", "user" - - appearance (or variant) for color and position, remove "actor" - - bubble is responsible for layout, conversation just does vertical layout - - single chat bubble, slot in content, use rich text viewer for MD if needed - - rich text viewer would need more features for links, images - - research a11y patterns for chat widgets - - mention plugins for links - - - +- remove "AI", "bot", "user" +- appearance (or variant) for color and position, remove "actor" +- bubble is responsible for layout, conversation just does vertical layout +- single chat bubble, slot in content, use rich text viewer for MD if needed +- rich text viewer would need more features for links, images +- research a11y patterns for chat widgets +- mention plugins for links Other examples https://daisyui.com/components/chat/ From 5809c064c9ef24cdcda55de83702a85acc6e22d1 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Thu, 30 Jan 2025 16:59:13 -0600 Subject: [PATCH 31/61] Delete README.md Deleted obsolete file --- specs/chat-components/README.md | 40 --------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 specs/chat-components/README.md diff --git a/specs/chat-components/README.md b/specs/chat-components/README.md deleted file mode 100644 index 680736c9f0..0000000000 --- a/specs/chat-components/README.md +++ /dev/null @@ -1,40 +0,0 @@ -spright-chat-message - draws outline/bg, sizes its content - Props/Attrs - source: ChatMessageSource - controls corner rounding. - timestamp: date string? (not yet, might belong to conversation) - Slots - any content: - plain text, including new lines - rich text viewer populated via markdown - styled HTML - -ChatMessageSource = -'me' | 'them' | 'system' -'sent' | 'received' | 'status' -'outgoing' | 'incoming' | 'status' -'right' | 'left' | 'center' -'this-user' | 'other-user' | 'system' - -appearance='ghost' | 'block' and location = 'start' | 'end' | 'middle' - -spright-chat-load-more-button - button at top or bottom of conversation to "virtualize" - -spright-chat-conversation - lays out text bubbles, rich text bubbles, prompt buttons, spinner vertically with 100% width - Props/Attrs - order = newest-top or newest-bottom (or use DOM order?) - Slots - child order determine layout - -Notes: -- remove "AI", "bot", "user" -- appearance (or variant) for color and position, remove "actor" -- bubble is responsible for layout, conversation just does vertical layout -- single chat bubble, slot in content, use rich text viewer for MD if needed -- rich text viewer would need more features for links, images -- research a11y patterns for chat widgets -- mention plugins for links - - Other examples - https://daisyui.com/components/chat/ - https://www.telerik.com/design-system/docs/components/chat/ - https://carbondesignsystem.com/community/patterns/chatbot/usage/ From 1e5b67aaa317eed8b77fa9e591f2762726da4a3f Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Thu, 30 Jan 2025 17:06:02 -0600 Subject: [PATCH 32/61] Small tweaks Made some small tweaks to the storybook --- packages/storybook/src/spright/chat/chat.mdx | 2 +- packages/storybook/src/spright/chat/chat.stories.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index b16245b197..c6de9ea9e6 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -12,7 +12,7 @@ The components can collect user input and display responses; the application is for connecting them to a source of data. Components include low level chat messages and input fields and higher level composite components -representing an entire conversation or chat window. +representing an entire conversation. ## API diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 7eaef256a4..cb85f10a9f 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -33,9 +33,6 @@ export const chatConversation: StoryObj<ChatConversation> = { }, render: createUserSelectedThemeStory(html` <${chatConversationTag}> - <${chatMessageTag}> - Using default message-type attribute which is outbound. - </${chatMessageTag}> <${chatMessageTag} message-type='outbound'> Hi, can you please help me? </${chatMessageTag}> From 0f6ab82aec12e3dba91447e655eac49e15856325 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 31 Jan 2025 09:39:01 -0600 Subject: [PATCH 33/61] Update chat.stories.ts Fixed lint error --- packages/storybook/src/spright/chat/chat.stories.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index cb85f10a9f..aec160a831 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -3,7 +3,7 @@ import { html } from '@microsoft/fast-element'; import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; -import { ChatMessageType as ChatMessageType } from '../../../../spright-components/src/chat/types'; +import { ChatMessageType } from '../../../../spright-components/src/chat/types'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { @@ -25,8 +25,8 @@ const markdownExample = `To configure your Python version: You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; -interface ChatConversation { -} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface ChatConversation {} export const chatConversation: StoryObj<ChatConversation> = { parameters: { actions: {} From d3a10109af2f1c559057e7a242af402885962bd5 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 31 Jan 2025 15:27:30 -0600 Subject: [PATCH 34/61] Change files --- ...ht-components-6dcca5fc-0353-4ba2-b325-63565d42b95e.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@ni-spright-components-6dcca5fc-0353-4ba2-b325-63565d42b95e.json diff --git a/change/@ni-spright-components-6dcca5fc-0353-4ba2-b325-63565d42b95e.json b/change/@ni-spright-components-6dcca5fc-0353-4ba2-b325-63565d42b95e.json new file mode 100644 index 0000000000..7b3455ef12 --- /dev/null +++ b/change/@ni-spright-components-6dcca5fc-0353-4ba2-b325-63565d42b95e.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Productize ChatConversation and ChatMessage elements", + "packageName": "@ni/spright-components", + "email": "jose.a.hernandez@ni.com", + "dependentChangeType": "patch" +} From 4b9ca60b5ab461b0c5380dad6188988dfac09dcf Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 31 Jan 2025 15:31:40 -0600 Subject: [PATCH 35/61] Fix lint and beachball errors --- .../Examples/Demo.Client/packages.lock.json | 720 +++++++++--------- .../packages.lock.json | 678 ++++++++--------- .../src/chat/conversation/index.ts | 4 +- .../tests/chat-conversation.spec.ts | 8 +- .../src/chat/message/styles.ts | 2 +- .../chat/message/tests/chat-message.spec.ts | 8 +- packages/spright-components/src/chat/types.ts | 2 +- .../chat/chat-message-matrix.stories.ts | 7 +- packages/storybook/src/spright/chat/chat.mdx | 15 +- .../src/spright/chat/chat.stories.ts | 3 +- 10 files changed, 725 insertions(+), 722 deletions(-) diff --git a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json index bacf469850..14db397e06 100644 --- a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json @@ -1,361 +1,361 @@ -{ - "version": 1, - "dependencies": { - "net8.0": { - "Microsoft.AspNetCore.Components.WebAssembly": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "8.0.11", - "Microsoft.Extensions.Configuration.Binder": "8.0.2", - "Microsoft.Extensions.Configuration.Json": "8.0.1", - "Microsoft.Extensions.Logging": "8.0.1", - "Microsoft.JSInterop.WebAssembly": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.WebAssembly.DevServer": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "Yl6dGx9jd5ZkjRl6iJhguazv16qZio5KpVynL3YVfrFz3UM5g3ZvkaZkZ6bF9/z7hADf6qoX4CRRnSPwbFb20A==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.12, )", - "resolved": "8.0.12", - "contentHash": "FV4HnQ3JI15PHnJ5PGTbz+rYvrih42oLi/7UMIshNwCwUZhTq13UzrggtXk4ygrcMcN+4jsS6hhshx2p/Zd0ig==" - }, - "Microsoft.NET.Sdk.WebAssembly.Pack": { - "type": "Direct", - "requested": "[8.0.12, )", - "resolved": "8.0.12", - "contentHash": "JS5B7ZJVqaBOjlbjDgOkg+COEy24CB6IdGiwNeZnPJMoIZFdxehGFUmlxl4Mz3GZaoIduOtMtwkEdy6jh+NUpg==" - }, - "NI.CSharp.Analyzers": { - "type": "Direct", - "requested": "[2.0.28, )", - "resolved": "2.0.28", - "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "Microsoft.CodeAnalysis.CSharp": "4.2.0", - "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", - "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", - "Roslynator.Analyzers": "4.1.1", - "StyleCop.Analyzers": "1.2.0-beta.556" - } - }, - "Apache.Arrow": { - "type": "Transitive", - "resolved": "18.0.0", - "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" - }, - "Microsoft.AspNetCore.Authorization": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", - "dependencies": { - "Microsoft.AspNetCore.Metadata": "8.0.11", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.AspNetCore.Components": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", - "dependencies": { - "Microsoft.AspNetCore.Authorization": "8.0.11", - "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Analyzers": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" - }, - "Microsoft.AspNetCore.Components.Forms": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Web": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11", - "Microsoft.AspNetCore.Components.Forms": "8.0.11", - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Primitives": "8.0.0", - "Microsoft.JSInterop": "8.0.11", - "System.IO.Pipelines": "8.0.0" - } - }, - "Microsoft.AspNetCore.Metadata": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" - }, - "Microsoft.CodeAnalysis.Analyzers": { - "type": "Transitive", - "resolved": "3.3.3", - "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" - }, - "Microsoft.CodeAnalysis.Common": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "System.Collections.Immutable": "5.0.0", - "System.Memory": "4.5.4", - "System.Reflection.Metadata": "5.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.CodeAnalysis.CSharp": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", - "dependencies": { - "Microsoft.CodeAnalysis.Common": "[4.2.0]" - } - }, - "Microsoft.CodeAnalysis.NetAnalyzers": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.FileExtensions": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Json": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileProviders.Physical": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", - "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileSystemGlobbing": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" - }, - "Microsoft.JSInterop": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" - }, - "Microsoft.JSInterop.WebAssembly": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", - "dependencies": { - "Microsoft.JSInterop": "8.0.11" - } - }, - "Microsoft.VisualStudio.Threading.Analyzers": { - "type": "Transitive", - "resolved": "17.10.48", - "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" - }, - "Roslynator.Analyzers": { - "type": "Transitive", - "resolved": "4.1.1", - "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" - }, - "StyleCop.Analyzers": { - "type": "Transitive", - "resolved": "1.2.0-beta.556", - "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", - "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.556" - } - }, - "StyleCop.Analyzers.Unstable": { - "type": "Transitive", - "resolved": "1.2.0.556", - "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" - }, - "demo.shared": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )", - "NI.CSharp.Analyzers": "[2.0.28, )", - "NimbleBlazor": "[1.0.0, )", - "SprightBlazor": "[1.0.0, )" - } - }, - "nimbleblazor": { - "type": "Project", - "dependencies": { - "Apache.Arrow": "[18.0.0, 18.0.0]", - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - }, - "sprightblazor": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - } - }, - "net8.0/browser-wasm": { - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - } - } +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.11", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.JSInterop.WebAssembly": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.WebAssembly.DevServer": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "Yl6dGx9jd5ZkjRl6iJhguazv16qZio5KpVynL3YVfrFz3UM5g3ZvkaZkZ6bF9/z7hADf6qoX4CRRnSPwbFb20A==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "zk5lnZrYJgtuJG8L4v17Ej8rZ3PUcR2iweNV08BaO5LbYHIi2wNaVNcJoLxvqgQdnjLlKnCCfVGLDr6QHeAarQ==" + }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "type": "Direct", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "Ch6dilt/TAo3XryG/9LF8Zy4rAT+2HYnks8thWAeNzPNOJs4aSyC6E5yxuBiN49d2eES78h1mSR/KNyOfbptXQ==" + }, + "NI.CSharp.Analyzers": { + "type": "Direct", + "requested": "[2.0.28, )", + "resolved": "2.0.28", + "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "Microsoft.CodeAnalysis.CSharp": "4.2.0", + "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", + "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", + "Roslynator.Analyzers": "4.1.1", + "StyleCop.Analyzers": "1.2.0-beta.556" + } + }, + "Apache.Arrow": { + "type": "Transitive", + "resolved": "18.0.0", + "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.11", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.11", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11", + "Microsoft.AspNetCore.Components.Forms": "8.0.11", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.11", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.2.0]" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", + "dependencies": { + "Microsoft.JSInterop": "8.0.11" + } + }, + "Microsoft.VisualStudio.Threading.Analyzers": { + "type": "Transitive", + "resolved": "17.10.48", + "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" + }, + "Roslynator.Analyzers": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" + }, + "StyleCop.Analyzers": { + "type": "Transitive", + "resolved": "1.2.0-beta.556", + "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.556" + } + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.556", + "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "demo.shared": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )", + "NI.CSharp.Analyzers": "[2.0.28, )", + "NimbleBlazor": "[1.0.0, )", + "SprightBlazor": "[1.0.0, )" + } + }, + "nimbleblazor": { + "type": "Project", + "dependencies": { + "Apache.Arrow": "[18.0.0, 18.0.0]", + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + } + }, + "net8.0/browser-wasm": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + } + } + } } \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json index 61b6676669..0bf72d4c3e 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json @@ -1,340 +1,340 @@ -{ - "version": 1, - "dependencies": { - "net8.0": { - "Microsoft.AspNetCore.Components.WebAssembly": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "8.0.11", - "Microsoft.Extensions.Configuration.Binder": "8.0.2", - "Microsoft.Extensions.Configuration.Json": "8.0.1", - "Microsoft.Extensions.Logging": "8.0.1", - "Microsoft.JSInterop.WebAssembly": "8.0.11" - } - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.12, )", - "resolved": "8.0.12", - "contentHash": "FV4HnQ3JI15PHnJ5PGTbz+rYvrih42oLi/7UMIshNwCwUZhTq13UzrggtXk4ygrcMcN+4jsS6hhshx2p/Zd0ig==" - }, - "Microsoft.NET.Sdk.WebAssembly.Pack": { - "type": "Direct", - "requested": "[8.0.12, )", - "resolved": "8.0.12", - "contentHash": "JS5B7ZJVqaBOjlbjDgOkg+COEy24CB6IdGiwNeZnPJMoIZFdxehGFUmlxl4Mz3GZaoIduOtMtwkEdy6jh+NUpg==" - }, - "NI.CSharp.Analyzers": { - "type": "Direct", - "requested": "[2.0.28, )", - "resolved": "2.0.28", - "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "Microsoft.CodeAnalysis.CSharp": "4.2.0", - "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", - "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", - "Roslynator.Analyzers": "4.1.1", - "StyleCop.Analyzers": "1.2.0-beta.556" - } - }, - "Apache.Arrow": { - "type": "Transitive", - "resolved": "18.0.0", - "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" - }, - "Microsoft.AspNetCore.Authorization": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", - "dependencies": { - "Microsoft.AspNetCore.Metadata": "8.0.11", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.AspNetCore.Components": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", - "dependencies": { - "Microsoft.AspNetCore.Authorization": "8.0.11", - "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Analyzers": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" - }, - "Microsoft.AspNetCore.Components.Forms": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Web": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11", - "Microsoft.AspNetCore.Components.Forms": "8.0.11", - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Primitives": "8.0.0", - "Microsoft.JSInterop": "8.0.11", - "System.IO.Pipelines": "8.0.0" - } - }, - "Microsoft.AspNetCore.Metadata": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" - }, - "Microsoft.CodeAnalysis.Analyzers": { - "type": "Transitive", - "resolved": "3.3.3", - "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" - }, - "Microsoft.CodeAnalysis.Common": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "System.Collections.Immutable": "5.0.0", - "System.Memory": "4.5.4", - "System.Reflection.Metadata": "5.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.CodeAnalysis.CSharp": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", - "dependencies": { - "Microsoft.CodeAnalysis.Common": "[4.2.0]" - } - }, - "Microsoft.CodeAnalysis.NetAnalyzers": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.FileExtensions": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Json": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileProviders.Physical": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", - "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileSystemGlobbing": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" - }, - "Microsoft.JSInterop": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" - }, - "Microsoft.JSInterop.WebAssembly": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", - "dependencies": { - "Microsoft.JSInterop": "8.0.11" - } - }, - "Microsoft.VisualStudio.Threading.Analyzers": { - "type": "Transitive", - "resolved": "17.10.48", - "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" - }, - "Roslynator.Analyzers": { - "type": "Transitive", - "resolved": "4.1.1", - "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" - }, - "StyleCop.Analyzers": { - "type": "Transitive", - "resolved": "1.2.0-beta.556", - "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", - "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.556" - } - }, - "StyleCop.Analyzers.Unstable": { - "type": "Transitive", - "resolved": "1.2.0.556", - "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" - }, - "nimbleblazor": { - "type": "Project", - "dependencies": { - "Apache.Arrow": "[18.0.0, 18.0.0]", - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - } - }, - "net8.0/browser-wasm": { - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - } - } +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.11", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.JSInterop.WebAssembly": "8.0.11" + } + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "zk5lnZrYJgtuJG8L4v17Ej8rZ3PUcR2iweNV08BaO5LbYHIi2wNaVNcJoLxvqgQdnjLlKnCCfVGLDr6QHeAarQ==" + }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "type": "Direct", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "Ch6dilt/TAo3XryG/9LF8Zy4rAT+2HYnks8thWAeNzPNOJs4aSyC6E5yxuBiN49d2eES78h1mSR/KNyOfbptXQ==" + }, + "NI.CSharp.Analyzers": { + "type": "Direct", + "requested": "[2.0.28, )", + "resolved": "2.0.28", + "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "Microsoft.CodeAnalysis.CSharp": "4.2.0", + "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", + "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", + "Roslynator.Analyzers": "4.1.1", + "StyleCop.Analyzers": "1.2.0-beta.556" + } + }, + "Apache.Arrow": { + "type": "Transitive", + "resolved": "18.0.0", + "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.11", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.11", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11", + "Microsoft.AspNetCore.Components.Forms": "8.0.11", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.11", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.2.0]" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", + "dependencies": { + "Microsoft.JSInterop": "8.0.11" + } + }, + "Microsoft.VisualStudio.Threading.Analyzers": { + "type": "Transitive", + "resolved": "17.10.48", + "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" + }, + "Roslynator.Analyzers": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" + }, + "StyleCop.Analyzers": { + "type": "Transitive", + "resolved": "1.2.0-beta.556", + "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.556" + } + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.556", + "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "nimbleblazor": { + "type": "Project", + "dependencies": { + "Apache.Arrow": "[18.0.0, 18.0.0]", + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + } + }, + "net8.0/browser-wasm": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + } + } + } } \ No newline at end of file diff --git a/packages/spright-components/src/chat/conversation/index.ts b/packages/spright-components/src/chat/conversation/index.ts index 6b5f4c080c..8b21371e4d 100644 --- a/packages/spright-components/src/chat/conversation/index.ts +++ b/packages/spright-components/src/chat/conversation/index.ts @@ -19,5 +19,7 @@ const sprightChatConversation = ChatConversation.compose({ styles }); -DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatConversation()); +DesignSystem.getOrCreate() + .withPrefix('spright') + .register(sprightChatConversation()); export const chatConversationTag = 'spright-chat-conversation'; diff --git a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts index e7ad070f57..4a3b2cb64d 100644 --- a/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts +++ b/packages/spright-components/src/chat/conversation/tests/chat-conversation.spec.ts @@ -22,13 +22,13 @@ describe('ChatConversation', () => { }); it('can construct an element instance', () => { - expect(document.createElement(chatConversationTag)).toBeInstanceOf(ChatConversation); + expect(document.createElement(chatConversationTag)).toBeInstanceOf( + ChatConversation + ); }); it('should have a slot element in the shadow DOM', async () => { await connect(); - expect( - (element.shadowRoot?.querySelector('SLOT')) - ).not.toBeNull(); + expect(element.shadowRoot?.querySelector('SLOT')).not.toBeNull(); }); }); diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 85f9c26540..739b273f76 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -5,7 +5,7 @@ import { borderHoverColor, borderWidth, fillSelectedColor, - mediumPadding, + mediumPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { display } from '../../utilities/style/display'; diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index a5d0150ec9..227694d240 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -23,14 +23,14 @@ describe('ChatMessage', () => { }); it('can construct an element instance', () => { - expect(document.createElement(chatMessageTag)).toBeInstanceOf(ChatMessage); + expect(document.createElement(chatMessageTag)).toBeInstanceOf( + ChatMessage + ); }); it('should have a slot element in the shadow DOM', async () => { await connect(); - expect( - (element.shadowRoot?.querySelector('SLOT')) - ).not.toBeNull(); + expect(element.shadowRoot?.querySelector('SLOT')).not.toBeNull(); }); it("should initialize 'message-type' to default", async () => { diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index 8f22fba5e1..67846dfcb6 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -5,7 +5,7 @@ export const ChatMessageType = { outbound: 'outbound', inbound: 'inbound', - system: 'system', + system: 'system' } as const; export type ChatMessageType = diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index e2ceed2917..f7b4a0704a 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -26,9 +26,10 @@ const metadata: Meta = { export default metadata; -const component = ( - [chatMessageTypeName, messageType]: ChatMessageTypeState, -): ViewTemplate => html` +const component = ([ + chatMessageTypeName, + messageType +]: ChatMessageTypeState): ViewTemplate => html` <${chatMessageTag} message-type=${() => messageType} style="margin-right: 8px;"> diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index c6de9ea9e6..860d383b4b 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -7,12 +7,12 @@ import { chatMessageTag } from '../../../../spright-components/src/chat/message' <Meta of={chatStories} /> <Title of={chatStories} /> -Chat components are used to conduct and display a conversation with a chat bot or other users. -The components can collect user input and display responses; the application is responsible -for connecting them to a source of data. +Chat components are used to conduct and display a conversation with a chat bot +or other users. The components can collect user input and display responses; the +application is responsible for connecting them to a source of data. -Components include low level chat messages and input fields and higher level composite components -representing an entire conversation. +Components include low level chat messages and input fields and higher level +composite components representing an entire conversation. ## API @@ -20,7 +20,8 @@ representing an entire conversation. ### Chat conversation -Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. +Use the <Tag name={chatConversationTag} /> element to display a series of +messages in a conversation. <Canvas of={chatStories.chatConversation} /> <Controls of={chatStories.chatConversation} /> @@ -45,4 +46,4 @@ Use the <Tag name={chatMessageTag} /> element to display content in a message. {/* ## Accessibility */} -{/* ## Resources */} \ No newline at end of file +{/* ## Resources */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index aec160a831..131b55bb69 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -8,7 +8,7 @@ import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/v import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { apiCategory, - createUserSelectedThemeStory, + createUserSelectedThemeStory } from '../../utilities/storybook'; const metadata: Meta<ChatMessageTextArgs> = { @@ -175,7 +175,6 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { description: 'The second prompt text', table: { category: apiCategory.slots } } - }, args: { messageType: ChatMessageType.system, From 96d9bae4dc436d820115b7886d725b8684763d6d Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 31 Jan 2025 15:49:26 -0600 Subject: [PATCH 36/61] Reverted lock.json files --- .../Examples/Demo.Client/packages.lock.json | 720 +++++++++--------- .../packages.lock.json | 678 ++++++++--------- 2 files changed, 699 insertions(+), 699 deletions(-) diff --git a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json index 14db397e06..bacf469850 100644 --- a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json @@ -1,361 +1,361 @@ -{ - "version": 1, - "dependencies": { - "net8.0": { - "Microsoft.AspNetCore.Components.WebAssembly": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "8.0.11", - "Microsoft.Extensions.Configuration.Binder": "8.0.2", - "Microsoft.Extensions.Configuration.Json": "8.0.1", - "Microsoft.Extensions.Logging": "8.0.1", - "Microsoft.JSInterop.WebAssembly": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.WebAssembly.DevServer": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "Yl6dGx9jd5ZkjRl6iJhguazv16qZio5KpVynL3YVfrFz3UM5g3ZvkaZkZ6bF9/z7hADf6qoX4CRRnSPwbFb20A==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "zk5lnZrYJgtuJG8L4v17Ej8rZ3PUcR2iweNV08BaO5LbYHIi2wNaVNcJoLxvqgQdnjLlKnCCfVGLDr6QHeAarQ==" - }, - "Microsoft.NET.Sdk.WebAssembly.Pack": { - "type": "Direct", - "requested": "[9.0.0, )", - "resolved": "9.0.0", - "contentHash": "Ch6dilt/TAo3XryG/9LF8Zy4rAT+2HYnks8thWAeNzPNOJs4aSyC6E5yxuBiN49d2eES78h1mSR/KNyOfbptXQ==" - }, - "NI.CSharp.Analyzers": { - "type": "Direct", - "requested": "[2.0.28, )", - "resolved": "2.0.28", - "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "Microsoft.CodeAnalysis.CSharp": "4.2.0", - "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", - "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", - "Roslynator.Analyzers": "4.1.1", - "StyleCop.Analyzers": "1.2.0-beta.556" - } - }, - "Apache.Arrow": { - "type": "Transitive", - "resolved": "18.0.0", - "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" - }, - "Microsoft.AspNetCore.Authorization": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", - "dependencies": { - "Microsoft.AspNetCore.Metadata": "8.0.11", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.AspNetCore.Components": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", - "dependencies": { - "Microsoft.AspNetCore.Authorization": "8.0.11", - "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Analyzers": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" - }, - "Microsoft.AspNetCore.Components.Forms": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Web": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11", - "Microsoft.AspNetCore.Components.Forms": "8.0.11", - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Primitives": "8.0.0", - "Microsoft.JSInterop": "8.0.11", - "System.IO.Pipelines": "8.0.0" - } - }, - "Microsoft.AspNetCore.Metadata": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" - }, - "Microsoft.CodeAnalysis.Analyzers": { - "type": "Transitive", - "resolved": "3.3.3", - "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" - }, - "Microsoft.CodeAnalysis.Common": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "System.Collections.Immutable": "5.0.0", - "System.Memory": "4.5.4", - "System.Reflection.Metadata": "5.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.CodeAnalysis.CSharp": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", - "dependencies": { - "Microsoft.CodeAnalysis.Common": "[4.2.0]" - } - }, - "Microsoft.CodeAnalysis.NetAnalyzers": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.FileExtensions": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Json": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileProviders.Physical": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", - "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileSystemGlobbing": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" - }, - "Microsoft.JSInterop": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" - }, - "Microsoft.JSInterop.WebAssembly": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", - "dependencies": { - "Microsoft.JSInterop": "8.0.11" - } - }, - "Microsoft.VisualStudio.Threading.Analyzers": { - "type": "Transitive", - "resolved": "17.10.48", - "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" - }, - "Roslynator.Analyzers": { - "type": "Transitive", - "resolved": "4.1.1", - "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" - }, - "StyleCop.Analyzers": { - "type": "Transitive", - "resolved": "1.2.0-beta.556", - "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", - "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.556" - } - }, - "StyleCop.Analyzers.Unstable": { - "type": "Transitive", - "resolved": "1.2.0.556", - "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" - }, - "demo.shared": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )", - "NI.CSharp.Analyzers": "[2.0.28, )", - "NimbleBlazor": "[1.0.0, )", - "SprightBlazor": "[1.0.0, )" - } - }, - "nimbleblazor": { - "type": "Project", - "dependencies": { - "Apache.Arrow": "[18.0.0, 18.0.0]", - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - }, - "sprightblazor": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - } - }, - "net8.0/browser-wasm": { - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - } - } +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.11", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.JSInterop.WebAssembly": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.WebAssembly.DevServer": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "Yl6dGx9jd5ZkjRl6iJhguazv16qZio5KpVynL3YVfrFz3UM5g3ZvkaZkZ6bF9/z7hADf6qoX4CRRnSPwbFb20A==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.12, )", + "resolved": "8.0.12", + "contentHash": "FV4HnQ3JI15PHnJ5PGTbz+rYvrih42oLi/7UMIshNwCwUZhTq13UzrggtXk4ygrcMcN+4jsS6hhshx2p/Zd0ig==" + }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "type": "Direct", + "requested": "[8.0.12, )", + "resolved": "8.0.12", + "contentHash": "JS5B7ZJVqaBOjlbjDgOkg+COEy24CB6IdGiwNeZnPJMoIZFdxehGFUmlxl4Mz3GZaoIduOtMtwkEdy6jh+NUpg==" + }, + "NI.CSharp.Analyzers": { + "type": "Direct", + "requested": "[2.0.28, )", + "resolved": "2.0.28", + "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "Microsoft.CodeAnalysis.CSharp": "4.2.0", + "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", + "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", + "Roslynator.Analyzers": "4.1.1", + "StyleCop.Analyzers": "1.2.0-beta.556" + } + }, + "Apache.Arrow": { + "type": "Transitive", + "resolved": "18.0.0", + "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.11", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.11", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11", + "Microsoft.AspNetCore.Components.Forms": "8.0.11", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.11", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.2.0]" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", + "dependencies": { + "Microsoft.JSInterop": "8.0.11" + } + }, + "Microsoft.VisualStudio.Threading.Analyzers": { + "type": "Transitive", + "resolved": "17.10.48", + "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" + }, + "Roslynator.Analyzers": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" + }, + "StyleCop.Analyzers": { + "type": "Transitive", + "resolved": "1.2.0-beta.556", + "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.556" + } + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.556", + "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "demo.shared": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )", + "NI.CSharp.Analyzers": "[2.0.28, )", + "NimbleBlazor": "[1.0.0, )", + "SprightBlazor": "[1.0.0, )" + } + }, + "nimbleblazor": { + "type": "Project", + "dependencies": { + "Apache.Arrow": "[18.0.0, 18.0.0]", + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + } + }, + "net8.0/browser-wasm": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + } + } + } } \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json index 0bf72d4c3e..61b6676669 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance.Client/packages.lock.json @@ -1,340 +1,340 @@ -{ - "version": 1, - "dependencies": { - "net8.0": { - "Microsoft.AspNetCore.Components.WebAssembly": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", - "dependencies": { - "Microsoft.AspNetCore.Components.Web": "8.0.11", - "Microsoft.Extensions.Configuration.Binder": "8.0.2", - "Microsoft.Extensions.Configuration.Json": "8.0.1", - "Microsoft.Extensions.Logging": "8.0.1", - "Microsoft.JSInterop.WebAssembly": "8.0.11" - } - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.11, )", - "resolved": "8.0.11", - "contentHash": "zk5lnZrYJgtuJG8L4v17Ej8rZ3PUcR2iweNV08BaO5LbYHIi2wNaVNcJoLxvqgQdnjLlKnCCfVGLDr6QHeAarQ==" - }, - "Microsoft.NET.Sdk.WebAssembly.Pack": { - "type": "Direct", - "requested": "[9.0.0, )", - "resolved": "9.0.0", - "contentHash": "Ch6dilt/TAo3XryG/9LF8Zy4rAT+2HYnks8thWAeNzPNOJs4aSyC6E5yxuBiN49d2eES78h1mSR/KNyOfbptXQ==" - }, - "NI.CSharp.Analyzers": { - "type": "Direct", - "requested": "[2.0.28, )", - "resolved": "2.0.28", - "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "Microsoft.CodeAnalysis.CSharp": "4.2.0", - "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", - "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", - "Roslynator.Analyzers": "4.1.1", - "StyleCop.Analyzers": "1.2.0-beta.556" - } - }, - "Apache.Arrow": { - "type": "Transitive", - "resolved": "18.0.0", - "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" - }, - "Microsoft.AspNetCore.Authorization": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", - "dependencies": { - "Microsoft.AspNetCore.Metadata": "8.0.11", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.AspNetCore.Components": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", - "dependencies": { - "Microsoft.AspNetCore.Authorization": "8.0.11", - "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Analyzers": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" - }, - "Microsoft.AspNetCore.Components.Forms": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11" - } - }, - "Microsoft.AspNetCore.Components.Web": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", - "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.11", - "Microsoft.AspNetCore.Components.Forms": "8.0.11", - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Primitives": "8.0.0", - "Microsoft.JSInterop": "8.0.11", - "System.IO.Pipelines": "8.0.0" - } - }, - "Microsoft.AspNetCore.Metadata": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" - }, - "Microsoft.CodeAnalysis.Analyzers": { - "type": "Transitive", - "resolved": "3.3.3", - "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" - }, - "Microsoft.CodeAnalysis.Common": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", - "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.3", - "System.Collections.Immutable": "5.0.0", - "System.Memory": "4.5.4", - "System.Reflection.Metadata": "5.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.CodeAnalysis.CSharp": { - "type": "Transitive", - "resolved": "4.2.0", - "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", - "dependencies": { - "Microsoft.CodeAnalysis.Common": "[4.2.0]" - } - }, - "Microsoft.CodeAnalysis.NetAnalyzers": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.FileExtensions": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Json": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileProviders.Physical": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", - "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.FileSystemGlobbing": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.1", - "Microsoft.Extensions.Logging.Abstractions": "8.0.2", - "Microsoft.Extensions.Options": "8.0.2" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.2", - "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" - }, - "Microsoft.JSInterop": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" - }, - "Microsoft.JSInterop.WebAssembly": { - "type": "Transitive", - "resolved": "8.0.11", - "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", - "dependencies": { - "Microsoft.JSInterop": "8.0.11" - } - }, - "Microsoft.VisualStudio.Threading.Analyzers": { - "type": "Transitive", - "resolved": "17.10.48", - "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" - }, - "Roslynator.Analyzers": { - "type": "Transitive", - "resolved": "4.1.1", - "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" - }, - "StyleCop.Analyzers": { - "type": "Transitive", - "resolved": "1.2.0-beta.556", - "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", - "dependencies": { - "StyleCop.Analyzers.Unstable": "1.2.0.556" - } - }, - "StyleCop.Analyzers.Unstable": { - "type": "Transitive", - "resolved": "1.2.0.556", - "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" - }, - "nimbleblazor": { - "type": "Project", - "dependencies": { - "Apache.Arrow": "[18.0.0, 18.0.0]", - "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" - } - } - }, - "net8.0/browser-wasm": { - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - } - } +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.11, )", + "resolved": "8.0.11", + "contentHash": "rrvIBSuEmxSo9qn18QHarVE1azbTk6+HU8CgYCUiNmh+NcK7dz6FmkiX3TH+buE+X1I/735LacefMabr4spLRg==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.11", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.JSInterop.WebAssembly": "8.0.11" + } + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.12, )", + "resolved": "8.0.12", + "contentHash": "FV4HnQ3JI15PHnJ5PGTbz+rYvrih42oLi/7UMIshNwCwUZhTq13UzrggtXk4ygrcMcN+4jsS6hhshx2p/Zd0ig==" + }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "type": "Direct", + "requested": "[8.0.12, )", + "resolved": "8.0.12", + "contentHash": "JS5B7ZJVqaBOjlbjDgOkg+COEy24CB6IdGiwNeZnPJMoIZFdxehGFUmlxl4Mz3GZaoIduOtMtwkEdy6jh+NUpg==" + }, + "NI.CSharp.Analyzers": { + "type": "Direct", + "requested": "[2.0.28, )", + "resolved": "2.0.28", + "contentHash": "elpqlHHGeZObXFxMoQnIu7yS2kWpXEJemFS7rIp2W5vANPXvmHQPkEiYFRu2P+uhvyHB9DCVQVjv+WjYQ0uPRw==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "Microsoft.CodeAnalysis.CSharp": "4.2.0", + "Microsoft.CodeAnalysis.NetAnalyzers": "9.0.0", + "Microsoft.VisualStudio.Threading.Analyzers": "17.10.48", + "Roslynator.Analyzers": "4.1.1", + "StyleCop.Analyzers": "1.2.0-beta.556" + } + }, + "Apache.Arrow": { + "type": "Transitive", + "resolved": "18.0.0", + "contentHash": "YaWKYdyPhTFCcrqT5F1KmIkNdKO7lQg+TAyg8sdQg8Xw3CE3jyjdixlOoTT36Af15O0z5CUIYfnkEzm9Lix+Hg==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "ACaLyjBSz9WUzbaJe0Sv09/FihRNHYlRUIj3uQ8CZFFByf6Qwv3+PXnbltidFKz2iOyqdvppQias3emdQUY2nA==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.11", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "kyhSQcVEQvMnv2BNRn7JRgYCr+PIO5Uh1mhIFdCNycxE/k8NsI72sV693s1KVmVebMA8g3hTBmfBEheWb3hhww==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.11", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "4JtFt5IR0ixuFpwY6D2Xi5R+vZQ6iykd2EuG3puHETCOZOgYG8M538LCY1lbgQTkHOL04YKDjQTQu8PU/BaXRQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "60g+idqaiVhPVNOqauy/vH5lREpjcuKl3/w6zJhdU1PFWg4jtdoyIPQH+qxBKsUohkELhH3cRfzGRKElVuZuwg==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "IDmjQ/K7hv6zUEz2LsCkQBngZx6PMnty8OdSPf0hYGMpC+4Yi37pgCc/25fFu3CSBe8nDirqTrqKtfToHWCpbw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.11", + "Microsoft.AspNetCore.Components.Forms": "8.0.11", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.11", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.2.0]" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "JajbvkrBgtdRghavIjcJuNHMOja4lqBmEezbhZyqWPYh2cpLhT5mPpfC7NQVDO4IehWQum9t/nwF4v+qQGtYWg==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.11", + "contentHash": "eB6YYFdA2DnmR8W1WO9of4hBSaRTsmxke7FVbHjzjhYu/1XgMZ9FZq6sY5OjE7rnkGN3XYHXXWB4T49Y8DAthA==", + "dependencies": { + "Microsoft.JSInterop": "8.0.11" + } + }, + "Microsoft.VisualStudio.Threading.Analyzers": { + "type": "Transitive", + "resolved": "17.10.48", + "contentHash": "xwvwT91oqFjLgQykUp6y/JPYxz8LchbfJKrLVatfczWddXKng8DAo8RiiIodt+pRdsVXP9Ud02GtJoY7ifdXPQ==" + }, + "Roslynator.Analyzers": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" + }, + "StyleCop.Analyzers": { + "type": "Transitive", + "resolved": "1.2.0-beta.556", + "contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.556" + } + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.556", + "contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "nimbleblazor": { + "type": "Project", + "dependencies": { + "Apache.Arrow": "[18.0.0, 18.0.0]", + "Microsoft.AspNetCore.Components.Web": "[8.0.11, )" + } + } + }, + "net8.0/browser-wasm": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + } + } + } } \ No newline at end of file From 5c8584b2bf630fd3f8a8de308ee46bfc50bdd301 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 31 Jan 2025 17:42:50 -0600 Subject: [PATCH 37/61] Implemented feedback --- .../src/chat/message/tests/chat-message.spec.ts | 3 +++ .../src/chat/message/tests/types.spec.ts | 9 +++++++++ 2 files changed, 12 insertions(+) create mode 100644 packages/spright-components/src/chat/message/tests/types.spec.ts diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index 227694d240..d088feb6f7 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -31,6 +31,9 @@ describe('ChatMessage', () => { it('should have a slot element in the shadow DOM', async () => { await connect(); expect(element.shadowRoot?.querySelector('SLOT')).not.toBeNull(); + expect( + element?.innerText?.includes('Some message', undefined) + ).toBeTrue(); }); it("should initialize 'message-type' to default", async () => { diff --git a/packages/spright-components/src/chat/message/tests/types.spec.ts b/packages/spright-components/src/chat/message/tests/types.spec.ts new file mode 100644 index 0000000000..d4b72f973f --- /dev/null +++ b/packages/spright-components/src/chat/message/tests/types.spec.ts @@ -0,0 +1,9 @@ +import type { ChatMessageType } from '../../types'; + +describe('ChatMessage message type', () => { + it('ChatMessageType fails compile if assigning arbitrary string values', () => { + // @ts-expect-error This expect will fail if the enum-like type is missing "as const" + const messageType: ChatMessageType = 'hello'; + expect(messageType).toEqual('hello'); + }); +}); From 3160b95e60d7f7b7bc687a23f06d53f46bb12aee Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 3 Feb 2025 13:29:50 -0600 Subject: [PATCH 38/61] Simpsons reference --- .../src/spright/chat/chat.stories.ts | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 131b55bb69..40385714d0 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -15,15 +15,7 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; -const markdownExample = `To configure your Python version: - -1. Select **Adapters...** from the **Configure** menu. - -2. Configure the Python adapter. - -3. Choose the desired version from the **Version** dropdown. - -You can also specify a Python version for a specific module call in the **Advanced Settings** of the Python adapter.`; +const markdownExample = 'I see **Esc**, **Crtl**, and **Pg Up**. There doesn\'t seem to be any **Any** key.'; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversation {} @@ -33,24 +25,21 @@ export const chatConversation: StoryObj<ChatConversation> = { }, render: createUserSelectedThemeStory(html` <${chatConversationTag}> - <${chatMessageTag} message-type='outbound'> - Hi, can you please help me? - </${chatMessageTag}> <${chatMessageTag} message-type='inbound'> - Yeah sure, what do you need help with? + To start, press any key. </${chatMessageTag}> <${chatMessageTag} message-type='outbound'> - Can you show me an example of some rendered markdown content? It should include a list and some bold text. Maybe some italics too. + Where is the Any key? </${chatMessageTag}> - <${chatMessageTag} message-type='inbound'> + <${chatMessageTag} message-type='outbound'> <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> </${chatMessageTag}> <${chatMessageTag} message-type='system'> <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> <${chatMessageTag} message-type='system'> - <${buttonTag} appearance='block'>Help with my taxes</${buttonTag}> - <${buttonTag} appearance='block'>Provide me some life advice</${buttonTag}> + <${buttonTag} appearance='block'>Order a tab</${buttonTag}> + <${buttonTag} appearance='block'>Check core temperature</${buttonTag}> </${chatMessageTag}> </${chatConversationTag}> @@ -89,7 +78,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { } }, args: { - text: 'How do I choose which version of Python to execute my script?', + text: 'Aurora Borealis? At this time of year? At this time of day? In this part of the country? Localized entirely within your kitchen?', messageType: ChatMessageType.outbound } }; @@ -178,7 +167,7 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { }, args: { messageType: ChatMessageType.system, - prompt1: 'Explain how to do my job', - prompt2: 'What is the meaning of life?' + prompt1: 'Eat my shorts', + prompt2: 'Do the Bartman' } }; From 5581ea4a0964f20449969588980a0a0f83c8644b Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 3 Feb 2025 13:34:30 -0600 Subject: [PATCH 39/61] Status table --- .../storybook/src/docs/component-status.stories.ts | 12 ++++++++++++ packages/storybook/src/docs/types.ts | 1 + 2 files changed, 13 insertions(+) diff --git a/packages/storybook/src/docs/component-status.stories.ts b/packages/storybook/src/docs/component-status.stories.ts index 881c0f3e4b..50fa740b9f 100644 --- a/packages/storybook/src/docs/component-status.stories.ts +++ b/packages/storybook/src/docs/component-status.stories.ts @@ -6,6 +6,7 @@ import { tableColumnMappingTag } from '../../../nimble-components/src/table-colu import { mappingIconTag } from '../../../nimble-components/src/mapping/icon'; import { iconCheckTag } from '../../../nimble-components/src/icons/check'; import { iconTriangleTag } from '../../../nimble-components/src/icons/triangle'; +import { iconTriangleFilledTag } from '../../../nimble-components/src/icons/triangle-filled'; import { iconXmarkTag } from '../../../nimble-components/src/icons/xmark'; import { tableFitRowsHeight } from '../../../nimble-components/src/theme-provider/design-tokens'; import { ComponentFrameworkStatus } from './types'; @@ -136,6 +137,16 @@ const components = [ angularStatus: ComponentFrameworkStatus.ready, blazorStatus: ComponentFrameworkStatus.ready }, + { + componentName: 'Chat', + componentHref: './?path=/docs/spright-chat--docs', + designHref: + 'https://www.figma.com/design/PO9mFOu5BCl8aJvFchEeuN/Nimble_Components?node-id=12342-81782&node-type=canvas&t=L5GvLaC3injrqWrR-0', + designLabel: 'Figma', + componentStatus: ComponentFrameworkStatus.spright, + angularStatus: ComponentFrameworkStatus.doesNotExist, + blazorStatus: ComponentFrameworkStatus.doesNotExist + }, { componentName: 'Checkbox', componentHref: './?path=/docs/components-checkbox--docs', @@ -547,6 +558,7 @@ const components = [ const iconMappings = html` <${mappingIconTag} key="${ComponentFrameworkStatus.ready}" text="Ready" icon="${iconCheckTag}" severity="success" text-hidden></${mappingIconTag}> + <${mappingIconTag} key="${ComponentFrameworkStatus.spright}" text="Spright" icon="${iconTriangleFilledTag}" severity="success"></${mappingIconTag}> <${mappingIconTag} key="${ComponentFrameworkStatus.incubating}" text="Incubating" icon="${iconTriangleTag}" severity="warning"></${mappingIconTag}> <${mappingIconTag} key="${ComponentFrameworkStatus.doesNotExist}" text="Does not exist" icon="${iconXmarkTag}" severity="error"></${mappingIconTag}> `; diff --git a/packages/storybook/src/docs/types.ts b/packages/storybook/src/docs/types.ts index c1ff0eb19c..fc097937a4 100644 --- a/packages/storybook/src/docs/types.ts +++ b/packages/storybook/src/docs/types.ts @@ -1,5 +1,6 @@ export const ComponentFrameworkStatus = { ready: 'ready', + spright: 'spright', incubating: 'incubating', doesNotExist: 'does_not_exist' } as const; From 0232ae3f3f73b1e1a65f4e73e65556e8d1bb2c51 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:02:50 -0600 Subject: [PATCH 40/61] Improve doc content --- packages/storybook/src/spright/chat/chat.mdx | 28 ++++++++++----- .../src/spright/chat/chat.stories.ts | 36 ++++++++----------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 860d383b4b..fb54ed32df 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -7,12 +7,11 @@ import { chatMessageTag } from '../../../../spright-components/src/chat/message' <Meta of={chatStories} /> <Title of={chatStories} /> -Chat components are used to conduct and display a conversation with a chat bot -or other users. The components can collect user input and display responses; the +Chat components are used to display a conversation with a chat bot +or other users. The components can display messages but the application is responsible for connecting them to a source of data. -Components include low level chat messages and input fields and higher level -composite components representing an entire conversation. +Components include a chat message and a chat conversation, which is a collection of messages. ## API @@ -29,20 +28,33 @@ messages in a conversation. ### Chat message Use the <Tag name={chatMessageTag} /> element to display content in a message. +Clients can place any HTML content within the message. + +#### Text message content <Canvas of={chatStories.chatMessageText} /> <Controls of={chatStories.chatMessageText} /> +#### Rich text message content + <Canvas of={chatStories.chatMessageRichText} /> -<Controls of={chatStories.chatMessageRichText} /> + +#### Spinner message content <Canvas of={chatStories.chatMessageSpinner} /> -<Controls of={chatStories.chatMessageSpinner} /> + +#### Prompt buttons message content <Canvas of={chatStories.chatMessagePrompts} /> -<Controls of={chatStories.chatMessagePrompts} /> -{/* ## Usage */} +## Usage + +These components are part of [Spright](?path=/docs/spright-docs--docs). They can be used in production +applications but are not yet part of the core Nimble library for reasons including: + +1. the interaction and visual design are iterating rapidly +2. we are unsure if the components are sufficiently atomic or general purpose to belong in Nimble +3. the implementation has not yet prioritized Nimble requirements like accessibility and support for all frameworks {/* ## Accessibility */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 40385714d0..a79b5f601a 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -42,8 +42,14 @@ export const chatConversation: StoryObj<ChatConversation> = { <${buttonTag} appearance='block'>Check core temperature</${buttonTag}> </${chatMessageTag}> </${chatConversationTag}> - - `) + `), + argTypes: { + content: { + name: 'default', + description: 'The messages to display in the chat conversation. The DOM order of the messages controls their screen order within the conversation (earlier DOM order implies older message)', + table: { category: apiCategory.slots } + }, + }, }; interface ChatMessageArgs { @@ -67,13 +73,15 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { `), argTypes: { text: { - description: 'The text to display in the chat message.', + name: 'default', + description: 'The content to display in the chat message.', table: { category: apiCategory.slots } }, messageType: { + name: 'message-type', options: Object.keys(ChatMessageType), control: { type: 'radio' }, - description: 'The status of the chat message.', + description: 'The type of the chat message.', table: { category: apiCategory.attributes } } }, @@ -135,18 +143,14 @@ export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { } }; -interface ChatMessagePrompts extends ChatMessageArgs { - prompt1: string; - prompt2: string; -} -export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { +export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { parameters: { actions: {} }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> - <${buttonTag} appearance='block'>${x => x.prompt1}</${buttonTag}> - <${buttonTag} appearance='block'>${x => x.prompt2}</${buttonTag}> + <${buttonTag} appearance='block'>Eat my shorts</${buttonTag}> + <${buttonTag} appearance='block'>Do the Bartman</${buttonTag}> </${chatMessageTag}> `), argTypes: { @@ -156,18 +160,8 @@ export const chatMessagePrompts: StoryObj<ChatMessagePrompts> = { description: 'The status of the chat message.', table: { category: apiCategory.attributes } }, - prompt1: { - description: 'The first prompt text', - table: { category: apiCategory.slots } - }, - prompt2: { - description: 'The second prompt text', - table: { category: apiCategory.slots } - } }, args: { messageType: ChatMessageType.system, - prompt1: 'Eat my shorts', - prompt2: 'Do the Bartman' } }; From 761c74a846a746ead681c4fbf9d9d458418e54ed Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:05:13 -0600 Subject: [PATCH 41/61] linting --- packages/storybook/src/spright/chat/chat.mdx | 20 +++++++++++-------- .../src/spright/chat/chat.stories.ts | 13 ++++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index fb54ed32df..0155967070 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -7,11 +7,12 @@ import { chatMessageTag } from '../../../../spright-components/src/chat/message' <Meta of={chatStories} /> <Title of={chatStories} /> -Chat components are used to display a conversation with a chat bot -or other users. The components can display messages but the -application is responsible for connecting them to a source of data. +Chat components are used to display a conversation with a chat bot or other +users. The components can display messages but the application is responsible +for connecting them to a source of data. -Components include a chat message and a chat conversation, which is a collection of messages. +Components include a chat message and a chat conversation, which is a collection +of messages. ## API @@ -49,12 +50,15 @@ Clients can place any HTML content within the message. ## Usage -These components are part of [Spright](?path=/docs/spright-docs--docs). They can be used in production -applications but are not yet part of the core Nimble library for reasons including: +These components are part of [Spright](?path=/docs/spright-docs--docs). They can +be used in production applications but are not yet part of the core Nimble +library for reasons including: 1. the interaction and visual design are iterating rapidly -2. we are unsure if the components are sufficiently atomic or general purpose to belong in Nimble -3. the implementation has not yet prioritized Nimble requirements like accessibility and support for all frameworks +2. we are unsure if the components are sufficiently atomic or general purpose to + belong in Nimble +3. the implementation has not yet prioritized Nimble requirements like + accessibility and support for all frameworks {/* ## Accessibility */} diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index a79b5f601a..814d72c978 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -15,7 +15,7 @@ const metadata: Meta<ChatMessageTextArgs> = { title: 'Spright/Chat' }; -const markdownExample = 'I see **Esc**, **Crtl**, and **Pg Up**. There doesn\'t seem to be any **Any** key.'; +const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversation {} @@ -46,10 +46,11 @@ export const chatConversation: StoryObj<ChatConversation> = { argTypes: { content: { name: 'default', - description: 'The messages to display in the chat conversation. The DOM order of the messages controls their screen order within the conversation (earlier DOM order implies older message)', + description: + 'The messages to display in the chat conversation. The DOM order of the messages controls their screen order within the conversation (earlier DOM order implies older message)', table: { category: apiCategory.slots } - }, - }, + } + } }; interface ChatMessageArgs { @@ -159,9 +160,9 @@ export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { control: { type: 'radio' }, description: 'The status of the chat message.', table: { category: apiCategory.attributes } - }, + } }, args: { - messageType: ChatMessageType.system, + messageType: ChatMessageType.system } }; From f9558ce923669ac1f20306e4fbabad6f6ea69f89 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Mon, 3 Feb 2025 18:45:18 -0600 Subject: [PATCH 42/61] Added chat messages of different sizes --- .../chat/chat-message-matrix.stories.ts | 179 +++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index f7b4a0704a..7e85d1c379 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -9,6 +9,8 @@ import { } from '../../utilities/matrix'; import { createStory } from '../../utilities/storybook'; import { hiddenWrapper } from '../../utilities/hidden'; +import { loremIpsum } from '../../utilities/lorem-ipsum'; +import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; const chatMessageTypes = [ ['outbound', ChatMessageType.outbound], @@ -26,6 +28,129 @@ const metadata: Meta = { export default metadata; +const multiLineMessage = ` +-------------------------------------------------------------------- + +Introduction to TestStand + +NI TestStand is a flexible and open test management framework for building, customizing, and deploying a full-featured test management system. + +**Creating a TestStand-Based System** + +Creating a TestStand-based test solution is a process that includes designing the test system, developing test sequences for units under test (UUTs), customizing the TestStand framework, debugging the test sequences, and deploying the test system to test station computers. + +**Design** + +Learn about the components of the TestStand framework, learn how to use those features, and understand when to customize that behavior. Plan the system architecture of the proposed solution. Determine the development environments to use to develop user interfaces and code modules in the solution. Consider how to manage the development and deployment of the solution, including how to organize files under development, how to deploy the files, and how to debug and update systems you deploy. + +Refer to the section of this tutorial for more information about the components and features of TestStand and how to customize those features. Refer to the NI TestStand Advanced Architecture Series for more advanced concept and architecture information. This series is a suite of documents TestStand architects and developers created to provide more detailed information for experienced TestStand users with complex projects. + +**Develop** + +Write test sequences for use on a test station computer. A test sequence is a series of steps that initialize instruments, perform complex tests, or change the flow of executions. Use the sequence editor or a custom sequence editor to write and edit test sequences. + +**Customize** + +Edit the default behavior of the TestStand framework depending on the needs of the application you create. You can customize reporting, database logging, process models, callback sequences, and user interfaces to create a unique, robust test solution for an application. + +**Debug** + +Ensure that the test sequences and any customized features execute correctly before you deploy the test system. Use the TestStand Sequence Analyzer in the sequence editor or the stand-alone sequence analyzer application during development or before deployment to find errors and enforce custom development guidelines you establish. + +TestStand provides multiple features in the sequence editor or a custom sequence editor for debugging sequences, including tracing, breakpoints, conditional breakpoints, stepping through code, and watch expressions. The TestStand system development cycle is an iterative process, and you might have to debug an application multiple times. + +**Deploy** + +After you develop, customize, and debug a TestStand system, you can deploy the system to multiple test stations. The TestStand Deployment Utility simplifies the complex process of deploying a TestStand system by automating many of the steps involved, including collecting sequence files, code modules, configuration data for instruments, and support files for the test system. You can also use the deployment utility to create an installer or patch distributions. + +**Major Software Components of TestStand** + +The major software components of TestStand include the TestStand Engine, sequence editor, user interfaces, module adapters, process models, and deployment utility. + +**TestStand Engine** + +The TestStand Engine is a set of DLLs that exports an ActiveX Automation server API. The sequence editor and TestStand User Interfaces use the TestStand API, which you can call from any programming environment that supports access to ActiveX servers, including code modules you write in LabVIEW and LabWindows/CVI. The NI TestStand Help includes detailed documentation for the TestStand API. + +**TestStand Sequence Editor** + +The sequence editor is a development environment in which you create, edit, execute, and debug sequences and the tests sequences call. Use the sequence editor to access all features, such as step types and process models. Refer to the Process Models section of this tutorial for more information about process models. + +You can debug a sequence using the following techniques, similar to how you debug in application development environments (ADEs) such as LabVIEW, LabWindows/CVI (ANSI), and Microsoft Visual Studio: + +- Setting breakpoints +- Stepping into, out of, or over steps +- Tracing through program executions +- Displaying variables +- Monitoring variables, expressions, and output messages during executions +- Performing static analysis of sequence files to locate errors and enforce coding guidelines + +In the sequence editor, you can start multiple concurrent executions, execute multiple instances of the same sequence, or execute different sequences at the same time. Each execution instance opens an Execution window. In Trace Mode, the Execution window shows the steps in the currently executing sequence. If the execution suspends, the Execution window shows the next step to execute and provides debugging options. + +In the sequence editor, you can fully customize the pane and tab layout to optimize development and debugging tasks. You can also customize the menus, toolbars, and keyboard shortcuts. + +**User Interfaces** + +A TestStand User Interface is an application you deploy to a development system or a production station to provide a custom GUI for executing, debugging, or editing sequences. Simple user interfaces might only support running sequences, and custom sequence editors might support editing, running, and debugging sequences. + +TestStand includes separate user interface applications developed in LabVIEW, LabWindows/CVI, Microsoft Visual Basic .NET Framework, C#, and C++ (MFC). Because TestStand also includes the source code for each user interface, you can fully customize the user interfaces. You can create a custom user interface using any programming language that can host ActiveX controls or control ActiveX Automation servers. + +TestStand ships with full-featured Custom Sequence Editor user interfaces. These interfaces can be found by default at C:/Users/Public/Documents/National Instruments/TestStand 20XX/UserInterfaces/Full-Featured/, or by navigating to **Start » All Programs » National Instruments » TestStand <Version> » User Interfaces** from the Windows Start Menu. + +With the user interfaces in Editor Mode, you can modify sequences and display sequence variables, sequence parameters, step properties, and so on. With the user interfaces in Operator Mode, you can start multiple concurrent executions, set breakpoints, and step through sequences. + +**Module Adapters** + +The TestStand Engine uses module adapters to invoke code modules that sequences call. A code module is a program module from an ADE or programming language and can contain one or more functions that perform a specific test or other action. Module adapters load and call code modules, pass parameters to code modules, and return values and status from code modules. The module adapters support the following types of code modules: + +- LabVIEW VIs +- LabWindows/CVI functions in DLLs you create in LabWindows/CVI or other compilers +- C/C++ functions in DLLs +- .NET assemblies +- ActiveX Automation servers +- HTBasic subroutines +- Python modules + +Adapters specific to an ADE can open the ADE, create source code for a new code module in the ADE, and display the source for an existing code module in the ADE. The adapters support stepping into the source code in the ADE while you execute the step from the TestStand Sequence Editor or a TestStand User Interface. + +TestStand includes the following module adapters: + +- LabVIEW Adapter—Calls LabVIEW VIs with a variety of connector panes. The VIs can exist in LLBs or in LabVIEW packed project libraries. You can also call VIs in the context of a LabVIEW project or call LabVIEW class member VIs. +- LabWindows/CVI Adapter—Calls C functions in a DLL with a variety of parameter types. +- C/C++ DLL Adapter—Calls C/C++ functions and static C++ class methods in a DLL with a variety of parameter types. You can call global static methods or static class methods in C++ DLLs. You can create the DLL code module with LabWindows/CVI, Visual Studio, or any other environment that can create a C/C++ DLL, including LabVIEW-built shared libraries. +.- NET Adapter—Calls .NET assemblies written in any .NET-compliant language, such as C# or Microsoft Visual Basic .NET. +- ActiveX/COM Adapter—Creates ActiveX/COM objects, calls methods, and accesses properties of those objects. When you create an object, you can assign the object reference to a variable or property for later use in other ActiveX/COM Adapter steps. +- Sequence Adapter—Calls a subsequence in the current sequence file, in another sequence file, or a sequence file on a remote system. You can also make recursive sequence calls. +- Python Adapter—Calls Python modules. + +Refer to the following tutorials for more information about using LabVIEW and LabWindows/CVI with TestStand. Refer to the NI TestStand Help for more information about using the LabVIEW and LabWindows/CVI Adapters. + +- Calling LabVIEW VIs +- Calling LabWindows/CVI Code Modules + +**Process Models** + +Testing a UUT requires more than just executing a set of tests. Usually, the test system must perform a series of operations before and after it executes the sequence that performs the tests. Common operations that define the testing process include identifying the UUT, notifying the operator of pass/fail status, logging results, and generating a report. The set of operations and the flow of execution is called a process model. A TestStand process model is a sequence file you can use to define standard testing operations so you do not have to re-implement the same operations in every sequence file you write. + +TestStand includes predefined Sequential, Parallel, and Batch models you can modify or replace. Use the Sequential model to run a test sequence on one UUT at a time. Use the Parallel and Batch models to run the same test sequence on multiple UUTs simultaneously. + +You can modify an existing TestStand process model or you can create a custom process model. The ability to modify a process model is essential because the testing process can vary depending on production lines, production sites, or company systems and practices. You can edit a process model in the same way you edit other sequence files. You can also use client sequence files to customize various model operations by overriding the callback sequences process models define. + +**Entry Points** + +A process model defines a set of entry points, and each entry point is a sequence in the process model file that invokes a test sequence file. Defining multiple entry points in a process model gives the test station operator different ways to invoke a Main sequence or configure the process model. + +Execution entry points in a process model provide different ways for the test station operator to invoke a Main sequence. Execution entry points handle common operations, such as UUT identification and report generation. For example, the default Sequential process model provides the Test UUTs and Single Pass Execution entry points. The Test UUTs Execution entry point initiates a loop that repeatedly identifies and tests UUTs. The Single Pass Execution entry point tests a single UUT without identifying it. + +Configuration entry points provide an interface for configuring the process model, typically through a GUI. For example, the default Batch model provides the Configure Model Options entry point. This entry point creates the Configure menu item. + +**TestStand Deployment Utility** + +Use the TestStand Deployment Utility to create a deployable image or a patch deployment of a TestStand system and an optional installer. The deployable image can contain sequence files, code modules, process models and supporting files, user interface applications, configuration files, and step types and supporting files the TestStand system uses. The installer can contain all files from a deployable image or contain only a subset of files to create a patch for a previously deployed image. + +You can also use the deployment utility to include the TestStand Engine and supporting files, LabVIEW and LabWindows/CVI Run-Time Engines, and hardware drivers in the installer you create. The installer that the deployment utility creates can also register ActiveX servers, replace existing files on the target computer, and create program shortcuts. You can configure the deployment utility to remove VI block diagrams or to lock the VIs you deploy. + +--------------------------------------------------------------------`; + const component = ([ chatMessageTypeName, messageType @@ -33,13 +158,65 @@ const component = ([ <${chatMessageTag} message-type=${() => messageType} style="margin-right: 8px;"> - ${() => `${chatMessageTypeName} Chat Message`}</${chatMessageTag}> + ${() => `Message Type: ${chatMessageTypeName}`}</${chatMessageTag}> +`; + +const differentChatSizeConversationTestCase = ( + [message]: [string], + [messageType]: [string] +): ViewTemplate => html` + <${chatMessageTag} + message-type=${() => messageType} + style="margin-right: 8px;"> + <${richTextViewerTag} + :markdown="${_ => message}"> + </${richTextViewerTag} + </${chatMessageTag}> `; export const chatMessageThemeMatrix: StoryFn = createMatrixThemeStory( createMatrix(component, [chatMessageTypes]) ); +export const tinyMessageSizing: StoryFn = createStory(html` + ${createMatrix(differentChatSizeConversationTestCase, [ + [ + ['a'], + ], + [ + ['outbound'], + ['inbound'], + ['system'] + ] + ])} +`); + +export const extraWideMessagSizing: StoryFn = createStory(html` + ${createMatrix(differentChatSizeConversationTestCase, [ + [ + [loremIpsum], + ], + [ + ['outbound'], + ['inbound'], + ['system'] + ] + ])} +`); + +export const manyLinesMessagSizing: StoryFn = createStory(html` + ${createMatrix(differentChatSizeConversationTestCase, [ + [ + [multiLineMessage], + ], + [ + ['outbound'], + ['inbound'], + ['system'] + ] + ])} +`); + export const hiddenChatMessage: StoryFn = createStory( hiddenWrapper( html`<${chatMessageTag} hidden>Hidden Chat Message</${chatMessageTag}>` From 4dfac11fe296433e4a2b3c347b3203b166c9f828 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Mon, 3 Feb 2025 21:19:20 -0600 Subject: [PATCH 43/61] Ran lint tool and added conversation tests --- .../chat/chat-message-matrix.stories.ts | 69 +++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index 7e85d1c379..4b17a46809 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -11,6 +11,7 @@ import { createStory } from '../../utilities/storybook'; import { hiddenWrapper } from '../../utilities/hidden'; import { loremIpsum } from '../../utilities/lorem-ipsum'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; +import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; const chatMessageTypes = [ ['outbound', ChatMessageType.outbound], @@ -161,7 +162,7 @@ const component = ([ ${() => `Message Type: ${chatMessageTypeName}`}</${chatMessageTag}> `; -const differentChatSizeConversationTestCase = ( +const differentChatMessageSizeTestCase = ( [message]: [string], [messageType]: [string] ): ViewTemplate => html` @@ -174,46 +175,58 @@ const differentChatSizeConversationTestCase = ( </${chatMessageTag}> `; +const differentChatConversationSizeTestCase = ([message]: [ + string +]): ViewTemplate => html` + <${chatConversationTag}> + <${chatMessageTag} message-type='outbound' style="margin-right: 8px;"> + <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> + </${chatMessageTag}> + <${chatMessageTag} message-type='inbound' style="margin-right: 8px;"> + <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> + </${chatMessageTag}> + <${chatMessageTag} message-type='system' style="margin-right: 8px;"> + <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> + </${chatMessageTag}> + </${chatConversationTag}> +`; + export const chatMessageThemeMatrix: StoryFn = createMatrixThemeStory( createMatrix(component, [chatMessageTypes]) ); export const tinyMessageSizing: StoryFn = createStory(html` - ${createMatrix(differentChatSizeConversationTestCase, [ - [ - ['a'], - ], - [ - ['outbound'], - ['inbound'], - ['system'] - ] + ${createMatrix(differentChatMessageSizeTestCase, [ + [['a']], + [['outbound'], ['inbound'], ['system']] ])} `); export const extraWideMessagSizing: StoryFn = createStory(html` - ${createMatrix(differentChatSizeConversationTestCase, [ - [ - [loremIpsum], - ], - [ - ['outbound'], - ['inbound'], - ['system'] - ] + ${createMatrix(differentChatMessageSizeTestCase, [ + [[loremIpsum]], + [['outbound'], ['inbound'], ['system']] ])} `); export const manyLinesMessagSizing: StoryFn = createStory(html` - ${createMatrix(differentChatSizeConversationTestCase, [ - [ - [multiLineMessage], - ], - [ - ['outbound'], - ['inbound'], - ['system'] - ] + ${createMatrix(differentChatMessageSizeTestCase, [ + [[multiLineMessage]], + [['outbound'], ['inbound'], ['system']] + ])} +`); + +export const tinyConversationSizing: StoryFn = createStory(html` + ${createMatrix(differentChatConversationSizeTestCase, [[['a']]])} +`); + +export const extraWideConversationSizing: StoryFn = createStory(html` + ${createMatrix(differentChatConversationSizeTestCase, [[[loremIpsum]]])} +`); + +export const manyLinesConversationSizing: StoryFn = createStory(html` + ${createMatrix(differentChatConversationSizeTestCase, [ + [[multiLineMessage]] ])} `); From 4314626a719e1a09db5a982cfdfac493afd97706 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Tue, 4 Feb 2025 08:05:03 -0600 Subject: [PATCH 44/61] Fixed typo --- .../storybook/src/spright/chat/chat-message-matrix.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts index 4b17a46809..88a0dd0790 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts @@ -202,7 +202,7 @@ export const tinyMessageSizing: StoryFn = createStory(html` ])} `); -export const extraWideMessagSizing: StoryFn = createStory(html` +export const extraWideMessageSizing: StoryFn = createStory(html` ${createMatrix(differentChatMessageSizeTestCase, [ [[loremIpsum]], [['outbound'], ['inbound'], ['system']] From a9fce4d0be1734d4ded564fabb7f0df4db5800d7 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Wed, 5 Feb 2025 09:27:53 -0600 Subject: [PATCH 45/61] Implemented latest feedback. --- .../spright/chat/chat-conversation.react.tsx | 4 +++ ...trix.stories.ts => chat-matrix.stories.ts} | 31 ++++++++++--------- 2 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 packages/storybook/src/spright/chat/chat-conversation.react.tsx rename packages/storybook/src/spright/chat/{chat-message-matrix.stories.ts => chat-matrix.stories.ts} (96%) diff --git a/packages/storybook/src/spright/chat/chat-conversation.react.tsx b/packages/storybook/src/spright/chat/chat-conversation.react.tsx new file mode 100644 index 0000000000..1133d9aabb --- /dev/null +++ b/packages/storybook/src/spright/chat/chat-conversation.react.tsx @@ -0,0 +1,4 @@ +import { ChatConversation } from '../../../../spright-components/src/chat/conversation'; +import { wrap } from '../../utilities/react-wrapper'; + +export const SprightChatConversation = wrap(ChatConversation); diff --git a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-matrix.stories.ts similarity index 96% rename from packages/storybook/src/spright/chat/chat-message-matrix.stories.ts rename to packages/storybook/src/spright/chat/chat-matrix.stories.ts index 88a0dd0790..5c12d52f62 100644 --- a/packages/storybook/src/spright/chat/chat-message-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-matrix.stories.ts @@ -30,8 +30,6 @@ const metadata: Meta = { export default metadata; const multiLineMessage = ` --------------------------------------------------------------------- - Introduction to TestStand NI TestStand is a flexible and open test management framework for building, customizing, and deploying a full-featured test management system. @@ -149,13 +147,13 @@ Configuration entry points provide an interface for configuring the process mode Use the TestStand Deployment Utility to create a deployable image or a patch deployment of a TestStand system and an optional installer. The deployable image can contain sequence files, code modules, process models and supporting files, user interface applications, configuration files, and step types and supporting files the TestStand system uses. The installer can contain all files from a deployable image or contain only a subset of files to create a patch for a previously deployed image. You can also use the deployment utility to include the TestStand Engine and supporting files, LabVIEW and LabWindows/CVI Run-Time Engines, and hardware drivers in the installer you create. The installer that the deployment utility creates can also register ActiveX servers, replace existing files on the target computer, and create program shortcuts. You can configure the deployment utility to remove VI block diagrams or to lock the VIs you deploy. - ---------------------------------------------------------------------`; +`; const component = ([ chatMessageTypeName, messageType ]: ChatMessageTypeState): ViewTemplate => html` + <${chatMessageTag} message-type=${() => messageType} style="margin-right: 8px;"> @@ -166,26 +164,29 @@ const differentChatMessageSizeTestCase = ( [message]: [string], [messageType]: [string] ): ViewTemplate => html` - <${chatMessageTag} - message-type=${() => messageType} - style="margin-right: 8px;"> - <${richTextViewerTag} - :markdown="${_ => message}"> - </${richTextViewerTag} - </${chatMessageTag}> + <div style="margin: 10px 0px;"> + <${chatMessageTag} + message-type=${() => messageType} + style="outline: 1px dashed red;"> + <${richTextViewerTag} + :markdown="${_ => message}"> + </${richTextViewerTag} + </${chatMessageTag}> + </div> `; const differentChatConversationSizeTestCase = ([message]: [ string ]): ViewTemplate => html` - <${chatConversationTag}> - <${chatMessageTag} message-type='outbound' style="margin-right: 8px;"> + <${chatConversationTag} + style="width: 900px; height: 400px;"> + <${chatMessageTag} message-type='outbound' style="outline: 1px dashed red;"> <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> </${chatMessageTag}> - <${chatMessageTag} message-type='inbound' style="margin-right: 8px;"> + <${chatMessageTag} message-type='inbound' style="outline: 1px dashed red;"> <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> </${chatMessageTag}> - <${chatMessageTag} message-type='system' style="margin-right: 8px;"> + <${chatMessageTag} message-type='system' style="outline: 1px dashed red;"> <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> </${chatMessageTag}> </${chatConversationTag}> From 02f1468a18f2d4cafac8450902a7babc7a6a9be1 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Wed, 5 Feb 2025 18:13:24 -0600 Subject: [PATCH 46/61] More feedback --- packages/storybook/.storybook/main.js | 6 +- .../src/spright/chat/chat-matrix.stories.ts | 104 +----------------- .../src/spright/chat/chat.stories.ts | 3 + .../chat/images/VIConnectorPanelImage.png | Bin 0 -> 6506 bytes 4 files changed, 11 insertions(+), 102 deletions(-) create mode 100644 packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png diff --git a/packages/storybook/.storybook/main.js b/packages/storybook/.storybook/main.js index 4c7d545800..1034e5c86b 100644 --- a/packages/storybook/.storybook/main.js +++ b/packages/storybook/.storybook/main.js @@ -61,7 +61,11 @@ export function webpackFinal(config) { ]; return config; } -export const staticDirs = ['public']; +export const staticDirs = [ + 'public', + '../src/nimble', + '../src/spright' +]; export const framework = { name: '@storybook/html-webpack5' }; diff --git a/packages/storybook/src/spright/chat/chat-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-matrix.stories.ts index 5c12d52f62..0d82ce2004 100644 --- a/packages/storybook/src/spright/chat/chat-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-matrix.stories.ts @@ -34,42 +34,6 @@ Introduction to TestStand NI TestStand is a flexible and open test management framework for building, customizing, and deploying a full-featured test management system. -**Creating a TestStand-Based System** - -Creating a TestStand-based test solution is a process that includes designing the test system, developing test sequences for units under test (UUTs), customizing the TestStand framework, debugging the test sequences, and deploying the test system to test station computers. - -**Design** - -Learn about the components of the TestStand framework, learn how to use those features, and understand when to customize that behavior. Plan the system architecture of the proposed solution. Determine the development environments to use to develop user interfaces and code modules in the solution. Consider how to manage the development and deployment of the solution, including how to organize files under development, how to deploy the files, and how to debug and update systems you deploy. - -Refer to the section of this tutorial for more information about the components and features of TestStand and how to customize those features. Refer to the NI TestStand Advanced Architecture Series for more advanced concept and architecture information. This series is a suite of documents TestStand architects and developers created to provide more detailed information for experienced TestStand users with complex projects. - -**Develop** - -Write test sequences for use on a test station computer. A test sequence is a series of steps that initialize instruments, perform complex tests, or change the flow of executions. Use the sequence editor or a custom sequence editor to write and edit test sequences. - -**Customize** - -Edit the default behavior of the TestStand framework depending on the needs of the application you create. You can customize reporting, database logging, process models, callback sequences, and user interfaces to create a unique, robust test solution for an application. - -**Debug** - -Ensure that the test sequences and any customized features execute correctly before you deploy the test system. Use the TestStand Sequence Analyzer in the sequence editor or the stand-alone sequence analyzer application during development or before deployment to find errors and enforce custom development guidelines you establish. - -TestStand provides multiple features in the sequence editor or a custom sequence editor for debugging sequences, including tracing, breakpoints, conditional breakpoints, stepping through code, and watch expressions. The TestStand system development cycle is an iterative process, and you might have to debug an application multiple times. - -**Deploy** - -After you develop, customize, and debug a TestStand system, you can deploy the system to multiple test stations. The TestStand Deployment Utility simplifies the complex process of deploying a TestStand system by automating many of the steps involved, including collecting sequence files, code modules, configuration data for instruments, and support files for the test system. You can also use the deployment utility to create an installer or patch distributions. - -**Major Software Components of TestStand** - -The major software components of TestStand include the TestStand Engine, sequence editor, user interfaces, module adapters, process models, and deployment utility. - -**TestStand Engine** - -The TestStand Engine is a set of DLLs that exports an ActiveX Automation server API. The sequence editor and TestStand User Interfaces use the TestStand API, which you can call from any programming environment that supports access to ActiveX servers, including code modules you write in LabVIEW and LabWindows/CVI. The NI TestStand Help includes detailed documentation for the TestStand API. - **TestStand Sequence Editor** The sequence editor is a development environment in which you create, edit, execute, and debug sequences and the tests sequences call. Use the sequence editor to access all features, such as step types and process models. Refer to the Process Models section of this tutorial for more information about process models. @@ -86,67 +50,6 @@ You can debug a sequence using the following techniques, similar to how you debu In the sequence editor, you can start multiple concurrent executions, execute multiple instances of the same sequence, or execute different sequences at the same time. Each execution instance opens an Execution window. In Trace Mode, the Execution window shows the steps in the currently executing sequence. If the execution suspends, the Execution window shows the next step to execute and provides debugging options. In the sequence editor, you can fully customize the pane and tab layout to optimize development and debugging tasks. You can also customize the menus, toolbars, and keyboard shortcuts. - -**User Interfaces** - -A TestStand User Interface is an application you deploy to a development system or a production station to provide a custom GUI for executing, debugging, or editing sequences. Simple user interfaces might only support running sequences, and custom sequence editors might support editing, running, and debugging sequences. - -TestStand includes separate user interface applications developed in LabVIEW, LabWindows/CVI, Microsoft Visual Basic .NET Framework, C#, and C++ (MFC). Because TestStand also includes the source code for each user interface, you can fully customize the user interfaces. You can create a custom user interface using any programming language that can host ActiveX controls or control ActiveX Automation servers. - -TestStand ships with full-featured Custom Sequence Editor user interfaces. These interfaces can be found by default at C:/Users/Public/Documents/National Instruments/TestStand 20XX/UserInterfaces/Full-Featured/, or by navigating to **Start » All Programs » National Instruments » TestStand <Version> » User Interfaces** from the Windows Start Menu. - -With the user interfaces in Editor Mode, you can modify sequences and display sequence variables, sequence parameters, step properties, and so on. With the user interfaces in Operator Mode, you can start multiple concurrent executions, set breakpoints, and step through sequences. - -**Module Adapters** - -The TestStand Engine uses module adapters to invoke code modules that sequences call. A code module is a program module from an ADE or programming language and can contain one or more functions that perform a specific test or other action. Module adapters load and call code modules, pass parameters to code modules, and return values and status from code modules. The module adapters support the following types of code modules: - -- LabVIEW VIs -- LabWindows/CVI functions in DLLs you create in LabWindows/CVI or other compilers -- C/C++ functions in DLLs -- .NET assemblies -- ActiveX Automation servers -- HTBasic subroutines -- Python modules - -Adapters specific to an ADE can open the ADE, create source code for a new code module in the ADE, and display the source for an existing code module in the ADE. The adapters support stepping into the source code in the ADE while you execute the step from the TestStand Sequence Editor or a TestStand User Interface. - -TestStand includes the following module adapters: - -- LabVIEW Adapter—Calls LabVIEW VIs with a variety of connector panes. The VIs can exist in LLBs or in LabVIEW packed project libraries. You can also call VIs in the context of a LabVIEW project or call LabVIEW class member VIs. -- LabWindows/CVI Adapter—Calls C functions in a DLL with a variety of parameter types. -- C/C++ DLL Adapter—Calls C/C++ functions and static C++ class methods in a DLL with a variety of parameter types. You can call global static methods or static class methods in C++ DLLs. You can create the DLL code module with LabWindows/CVI, Visual Studio, or any other environment that can create a C/C++ DLL, including LabVIEW-built shared libraries. -.- NET Adapter—Calls .NET assemblies written in any .NET-compliant language, such as C# or Microsoft Visual Basic .NET. -- ActiveX/COM Adapter—Creates ActiveX/COM objects, calls methods, and accesses properties of those objects. When you create an object, you can assign the object reference to a variable or property for later use in other ActiveX/COM Adapter steps. -- Sequence Adapter—Calls a subsequence in the current sequence file, in another sequence file, or a sequence file on a remote system. You can also make recursive sequence calls. -- Python Adapter—Calls Python modules. - -Refer to the following tutorials for more information about using LabVIEW and LabWindows/CVI with TestStand. Refer to the NI TestStand Help for more information about using the LabVIEW and LabWindows/CVI Adapters. - -- Calling LabVIEW VIs -- Calling LabWindows/CVI Code Modules - -**Process Models** - -Testing a UUT requires more than just executing a set of tests. Usually, the test system must perform a series of operations before and after it executes the sequence that performs the tests. Common operations that define the testing process include identifying the UUT, notifying the operator of pass/fail status, logging results, and generating a report. The set of operations and the flow of execution is called a process model. A TestStand process model is a sequence file you can use to define standard testing operations so you do not have to re-implement the same operations in every sequence file you write. - -TestStand includes predefined Sequential, Parallel, and Batch models you can modify or replace. Use the Sequential model to run a test sequence on one UUT at a time. Use the Parallel and Batch models to run the same test sequence on multiple UUTs simultaneously. - -You can modify an existing TestStand process model or you can create a custom process model. The ability to modify a process model is essential because the testing process can vary depending on production lines, production sites, or company systems and practices. You can edit a process model in the same way you edit other sequence files. You can also use client sequence files to customize various model operations by overriding the callback sequences process models define. - -**Entry Points** - -A process model defines a set of entry points, and each entry point is a sequence in the process model file that invokes a test sequence file. Defining multiple entry points in a process model gives the test station operator different ways to invoke a Main sequence or configure the process model. - -Execution entry points in a process model provide different ways for the test station operator to invoke a Main sequence. Execution entry points handle common operations, such as UUT identification and report generation. For example, the default Sequential process model provides the Test UUTs and Single Pass Execution entry points. The Test UUTs Execution entry point initiates a loop that repeatedly identifies and tests UUTs. The Single Pass Execution entry point tests a single UUT without identifying it. - -Configuration entry points provide an interface for configuring the process model, typically through a GUI. For example, the default Batch model provides the Configure Model Options entry point. This entry point creates the Configure menu item. - -**TestStand Deployment Utility** - -Use the TestStand Deployment Utility to create a deployable image or a patch deployment of a TestStand system and an optional installer. The deployable image can contain sequence files, code modules, process models and supporting files, user interface applications, configuration files, and step types and supporting files the TestStand system uses. The installer can contain all files from a deployable image or contain only a subset of files to create a patch for a previously deployed image. - -You can also use the deployment utility to include the TestStand Engine and supporting files, LabVIEW and LabWindows/CVI Run-Time Engines, and hardware drivers in the installer you create. The installer that the deployment utility creates can also register ActiveX servers, replace existing files on the target computer, and create program shortcuts. You can configure the deployment utility to remove VI block diagrams or to lock the VIs you deploy. `; const component = ([ @@ -155,8 +58,7 @@ const component = ([ ]: ChatMessageTypeState): ViewTemplate => html` <${chatMessageTag} - message-type=${() => messageType} - style="margin-right: 8px;"> + message-type=${() => messageType}> ${() => `Message Type: ${chatMessageTypeName}`}</${chatMessageTag}> `; @@ -179,7 +81,7 @@ const differentChatConversationSizeTestCase = ([message]: [ string ]): ViewTemplate => html` <${chatConversationTag} - style="width: 900px; height: 400px;"> + style="width: 900px; height: 400px; margin: 0px 0px 5px 0px"> <${chatMessageTag} message-type='outbound' style="outline: 1px dashed red;"> <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> </${chatMessageTag}> @@ -210,7 +112,7 @@ export const extraWideMessageSizing: StoryFn = createStory(html` ])} `); -export const manyLinesMessagSizing: StoryFn = createStory(html` +export const manyLinesMessageSizing: StoryFn = createStory(html` ${createMatrix(differentChatMessageSizeTestCase, [ [[multiLineMessage]], [['outbound'], ['inbound'], ['system']] diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 814d72c978..c4b4b7c0de 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -37,6 +37,9 @@ export const chatConversation: StoryObj<ChatConversation> = { <${chatMessageTag} message-type='system'> <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> + <${chatMessageTag} message-type='inbound'> + <img src=/chat/images/VIConnectorPanelImage.png /> + </${chatMessageTag}> <${chatMessageTag} message-type='system'> <${buttonTag} appearance='block'>Order a tab</${buttonTag}> <${buttonTag} appearance='block'>Check core temperature</${buttonTag}> diff --git a/packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png b/packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png new file mode 100644 index 0000000000000000000000000000000000000000..1ea42f4c7e80f99102427eee175fd9dfd2b04144 GIT binary patch literal 6506 zcmaJ`XH*kgv_`L9L3$IVmkAwm5$R2uB=oAF6j6Hby(nS;LCVm(NE7KT6e&szktSUT z!UaMJ7)t2<#r4)*>-~B^X6BqTbLQ+b`#W>KZ|@j=T@A|H%(qEMNGRbjHA51TYj9%O zk@RokxyfKuka)S~ZK$C_QZ>wqBUWzME9)qekklrSpIhG~*2z3zX5J(uRNa4$Ybf_m zHY6l>ui$FR#sQZ2T<5SQ>G~*DI}@&Uw!w-QCH^EQe#45_+oQcDf7GNlEjL{j3$_4S zt5klU_>@LIl)r`QX-TG8Jw<u4mcG*(^JKLrNiSNK9wu4S^6GS3gF^A-B14atqFrAu zAL4`JJ;t+y?_rQhK}#xcJAs2s{b0NLL)#8F|7nLFznNh>C_bcJZd-2DFH9r2Mn}rZ zf{j;EbT73b6M1%4kvr<Q5Mt{*d00W!fLbjNWv}{RVR&YT42`8sO$u;xu8eqU2Ja9* zOYpxOo=xjsxad27imYx3T`gb0bIfw=?)AE!PKsJtVP=++H$H~G8aW<zFF$N5JD(<` zPQ|$HPF00n6)Za}gq?qAt5-jRpGfn~9y=xIB|rMD6z1_o;$o;lX(E4B>77-0Q~0Q? ztHt!cf?%ZnAzdgE&|yokH3#RaztBIR&DJ#R<=+f+<V>c8*YS1J12P$FiY~aw-XjYa z&cEUvl@t%t;f4UpH_vF~J#epQGCD^sBP70@LRmmD8GBiHp<H*nF4b_r_Dk^yX_*aE zKH<XTlUQe}FMl{gVHzMZo9zR)q)+<Q=E&lr!N|>L3r_5a0FL5{$pFq~%~iAgr*oc9 zq8h`t%)z`G$lc1zIC+kLKkL-ft&-j3?%oh?XA5_N*7BD}JXEH!=Uc81PL}%D3%)@n z%-xm+G*MnTzh%GsvwDry4cS1Ct-qbcB-mMe48$)thVDrk-z4MC1NtS_C}4E1DrRMv zL#h^({j?T2b%KdtR=Vxus=}yfYL!{f1h4t327?xW{)CMOO^Ij0*809<&|l*Xc~Uhp zRhggN7YC@><=mNl#_`yS6I~ScKx)5^sUf%f5Qi*BI@b&KLTBHeY+0Fd=+3!>T3jsl z;Fa;ODH<%J-^IrESg!8buw0a=;WPV?55LOIrmw>tSt)g-65mYm>>5O>f(&H6tu>Ya zc6Vmy$++B%lY2apakAR*<+YCLSrb)HM!44(TZ<NclMl5_0{cCJzC|ZK3MKaCW4(}T zvUUb`Aqwz*9mSF9vptC89Z@+>G!?BS!w0a>*{q7(wfI40lb$*#2-~0F|6~|RDxveX z$zth-FbwQ{<ePHCoRgwa{l!yitwj1aKO7W17cBuk_UYuo4PyZSKfH&wXDm#^jopW5 z9V*)i13mUCnq?_E8{4xi8zyQ22Cp=ktJB4rMQ75UR?|hMP4nnKGkrcbp!O_)l&ruh zD_RU**w&s0TzY;)E(W~k>%0waGRfE;96@5XNo(Oyo!;nwVx(bX72Vu{+5E+B{bw@{ z)o#;O#ZC8?1VQXZ#J<l}S+f&pEI_3N_7i4KFI`Zwa|l4-E*92~l-mbVMJ}8XzAIgu zy|H&aRUJ?VSi{B?NQ|sWNZjp&o(3^TSmSk*vJWD2m?S^8`6$8G8inO9FXcLzVK<qE zCf!oBuZ^us$E>|u)V^Zj2S!>8Jw#)G7KFMw*c6;KipA3h?asP^iTL7d?pp0Kz8Ni} zQDvuW&MI9GWsv6Hltn5KYSpf6_?<p-dU7EdP~_1I8#IMy`2w&D2%K=r?^^qGG?0Pd z@+njmG?q0(w0(I81QUKYY9#sX4i#BUy<uwsUYe#o)4EU9!X+M0ma;rb^_xE_;4$yY zAvh88W*_)ON6zQ1^vkOPpiPmLI*y9mFq)YOX&mW~qMu8PowEX&sW3%CPvT4Ivzurs z`Iu4<f1F0V!hT`y<A<|awdUmk4Q*x`5k>yC?}6ed<|;h|i`?-g3PuN9R|`G~hPgla zdek@#2z;DN242jMFuFJW^k#1dWIli44G@8EjJ$5}?+1HYanIK&>z#MiQust_qs)qg z;cnDa4+Uc#gj6nA$09y7S7riw_uTlpzZuSvf!g04gBvW%>=jWR;_U+2)jMWy3$Jf< zlxwc|fsy<)LlLFE^#B)h(abi9)1Ox!vNf5}aSIyqs5-GM{3=13zWz)qlV3CmWMb8e z9e8?_7o=`$BQS!MoLLQFy7l?~+$zECyVDwHwbU4Ueek&IehL+#4m_t58%1h%*}}J! z((oE{Q(04FHN0v<O^F(t<luXppii14e%f^81`zWXtQu-53>S@MW8Wa>6WjO&+4YQ( zav%iYB&bLqr~{50`eL8?gLiWnba~^ak*lEEBSzbTc&b!$=~^B`Ci2@%XQR4zVv00$ z6Kw{C4hUo_KSSP*%!XNl^QG^WUjaHNiB@3d(;3~T=DNte7pkbpm;|jh<z$pr`(M}b zu;~~GGQ9&j@K2w;l$#(}L;-M?(FgALQ8o(EW=y@@ShEq*cU09jx~F;X(k-!H8UB&q zCgtJ=|KXT}g0W?=UpGi$xH<bgk{=srSX;cg1;1aF@O^f{BVHFwRxK(YYvY=&mv=J7 z%hS+4*XtY6<n6m<9h~&?r;vY&&Gf+Uv;y|k)TBHh$nDzx-7`E_wFPYbCYyK>73|Vd z?!2g7W-R&lkqukvvOo|Rq_F3gAZMq#Uw9KIf4hB`4$(u0lfIef(2SRk_m&lfqdar2 znS=4m(tkArY$(saJ>atO%M|~DKCGyFUm-Z@c=1>NcccA(I^-Bcw6HB;d?n5B$^l-# zj^=@;>BT`wby1OO^ZEGBtDw}F6ej#yIAYTiE<4QMlBQpUmP#t>7`x7Kby*&2MLlA( z1^VO|EP)l??XGX0sGbvT88#*5^RLfn3fTO2b>xw*U#QM&g%fdFV7tmpe`dCv^0sfq zj$4VoWE(kO8&An7Q<7(`?b&Gu)pl%>FD^K=RqD>FZ}t-fz;>{lN&6h*G$|>*mz%MO zjBL7(@bhsu6%Ij}@*&1}bD9RIDtC2RFNTTVA=luaGnv9<?B>U-tCQ35j>{0X$txod zm8f(-gJeh?{b?c~PMfF}R^e}~#Pq#?;9k=1KpR%w>bQ*pD!6P26hdMJQ)0Hi*rC@Y zbSqh)mh~^n8{M-f7%kUr=iNRTW4e^Nt}Kg3xUBfl+8ID^^RJ!uFxEQ&alX_V>PHu& z^s?zo*WjA&{QKOEPZ;Oxe)c+VR~l;6UKa1eaN=YyZ&~lO{ur2)G$>R1u#G<-YRjbs z+9g~$V(#G!^O&axuy_MO*F_-OqO-8WcXTRw+OfyfaXMUIDkurCyA1h5n&v1K3cLkY z7k^`+(dD|u@s>~5XWETMoSMScuIiywngofq?N(e+Sn+*|r3BE%fxL?H(lXmQ65f6{ z?TSC7`qEz;0$-t?Ygdfa8Vi&j!6f$xxenDZwwFk=4yh*|%zvgJ2gvGsb~=KDq_OBI zOxAoVs<CUU%7cI0-RkKR-)731JPxyGH45Nn(Mb(Q{uk%0Hn*@Nzb49Eqx>a5Ipq&T zthKNNd6g%U-YKNuV~X`trW3dwujeF=U2T$2({+C)T3*OR6_F`16O6RAu+I3bYW{pc zYv$y0Kt12Qjac^z;XO<7#GRP#_t{djl6&8gwW<UgmXGhkz63<$L7$SIy?r28VCg@o z%d>97WncFFhxtJ1`DCBIxc|Vv=h4Q8i_6@Ed0`?KIESY3mLK!-E?PrT+l_t;+t_I| z9ebnp<4>pAuyf>(D}xM*Cy7|3>-tw$BwY^0gj-t1joiZ5z}4DS$L!U`)!`QTl!6X? z>DG^WA7nN>@roo=c&^&w2?(I=yewep*cL1(d?4&hH`x|7=IpEU43sV#8kbD|3JI(Q zMq?-51P+%B7SFsr+6?sC>C``}=V)@9_TJYXdQ!T09)}>5jU1*_%N1nd<GWY90xcWR zRo*O;52%wQIvk}~1@8Z<z_b)eq|{h-qBL?>ZDudyXORQab7>>aEy4yu;)OSZZLkBs zi#gHIQ_I5yq={%3XR|&TyM$0_>9d=j3h)m7yb7H{^FeLL0E7%XRNjQSgtmU{x9%yM z(lRT7Q1`Q;6BnSh{1|^5^#z|fYoE(QaL7-27IHaUBE$2d#p38L=h}q}%lOvuCu_nd zE6KATYo9~Y9}KFtJX`(}>AhWf_&e}${dwS}Cd+&Z#+Ro?2wEiC`;h(bXy^6LJM_0& z%9^D!(9|}88BbdbEi0fnxRa@uL8iacJ`-wO7vYi=*}Bg84qUFeJqc=o8xE4zYwqcW zyh1nN+?uv!Xdd$Pp2=k3GLG~Oi2=OH)BxdQVXfh4VE_i68EaNI#0d<pljUjELeXwQ zoVuknM%t`cKL_?cVQM2G4U{d^z1qSoW24SnV|X5G=2r2hhpD&UI&*+-h5HjUU%&7{ z(%aQZk32s)qS-gRSil$TB^f2*l;ZE-WWX}c@i=cBg681#NBx@$S;3Xhfm~u_yzMYE z&c+Nq|K5TcQ0u-(GUBGfj7A6RWb%a4Oi2r;@2I7gE2#oMx)#c$SqHQ~pt2R*`$uq0 zOUu5iETw!^0{=ZIw9P}03T(iSd_U;AKCQv_x0@DcZdT=Ejp7cLR~CU>K#UOpSAbHu z)8F>Ii+FilbyfY^=l4H&N2*k<z0Y$h%n%STsYx@Bi0b-&56mHjc>Xd0Q`?pw>22^p z0@bK#7}g?%X-Wh(5p}97D)X7xp;?o}r=00i1vNW4V9$ZlxKJd?OIZRHMZL)S#gJHM zPURPE?w-F^TH6GhXgIp|tNGQ7SS<D&e;3p&fi}uc@}Z)XO?Zj#g;AIV74YmYZ#c0l z1o7G?Ko`cU*WINrR!2jfvPl@LouxN%-RjT!p=k}7c#_w7-&{`znUpD1XTEUI@){t! z!;^d0lzEmGjOX%=L#cEx`f}-(cS-aH7(s4LUw_%saO<bg6ZF6dO=;jB*HL>EhQ5Fw z-5gro8KMWL6Mi(~XUDFl?NF}ZV!2xGr;c)BFO_omv8QQwyQ#+1=PHBA$8*g2%xTTN z0=p7o>c89fzAxP-C=Q4zQj`maSYuL#7-yWP-#149?i#y@A=;d0!!q&a;E{QW5E?T| zsRvnt4T~JP#61D!T@;te^1KIRG`u(SmJ50zj{jPFFCvDxi1#Do^ufg}UMp0CR3Y`p z&bRW7bNweW&X{mVsrL?L7D{cm=97*0j}lV-`;29p=Jr%H+QpsBK{8=<_;-BJ`dBau zxo7dAeKU?Z6&rmy6mH}0mZE^puNFnS$7y-}*46=29>vhDe@c}x2@-{`%{K$6VFt*F z3SI)o6&{`uA8^UGLe}k{UgYi0E(D*8Nn6m5&!64qavwAX%DfuLR}7R9s+IJ%3`Li0 z0-EVq)8>VQ77ohzIrq4CIuT5Zpz+`8#dX4@hD?_R4UEKxxW2EYU>hTSbZT3GPBKyS zv&87zh7Duj4mx6@^RJIYQ5m5{VD-Q%($ML#x(%$k4EMewb&6dKgowP;?>-LiAJ8HM zygb&iB^Xn&TjWIHe(dz<hG5@u=wK-xfrsM#UFhZavJmFVz4kL&$<?BXvB6I6?%Dev zRcra+r;0R%UP#UZ_lGIwM?B%zjlo3$a4vi&BsPduc!?g`;`1P`g&xoID&Sn7{n}i` zx-_}3?}#Dw<eLQzCxt_Uj^FnjU!ktqx@pSu-dn4STlpR2w3*^T_-TFWfMxj5ehGt# z#sH2y8-sVx+Zq+^Daj0&0R(52?IW?zA9n8j^vJV&c=0G_MdMzh{E~CNa#osrdb<Tu z9$H+b7mFo2qoH~|T94_}3$~nG))39v>0o83CMQ>@A@dZTMtA`ysIvRyl*O55WXREu z-KEnJcwbaF;$9yqn)8O%P<Tiz)23q5w@cPh!TJ(DEKTMBRip#8=9A;3JdNc~)*kXT z%DXn3-x`aH+~qIak|x!;T2af^O|lt_O}W`_5VJjU|AB&vo<YaW&=Tkj8R4NGZA2vN z2%~M?R`5seHXG9+!?wPL=Yhv_LBg=|L7hzPkOF#rib>}#IMgtWMGxlb$}0$$GanvD zd@sg&>k-^uW|ql|sg)31^eTm}D72;1rW+VS@v8343S2>8(Flr^F8p!4;NZ7T?G#b8 zJmt?tg1|u$!&-(7dZujPle}J~q;WMF-%2Su5^$_iC3s+>2Q96z)~zC?`Q#ti^Mb(* zkY5x!&HHAD=&s6G`s33Vb-Kya)lPRe#8gtGNu6;o`IshaiO4DpN;({g_8J3i0<qn$ zLLUlFAl_t|_j-c4<-DmLO>}!}GnW;#bx1``8!=CDJhgYcMC1P9f)8U#aF)zz=1MkV zh-2yS;%M4#0*$--9KUi+d$w%Q8;I_Ftg#UM#!#YsmC=}K71)P+Fo!%@9?Efiq3-*c zbL5iVK=&DVBi0}uDr?tu0DIlb@A$Tb{^VFp$}Ou`p55pdCFgL+Dr=mwpST>VsIOp< zWs;E(HxwyXGtBuUc#p`Cq`uxB4}72i-}n}ejmTC+OMK=@cjrQvdwkGXH)kZS%==8S z@4oy0${Y89Ur)y>c*1p4@|EoIojzlVFTVZQ6gE(fpWx9>qu(SFjg!*3DrczG<7iQI z>D$9radl2~%~?c4m&bnCVtugp;}rV|>!_o^v&(a`#p&sRZkpWy2yTv^m2von0sQjZ zZ0qJPuND|c@=?D2Tp<WN4iklI5C>#{(Y15rO!%xK`sH?OHY0i}r!SIiqS*y6cZsb2 zD@4YCT?AfnW)Q12*20&N4ut*4Jy#?I>=ea?UIzVkN$*y=uXIyxuA>R)6i>uTBQXAL zGRfz#km$8G>-_+D9=Vc;c;ge)Qq+b|A}(PVN+diid4`~d_(aLJ&=0hxVSZB{D`sWK z<)H?lfAP@YPQKff_%q_y0;9eLQNr?_=Lv=Wi=z*FRu<b>+1aoWYFzF>5hQ{4&RR;t zzn&^`YNcMsY_^rGvk)cvZ=n2`LqP~mJ~5iY*BK*a6(|k0=c^_iFYyf&xD&W*cw9kt zbs2oR&0Z^dz5oeSAkyLqNRkr`JRm1AK1zv&HkKXw_(7%*cC^DIP9%u_kq^DC$0sYl z7RrR{b_bCyYy+EJMh5QXjBMLx*@{oj9c*DJ@tFW^Fz8=%K9TdE1%Ww9OLy{TkvQdG zF_b3xw?{!P(NQ5URK!?&`@0$l^?@ROp<GrWX<7Mb-m*hU(Un+wbCO8s6_uw9Jmkq! z)80@5mnFe~O`aM+VVq-DJc!Lkn*ut1ucaF*W3MIJ{A62MfJ}8M&UJ|1io%qND!>sj z0*0AvV9`aK%UhXyyT2QTZ^i8UGdotQu;>2b)1AVUqxxQ2RJ-yRs?PX)q?}cBzn=h6 zs{WOt?u-%lbb#8`%yq%<GD&ivzkU~|_HJoNZ+11#3N(w=5vnK@Y%m8U^U3NNTrD+4 zbZQ2?20EqeAk(c6!tbnlnOzL%D}Cps-?_iC39jt}zMgQ)gwH^A#5>@R+~I9kG7I=f zUcZoZi-&=3%I}0{@aga(+rhd=+vJ9F^$2Wig8owjPCu){`Fs5pKO?-Pjy#dIqa7Fz zxmKw~U$=t>)mRBfkFjyDHayM*Kf#8R0K{5W^$kQ*N_dlFHb2Vt%dgShva#~1<jPHE zkU>Sy=a4N5Q(Pdngo|vtzWH`<Q4;;?uRu%UR3<X}^~%hXh2fymS~ot6Vy{5#N9zM5 z!*CQv@LL3s6#wRjn#}TI2ME-*bBIR)iX2<1yEU>bc2E{`(eVPA4S^wiMzym;v#WYW zdc7mtT-8qm&L9!^79nmyc!|Jp3ixxn_mnVBeFKv|aJ7HQT^r~Uel%XC5=ud?yEp1J z=)nT4jI}AiEpb~&Z<Z~&IbPGa`!{q~tp|&Ex~BtNR=Zul1`cks?ftVpnM~P~6jd#O zknd%Ys_l4?GicI++sIfN=oGev>t2iAjtS?(%^@(FUJ*6M)RYIEQsb$BSTCQO-Fj{- zkH&y&6lVNQaMbDJK0ezqq5^kb2DQT%qz?)R5`Urr-=Z+O@kAL!AqwY15!KP(9By(l zL~SNU6w0hbC3!cb8IS!FJop#9aZqZXNBh5Rl;+@_KcxylOI$R!9;o{jzGEJD%F?p~ zXeAmdj@U4j$j>ZC#=305hA?M3FD*rNA0)-<cV{DULzE|TpM8i!D@S2ydL-tTa}QxA zYTR{JT6xEdvH7`3dQ(m-C04$!=es!ZnLtbOu~xL;>53*OT&y7V$FhfD@%+CKt&~3- z-dn!U{k$3dkX|pX{QNCDZVsAR_=-6wK@56$LruYAG&dqry&2&6lTX<C8%vMq!`XIl zSvyK|xRswHA`uNC&6O)%;<IS;wCct{o_v-+;+cL+CyVPyjOc@iaW6q}kB1JEUXhtn y_j3p6;C62P6YF|W{|U!G>52anH8Ghz>@;jmmo!rA&n4zZNZ{(aYE>%FBmM`by}r%> literal 0 HcmV?d00001 From 75d40cff2ba68547d25d3bc4b1a862c1ba472941 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Wed, 5 Feb 2025 18:43:51 -0600 Subject: [PATCH 47/61] Added margins to chat messages in storybook matrix stories --- .../src/spright/chat/chat-matrix.stories.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-matrix.stories.ts index 0d82ce2004..458ce6fc58 100644 --- a/packages/storybook/src/spright/chat/chat-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-matrix.stories.ts @@ -66,15 +66,13 @@ const differentChatMessageSizeTestCase = ( [message]: [string], [messageType]: [string] ): ViewTemplate => html` - <div style="margin: 10px 0px;"> - <${chatMessageTag} - message-type=${() => messageType} - style="outline: 1px dashed red;"> - <${richTextViewerTag} - :markdown="${_ => message}"> - </${richTextViewerTag} - </${chatMessageTag}> - </div> + <${chatMessageTag} + message-type=${() => messageType} + style="outline: 1px dashed red; margin: 10px"> + <${richTextViewerTag} + :markdown="${_ => message}"> + </${richTextViewerTag} + </${chatMessageTag}> `; const differentChatConversationSizeTestCase = ([message]: [ From 1d879125fb7fa681cb4ff2f95128347cbc25e9ef Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Thu, 6 Feb 2025 08:18:46 -0600 Subject: [PATCH 48/61] Updating margins --- packages/storybook/src/spright/chat/chat-matrix.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/storybook/src/spright/chat/chat-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-matrix.stories.ts index 458ce6fc58..144bd606ab 100644 --- a/packages/storybook/src/spright/chat/chat-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-matrix.stories.ts @@ -68,7 +68,7 @@ const differentChatMessageSizeTestCase = ( ): ViewTemplate => html` <${chatMessageTag} message-type=${() => messageType} - style="outline: 1px dashed red; margin: 10px"> + style="outline: 1px dashed red; margin: 0px 20px 20px 0px"> <${richTextViewerTag} :markdown="${_ => message}"> </${richTextViewerTag} From 5956cd598c4d2ed7a906b5adcb672d19fee9b5af Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Thu, 6 Feb 2025 14:03:34 -0600 Subject: [PATCH 49/61] Removed usage of png file and started using svg image --- packages/storybook/.storybook/main.js | 6 +-- packages/storybook/src/spright/chat/chat.mdx | 5 +++ .../src/spright/chat/chat.stories.ts | 36 +++++++++++++++++- .../chat/images/VIConnectorPanelImage.png | Bin 6506 -> 0 bytes 4 files changed, 41 insertions(+), 6 deletions(-) delete mode 100644 packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png diff --git a/packages/storybook/.storybook/main.js b/packages/storybook/.storybook/main.js index 1034e5c86b..4c7d545800 100644 --- a/packages/storybook/.storybook/main.js +++ b/packages/storybook/.storybook/main.js @@ -61,11 +61,7 @@ export function webpackFinal(config) { ]; return config; } -export const staticDirs = [ - 'public', - '../src/nimble', - '../src/spright' -]; +export const staticDirs = ['public']; export const framework = { name: '@storybook/html-webpack5' }; diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index 0155967070..d1bc73e37d 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -44,6 +44,11 @@ Clients can place any HTML content within the message. <Canvas of={chatStories.chatMessageSpinner} /> +#### Image message content + +<Canvas of={chatStories.chatMessageImage} /> + + #### Prompt buttons message content <Canvas of={chatStories.chatMessagePrompts} /> diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index c4b4b7c0de..56578a8055 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -17,6 +17,18 @@ const metadata: Meta<ChatMessageTextArgs> = { const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; +// Vectors and icons by <a href="https://www.svgrepo.com" target="_blank">SVG Repo</a> +const svgImage = ` +<svg fill="#000000" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" +width="100px" height="100px" viewBox="0 0 225 256" xml:space="preserve"> +<path d="M91.6,18.2c12.5,0,22.6,10.1,22.6,22.6s-10.1,22.6-22.6,22.6S69,53.3,69,40.8S79.1,18.2,91.6,18.2z M211.6,119.2l-25.9-67.9 +l-0.1,0L199.1,5l-10.4-3l-26.7,91.5l10.4,3l8.2-28.3l17.1,44.1h-25.3v6.9h-25.9c0-0.1,0-0.2,0-0.3c0-6.7-4.9-12.5-11.6-12.5l-41.6,0 +c0,0-11.7-32.4-15.9-39.4c-3.3-5.4-8.4-8.8-15.1-8.8c-10.3,0-18.1,8.5-23.7,20.8c-9.3,20.4-13.3,45.5-11,68.6 +c1.1,9.4,3.4,17.3,8.9,21.8H18V96.6H2.3V254H18v-68.9h74.6l-10.4,51.6c-1.6,7.8,3.5,15.4,11.3,17c1,0.2,1.9,0.3,2.9,0.3 +c6.7,0,12.7-4.7,14.1-11.6l8.8-43.7l11.2,30.1c2.2,5.8,7.7,9.4,13.5,9.4c1.7,0,3.4-0.3,5-0.9c7.5-2.8,11.2-11.1,8.5-18.5l-24.4-65.5 +c-2.1-5.6-7.5-9.4-13.5-9.4H81v-9.1h126V254h15.7V119.2H211.6z"/> +</svg>`; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversation {} export const chatConversation: StoryObj<ChatConversation> = { @@ -38,7 +50,7 @@ export const chatConversation: StoryObj<ChatConversation> = { <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> <${chatMessageTag} message-type='inbound'> - <img src=/chat/images/VIConnectorPanelImage.png /> + <img src='data:image/svg+xml;utf8,${encodeURIComponent(svgImage)}'/> </${chatMessageTag}> <${chatMessageTag} message-type='system'> <${buttonTag} appearance='block'>Order a tab</${buttonTag}> @@ -147,6 +159,28 @@ export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { } }; +export const chatMessageImage: StoryObj<ChatMessageArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + <img src='data:image/svg+xml;utf8,${encodeURIComponent(svgImage)}'/> + </${chatMessageTag}> + `), + argTypes: { + messageType: { + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + messageType: ChatMessageType.inbound + } +}; + export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { parameters: { actions: {} diff --git a/packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png b/packages/storybook/src/spright/chat/images/VIConnectorPanelImage.png deleted file mode 100644 index 1ea42f4c7e80f99102427eee175fd9dfd2b04144..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6506 zcmaJ`XH*kgv_`L9L3$IVmkAwm5$R2uB=oAF6j6Hby(nS;LCVm(NE7KT6e&szktSUT z!UaMJ7)t2<#r4)*>-~B^X6BqTbLQ+b`#W>KZ|@j=T@A|H%(qEMNGRbjHA51TYj9%O zk@RokxyfKuka)S~ZK$C_QZ>wqBUWzME9)qekklrSpIhG~*2z3zX5J(uRNa4$Ybf_m zHY6l>ui$FR#sQZ2T<5SQ>G~*DI}@&Uw!w-QCH^EQe#45_+oQcDf7GNlEjL{j3$_4S zt5klU_>@LIl)r`QX-TG8Jw<u4mcG*(^JKLrNiSNK9wu4S^6GS3gF^A-B14atqFrAu zAL4`JJ;t+y?_rQhK}#xcJAs2s{b0NLL)#8F|7nLFznNh>C_bcJZd-2DFH9r2Mn}rZ zf{j;EbT73b6M1%4kvr<Q5Mt{*d00W!fLbjNWv}{RVR&YT42`8sO$u;xu8eqU2Ja9* zOYpxOo=xjsxad27imYx3T`gb0bIfw=?)AE!PKsJtVP=++H$H~G8aW<zFF$N5JD(<` zPQ|$HPF00n6)Za}gq?qAt5-jRpGfn~9y=xIB|rMD6z1_o;$o;lX(E4B>77-0Q~0Q? ztHt!cf?%ZnAzdgE&|yokH3#RaztBIR&DJ#R<=+f+<V>c8*YS1J12P$FiY~aw-XjYa z&cEUvl@t%t;f4UpH_vF~J#epQGCD^sBP70@LRmmD8GBiHp<H*nF4b_r_Dk^yX_*aE zKH<XTlUQe}FMl{gVHzMZo9zR)q)+<Q=E&lr!N|>L3r_5a0FL5{$pFq~%~iAgr*oc9 zq8h`t%)z`G$lc1zIC+kLKkL-ft&-j3?%oh?XA5_N*7BD}JXEH!=Uc81PL}%D3%)@n z%-xm+G*MnTzh%GsvwDry4cS1Ct-qbcB-mMe48$)thVDrk-z4MC1NtS_C}4E1DrRMv zL#h^({j?T2b%KdtR=Vxus=}yfYL!{f1h4t327?xW{)CMOO^Ij0*809<&|l*Xc~Uhp zRhggN7YC@><=mNl#_`yS6I~ScKx)5^sUf%f5Qi*BI@b&KLTBHeY+0Fd=+3!>T3jsl z;Fa;ODH<%J-^IrESg!8buw0a=;WPV?55LOIrmw>tSt)g-65mYm>>5O>f(&H6tu>Ya zc6Vmy$++B%lY2apakAR*<+YCLSrb)HM!44(TZ<NclMl5_0{cCJzC|ZK3MKaCW4(}T zvUUb`Aqwz*9mSF9vptC89Z@+>G!?BS!w0a>*{q7(wfI40lb$*#2-~0F|6~|RDxveX z$zth-FbwQ{<ePHCoRgwa{l!yitwj1aKO7W17cBuk_UYuo4PyZSKfH&wXDm#^jopW5 z9V*)i13mUCnq?_E8{4xi8zyQ22Cp=ktJB4rMQ75UR?|hMP4nnKGkrcbp!O_)l&ruh zD_RU**w&s0TzY;)E(W~k>%0waGRfE;96@5XNo(Oyo!;nwVx(bX72Vu{+5E+B{bw@{ z)o#;O#ZC8?1VQXZ#J<l}S+f&pEI_3N_7i4KFI`Zwa|l4-E*92~l-mbVMJ}8XzAIgu zy|H&aRUJ?VSi{B?NQ|sWNZjp&o(3^TSmSk*vJWD2m?S^8`6$8G8inO9FXcLzVK<qE zCf!oBuZ^us$E>|u)V^Zj2S!>8Jw#)G7KFMw*c6;KipA3h?asP^iTL7d?pp0Kz8Ni} zQDvuW&MI9GWsv6Hltn5KYSpf6_?<p-dU7EdP~_1I8#IMy`2w&D2%K=r?^^qGG?0Pd z@+njmG?q0(w0(I81QUKYY9#sX4i#BUy<uwsUYe#o)4EU9!X+M0ma;rb^_xE_;4$yY zAvh88W*_)ON6zQ1^vkOPpiPmLI*y9mFq)YOX&mW~qMu8PowEX&sW3%CPvT4Ivzurs z`Iu4<f1F0V!hT`y<A<|awdUmk4Q*x`5k>yC?}6ed<|;h|i`?-g3PuN9R|`G~hPgla zdek@#2z;DN242jMFuFJW^k#1dWIli44G@8EjJ$5}?+1HYanIK&>z#MiQust_qs)qg z;cnDa4+Uc#gj6nA$09y7S7riw_uTlpzZuSvf!g04gBvW%>=jWR;_U+2)jMWy3$Jf< zlxwc|fsy<)LlLFE^#B)h(abi9)1Ox!vNf5}aSIyqs5-GM{3=13zWz)qlV3CmWMb8e z9e8?_7o=`$BQS!MoLLQFy7l?~+$zECyVDwHwbU4Ueek&IehL+#4m_t58%1h%*}}J! z((oE{Q(04FHN0v<O^F(t<luXppii14e%f^81`zWXtQu-53>S@MW8Wa>6WjO&+4YQ( zav%iYB&bLqr~{50`eL8?gLiWnba~^ak*lEEBSzbTc&b!$=~^B`Ci2@%XQR4zVv00$ z6Kw{C4hUo_KSSP*%!XNl^QG^WUjaHNiB@3d(;3~T=DNte7pkbpm;|jh<z$pr`(M}b zu;~~GGQ9&j@K2w;l$#(}L;-M?(FgALQ8o(EW=y@@ShEq*cU09jx~F;X(k-!H8UB&q zCgtJ=|KXT}g0W?=UpGi$xH<bgk{=srSX;cg1;1aF@O^f{BVHFwRxK(YYvY=&mv=J7 z%hS+4*XtY6<n6m<9h~&?r;vY&&Gf+Uv;y|k)TBHh$nDzx-7`E_wFPYbCYyK>73|Vd z?!2g7W-R&lkqukvvOo|Rq_F3gAZMq#Uw9KIf4hB`4$(u0lfIef(2SRk_m&lfqdar2 znS=4m(tkArY$(saJ>atO%M|~DKCGyFUm-Z@c=1>NcccA(I^-Bcw6HB;d?n5B$^l-# zj^=@;>BT`wby1OO^ZEGBtDw}F6ej#yIAYTiE<4QMlBQpUmP#t>7`x7Kby*&2MLlA( z1^VO|EP)l??XGX0sGbvT88#*5^RLfn3fTO2b>xw*U#QM&g%fdFV7tmpe`dCv^0sfq zj$4VoWE(kO8&An7Q<7(`?b&Gu)pl%>FD^K=RqD>FZ}t-fz;>{lN&6h*G$|>*mz%MO zjBL7(@bhsu6%Ij}@*&1}bD9RIDtC2RFNTTVA=luaGnv9<?B>U-tCQ35j>{0X$txod zm8f(-gJeh?{b?c~PMfF}R^e}~#Pq#?;9k=1KpR%w>bQ*pD!6P26hdMJQ)0Hi*rC@Y zbSqh)mh~^n8{M-f7%kUr=iNRTW4e^Nt}Kg3xUBfl+8ID^^RJ!uFxEQ&alX_V>PHu& z^s?zo*WjA&{QKOEPZ;Oxe)c+VR~l;6UKa1eaN=YyZ&~lO{ur2)G$>R1u#G<-YRjbs z+9g~$V(#G!^O&axuy_MO*F_-OqO-8WcXTRw+OfyfaXMUIDkurCyA1h5n&v1K3cLkY z7k^`+(dD|u@s>~5XWETMoSMScuIiywngofq?N(e+Sn+*|r3BE%fxL?H(lXmQ65f6{ z?TSC7`qEz;0$-t?Ygdfa8Vi&j!6f$xxenDZwwFk=4yh*|%zvgJ2gvGsb~=KDq_OBI zOxAoVs<CUU%7cI0-RkKR-)731JPxyGH45Nn(Mb(Q{uk%0Hn*@Nzb49Eqx>a5Ipq&T zthKNNd6g%U-YKNuV~X`trW3dwujeF=U2T$2({+C)T3*OR6_F`16O6RAu+I3bYW{pc zYv$y0Kt12Qjac^z;XO<7#GRP#_t{djl6&8gwW<UgmXGhkz63<$L7$SIy?r28VCg@o z%d>97WncFFhxtJ1`DCBIxc|Vv=h4Q8i_6@Ed0`?KIESY3mLK!-E?PrT+l_t;+t_I| z9ebnp<4>pAuyf>(D}xM*Cy7|3>-tw$BwY^0gj-t1joiZ5z}4DS$L!U`)!`QTl!6X? z>DG^WA7nN>@roo=c&^&w2?(I=yewep*cL1(d?4&hH`x|7=IpEU43sV#8kbD|3JI(Q zMq?-51P+%B7SFsr+6?sC>C``}=V)@9_TJYXdQ!T09)}>5jU1*_%N1nd<GWY90xcWR zRo*O;52%wQIvk}~1@8Z<z_b)eq|{h-qBL?>ZDudyXORQab7>>aEy4yu;)OSZZLkBs zi#gHIQ_I5yq={%3XR|&TyM$0_>9d=j3h)m7yb7H{^FeLL0E7%XRNjQSgtmU{x9%yM z(lRT7Q1`Q;6BnSh{1|^5^#z|fYoE(QaL7-27IHaUBE$2d#p38L=h}q}%lOvuCu_nd zE6KATYo9~Y9}KFtJX`(}>AhWf_&e}${dwS}Cd+&Z#+Ro?2wEiC`;h(bXy^6LJM_0& z%9^D!(9|}88BbdbEi0fnxRa@uL8iacJ`-wO7vYi=*}Bg84qUFeJqc=o8xE4zYwqcW zyh1nN+?uv!Xdd$Pp2=k3GLG~Oi2=OH)BxdQVXfh4VE_i68EaNI#0d<pljUjELeXwQ zoVuknM%t`cKL_?cVQM2G4U{d^z1qSoW24SnV|X5G=2r2hhpD&UI&*+-h5HjUU%&7{ z(%aQZk32s)qS-gRSil$TB^f2*l;ZE-WWX}c@i=cBg681#NBx@$S;3Xhfm~u_yzMYE z&c+Nq|K5TcQ0u-(GUBGfj7A6RWb%a4Oi2r;@2I7gE2#oMx)#c$SqHQ~pt2R*`$uq0 zOUu5iETw!^0{=ZIw9P}03T(iSd_U;AKCQv_x0@DcZdT=Ejp7cLR~CU>K#UOpSAbHu z)8F>Ii+FilbyfY^=l4H&N2*k<z0Y$h%n%STsYx@Bi0b-&56mHjc>Xd0Q`?pw>22^p z0@bK#7}g?%X-Wh(5p}97D)X7xp;?o}r=00i1vNW4V9$ZlxKJd?OIZRHMZL)S#gJHM zPURPE?w-F^TH6GhXgIp|tNGQ7SS<D&e;3p&fi}uc@}Z)XO?Zj#g;AIV74YmYZ#c0l z1o7G?Ko`cU*WINrR!2jfvPl@LouxN%-RjT!p=k}7c#_w7-&{`znUpD1XTEUI@){t! z!;^d0lzEmGjOX%=L#cEx`f}-(cS-aH7(s4LUw_%saO<bg6ZF6dO=;jB*HL>EhQ5Fw z-5gro8KMWL6Mi(~XUDFl?NF}ZV!2xGr;c)BFO_omv8QQwyQ#+1=PHBA$8*g2%xTTN z0=p7o>c89fzAxP-C=Q4zQj`maSYuL#7-yWP-#149?i#y@A=;d0!!q&a;E{QW5E?T| zsRvnt4T~JP#61D!T@;te^1KIRG`u(SmJ50zj{jPFFCvDxi1#Do^ufg}UMp0CR3Y`p z&bRW7bNweW&X{mVsrL?L7D{cm=97*0j}lV-`;29p=Jr%H+QpsBK{8=<_;-BJ`dBau zxo7dAeKU?Z6&rmy6mH}0mZE^puNFnS$7y-}*46=29>vhDe@c}x2@-{`%{K$6VFt*F z3SI)o6&{`uA8^UGLe}k{UgYi0E(D*8Nn6m5&!64qavwAX%DfuLR}7R9s+IJ%3`Li0 z0-EVq)8>VQ77ohzIrq4CIuT5Zpz+`8#dX4@hD?_R4UEKxxW2EYU>hTSbZT3GPBKyS zv&87zh7Duj4mx6@^RJIYQ5m5{VD-Q%($ML#x(%$k4EMewb&6dKgowP;?>-LiAJ8HM zygb&iB^Xn&TjWIHe(dz<hG5@u=wK-xfrsM#UFhZavJmFVz4kL&$<?BXvB6I6?%Dev zRcra+r;0R%UP#UZ_lGIwM?B%zjlo3$a4vi&BsPduc!?g`;`1P`g&xoID&Sn7{n}i` zx-_}3?}#Dw<eLQzCxt_Uj^FnjU!ktqx@pSu-dn4STlpR2w3*^T_-TFWfMxj5ehGt# z#sH2y8-sVx+Zq+^Daj0&0R(52?IW?zA9n8j^vJV&c=0G_MdMzh{E~CNa#osrdb<Tu z9$H+b7mFo2qoH~|T94_}3$~nG))39v>0o83CMQ>@A@dZTMtA`ysIvRyl*O55WXREu z-KEnJcwbaF;$9yqn)8O%P<Tiz)23q5w@cPh!TJ(DEKTMBRip#8=9A;3JdNc~)*kXT z%DXn3-x`aH+~qIak|x!;T2af^O|lt_O}W`_5VJjU|AB&vo<YaW&=Tkj8R4NGZA2vN z2%~M?R`5seHXG9+!?wPL=Yhv_LBg=|L7hzPkOF#rib>}#IMgtWMGxlb$}0$$GanvD zd@sg&>k-^uW|ql|sg)31^eTm}D72;1rW+VS@v8343S2>8(Flr^F8p!4;NZ7T?G#b8 zJmt?tg1|u$!&-(7dZujPle}J~q;WMF-%2Su5^$_iC3s+>2Q96z)~zC?`Q#ti^Mb(* zkY5x!&HHAD=&s6G`s33Vb-Kya)lPRe#8gtGNu6;o`IshaiO4DpN;({g_8J3i0<qn$ zLLUlFAl_t|_j-c4<-DmLO>}!}GnW;#bx1``8!=CDJhgYcMC1P9f)8U#aF)zz=1MkV zh-2yS;%M4#0*$--9KUi+d$w%Q8;I_Ftg#UM#!#YsmC=}K71)P+Fo!%@9?Efiq3-*c zbL5iVK=&DVBi0}uDr?tu0DIlb@A$Tb{^VFp$}Ou`p55pdCFgL+Dr=mwpST>VsIOp< zWs;E(HxwyXGtBuUc#p`Cq`uxB4}72i-}n}ejmTC+OMK=@cjrQvdwkGXH)kZS%==8S z@4oy0${Y89Ur)y>c*1p4@|EoIojzlVFTVZQ6gE(fpWx9>qu(SFjg!*3DrczG<7iQI z>D$9radl2~%~?c4m&bnCVtugp;}rV|>!_o^v&(a`#p&sRZkpWy2yTv^m2von0sQjZ zZ0qJPuND|c@=?D2Tp<WN4iklI5C>#{(Y15rO!%xK`sH?OHY0i}r!SIiqS*y6cZsb2 zD@4YCT?AfnW)Q12*20&N4ut*4Jy#?I>=ea?UIzVkN$*y=uXIyxuA>R)6i>uTBQXAL zGRfz#km$8G>-_+D9=Vc;c;ge)Qq+b|A}(PVN+diid4`~d_(aLJ&=0hxVSZB{D`sWK z<)H?lfAP@YPQKff_%q_y0;9eLQNr?_=Lv=Wi=z*FRu<b>+1aoWYFzF>5hQ{4&RR;t zzn&^`YNcMsY_^rGvk)cvZ=n2`LqP~mJ~5iY*BK*a6(|k0=c^_iFYyf&xD&W*cw9kt zbs2oR&0Z^dz5oeSAkyLqNRkr`JRm1AK1zv&HkKXw_(7%*cC^DIP9%u_kq^DC$0sYl z7RrR{b_bCyYy+EJMh5QXjBMLx*@{oj9c*DJ@tFW^Fz8=%K9TdE1%Ww9OLy{TkvQdG zF_b3xw?{!P(NQ5URK!?&`@0$l^?@ROp<GrWX<7Mb-m*hU(Un+wbCO8s6_uw9Jmkq! z)80@5mnFe~O`aM+VVq-DJc!Lkn*ut1ucaF*W3MIJ{A62MfJ}8M&UJ|1io%qND!>sj z0*0AvV9`aK%UhXyyT2QTZ^i8UGdotQu;>2b)1AVUqxxQ2RJ-yRs?PX)q?}cBzn=h6 zs{WOt?u-%lbb#8`%yq%<GD&ivzkU~|_HJoNZ+11#3N(w=5vnK@Y%m8U^U3NNTrD+4 zbZQ2?20EqeAk(c6!tbnlnOzL%D}Cps-?_iC39jt}zMgQ)gwH^A#5>@R+~I9kG7I=f zUcZoZi-&=3%I}0{@aga(+rhd=+vJ9F^$2Wig8owjPCu){`Fs5pKO?-Pjy#dIqa7Fz zxmKw~U$=t>)mRBfkFjyDHayM*Kf#8R0K{5W^$kQ*N_dlFHb2Vt%dgShva#~1<jPHE zkU>Sy=a4N5Q(Pdngo|vtzWH`<Q4;;?uRu%UR3<X}^~%hXh2fymS~ot6Vy{5#N9zM5 z!*CQv@LL3s6#wRjn#}TI2ME-*bBIR)iX2<1yEU>bc2E{`(eVPA4S^wiMzym;v#WYW zdc7mtT-8qm&L9!^79nmyc!|Jp3ixxn_mnVBeFKv|aJ7HQT^r~Uel%XC5=ud?yEp1J z=)nT4jI}AiEpb~&Z<Z~&IbPGa`!{q~tp|&Ex~BtNR=Zul1`cks?ftVpnM~P~6jd#O zknd%Ys_l4?GicI++sIfN=oGev>t2iAjtS?(%^@(FUJ*6M)RYIEQsb$BSTCQO-Fj{- zkH&y&6lVNQaMbDJK0ezqq5^kb2DQT%qz?)R5`Urr-=Z+O@kAL!AqwY15!KP(9By(l zL~SNU6w0hbC3!cb8IS!FJop#9aZqZXNBh5Rl;+@_KcxylOI$R!9;o{jzGEJD%F?p~ zXeAmdj@U4j$j>ZC#=305hA?M3FD*rNA0)-<cV{DULzE|TpM8i!D@S2ydL-tTa}QxA zYTR{JT6xEdvH7`3dQ(m-C04$!=es!ZnLtbOu~xL;>53*OT&y7V$FhfD@%+CKt&~3- z-dn!U{k$3dkX|pX{QNCDZVsAR_=-6wK@56$LruYAG&dqry&2&6lTX<C8%vMq!`XIl zSvyK|xRswHA`uNC&6O)%;<IS;wCct{o_v-+;+cL+CyVPyjOc@iaW6q}kB1JEUXhtn y_j3p6;C62P6YF|W{|U!G>52anH8Ghz>@;jmmo!rA&n4zZNZ{(aYE>%FBmM`by}r%> From d798feb62460d47195ee791dad2ee10d3413d86e Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Fri, 7 Feb 2025 09:09:52 -0600 Subject: [PATCH 50/61] Fixed formatting --- packages/storybook/src/spright/chat/chat.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/chat.mdx index d1bc73e37d..87c7c20beb 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/chat.mdx @@ -48,7 +48,6 @@ Clients can place any HTML content within the message. <Canvas of={chatStories.chatMessageImage} /> - #### Prompt buttons message content <Canvas of={chatStories.chatMessagePrompts} /> From 3cbe591107a9de8784c35da9da0d5cffcb17b9b3 Mon Sep 17 00:00:00 2001 From: "Jose A. Hernandez" <jose.a.hernandez@ni.com> Date: Sat, 8 Feb 2025 19:10:54 -0600 Subject: [PATCH 51/61] Implemented Milan's feedback --- .../src/chat/message/index.ts | 2 +- .../src/chat/message/styles.ts | 4 +- .../src/chat/message/template.ts | 6 +-- .../chat/message/tests/chat-message.spec.ts | 2 +- .../src/chat/message/tests/types.spec.ts | 2 +- packages/spright-components/src/chat/types.ts | 4 +- .../src/spright/chat/chat-matrix.stories.ts | 52 +++++++++++++++---- 7 files changed, 51 insertions(+), 21 deletions(-) diff --git a/packages/spright-components/src/chat/message/index.ts b/packages/spright-components/src/chat/message/index.ts index 0645dcad5b..4662df59ee 100644 --- a/packages/spright-components/src/chat/message/index.ts +++ b/packages/spright-components/src/chat/message/index.ts @@ -21,7 +21,7 @@ export class ChatMessage extends FoundationElement { * HTML Attribute: message-type */ @attr({ attribute: 'message-type' }) - public readonly messageType: ChatMessageType = ChatMessageType.outbound; + public readonly messageType: ChatMessageType = ChatMessageType.system; } const sprightChatMessage = ChatMessage.compose({ diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 739b273f76..6edfa8e347 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -19,6 +19,8 @@ export const styles = css` flex-direction: row; justify-content: center; flex-shrink: 0; + font: ${bodyFont}; + color: ${bodyFontColor}; } :host([message-type='outbound']) { @@ -34,8 +36,6 @@ export const styles = css` width: fit-content; height: fit-content; padding: ${mediumPadding}; - font: ${bodyFont}; - color: ${bodyFontColor}; } :host([message-type='outbound']) div { diff --git a/packages/spright-components/src/chat/message/template.ts b/packages/spright-components/src/chat/message/template.ts index a746e3567e..4fd932c759 100644 --- a/packages/spright-components/src/chat/message/template.ts +++ b/packages/spright-components/src/chat/message/template.ts @@ -3,9 +3,5 @@ import type { ChatMessage } from '.'; /* eslint-disable @typescript-eslint/indent */ // prettier-ignore -export const template = html<ChatMessage>` - <div> - <slot></slot> - </div> -`; +export const template = html<ChatMessage>`<div><slot></slot></div>`; /* eslint-enable @typescript-eslint/indent */ diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index d088feb6f7..29240eb86b 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -38,6 +38,6 @@ describe('ChatMessage', () => { it("should initialize 'message-type' to default", async () => { await connect(); - expect(element.messageType).toBe(ChatMessageType.outbound); + expect(element.messageType).toBe(ChatMessageType.system); }); }); diff --git a/packages/spright-components/src/chat/message/tests/types.spec.ts b/packages/spright-components/src/chat/message/tests/types.spec.ts index d4b72f973f..87779a1cda 100644 --- a/packages/spright-components/src/chat/message/tests/types.spec.ts +++ b/packages/spright-components/src/chat/message/tests/types.spec.ts @@ -4,6 +4,6 @@ describe('ChatMessage message type', () => { it('ChatMessageType fails compile if assigning arbitrary string values', () => { // @ts-expect-error This expect will fail if the enum-like type is missing "as const" const messageType: ChatMessageType = 'hello'; - expect(messageType).toEqual('hello'); + expect(messageType!).toEqual('hello'); }); }); diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/types.ts index 67846dfcb6..e332d86832 100644 --- a/packages/spright-components/src/chat/types.ts +++ b/packages/spright-components/src/chat/types.ts @@ -3,9 +3,9 @@ * @public */ export const ChatMessageType = { + system: undefined, outbound: 'outbound', - inbound: 'inbound', - system: 'system' + inbound: 'inbound' } as const; export type ChatMessageType = diff --git a/packages/storybook/src/spright/chat/chat-matrix.stories.ts b/packages/storybook/src/spright/chat/chat-matrix.stories.ts index 144bd606ab..023f248b99 100644 --- a/packages/storybook/src/spright/chat/chat-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/chat-matrix.stories.ts @@ -12,6 +12,7 @@ import { hiddenWrapper } from '../../utilities/hidden'; import { loremIpsum } from '../../utilities/lorem-ipsum'; import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; +import { textCustomizationWrapper } from '../../utilities/text-customization'; const chatMessageTypes = [ ['outbound', ChatMessageType.outbound], @@ -21,7 +22,7 @@ const chatMessageTypes = [ type ChatMessageTypeState = (typeof chatMessageTypes)[number]; const metadata: Meta = { - title: 'Tests Spright/Chat Message', + title: 'Tests Spright/Chat', parameters: { ...sharedMatrixParameters() } @@ -75,6 +76,20 @@ const differentChatMessageSizeTestCase = ( </${chatMessageTag}> `; +const messageWithFixSizeTestCase = ( + [message]: [string], + [messageType]: [string] +): ViewTemplate => html` + <${chatMessageTag} + message-type=${() => messageType} + style="outline: 1px dashed red; margin: 0px 20px 20px 0px"> + <${richTextViewerTag} + style="width: 400px; height: 80px;" + :markdown="${_ => message}"> + </${richTextViewerTag} + </${chatMessageTag}> +`; + const differentChatConversationSizeTestCase = ([message]: [ string ]): ViewTemplate => html` @@ -92,47 +107,66 @@ const differentChatConversationSizeTestCase = ([message]: [ </${chatConversationTag}> `; -export const chatMessageThemeMatrix: StoryFn = createMatrixThemeStory( +export const messageThemeMatrix: StoryFn = createMatrixThemeStory( createMatrix(component, [chatMessageTypes]) ); -export const tinyMessageSizing: StoryFn = createStory(html` +export const messageTinySizing: StoryFn = createStory(html` ${createMatrix(differentChatMessageSizeTestCase, [ [['a']], [['outbound'], ['inbound'], ['system']] ])} `); -export const extraWideMessageSizing: StoryFn = createStory(html` +export const messageExtraWideSizing: StoryFn = createStory(html` ${createMatrix(differentChatMessageSizeTestCase, [ [[loremIpsum]], [['outbound'], ['inbound'], ['system']] ])} `); -export const manyLinesMessageSizing: StoryFn = createStory(html` +export const messageWithFixedSizeSizing: StoryFn = createStory(html` + ${createMatrix(messageWithFixSizeTestCase, [ + [[loremIpsum]], + [['outbound'], ['inbound'], ['system']] + ])} +`); + +export const messageManyLinesSizing: StoryFn = createStory(html` ${createMatrix(differentChatMessageSizeTestCase, [ [[multiLineMessage]], [['outbound'], ['inbound'], ['system']] ])} `); -export const tinyConversationSizing: StoryFn = createStory(html` +export const conversationTinySizing: StoryFn = createStory(html` ${createMatrix(differentChatConversationSizeTestCase, [[['a']]])} `); -export const extraWideConversationSizing: StoryFn = createStory(html` +export const conversationExtraWideSizing: StoryFn = createStory(html` ${createMatrix(differentChatConversationSizeTestCase, [[[loremIpsum]]])} `); -export const manyLinesConversationSizing: StoryFn = createStory(html` +export const conversationManyLinesSizing: StoryFn = createStory(html` ${createMatrix(differentChatConversationSizeTestCase, [ [[multiLineMessage]] ])} `); -export const hiddenChatMessage: StoryFn = createStory( +export const messageHidden: StoryFn = createStory( hiddenWrapper( html`<${chatMessageTag} hidden>Hidden Chat Message</${chatMessageTag}>` ) ); + +export const conversationHidden: StoryFn = createStory( + hiddenWrapper( + html`<${chatConversationTag} hidden>Hidden Chat Conversation</${chatConversationTag}>` + ) +); + +export const messageTextCustomized: StoryFn = createMatrixThemeStory( + textCustomizationWrapper( + html`<${chatMessageTag}>Message</${chatMessageTag}>` + ) +); From ab06456dd4c587fc00e68bdaf7041543f4368272 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Mon, 10 Feb 2025 16:43:05 -0600 Subject: [PATCH 52/61] Use nimble icon svg --- .../src/spright/chat/chat.stories.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/chat.stories.ts index 56578a8055..71fa347550 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/chat.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; +import { webviCustom16X16 } from '../../../../nimble-tokens/dist/icons/js'; import { buttonTag } from '../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../spright-components/src/chat/message'; @@ -17,17 +18,10 @@ const metadata: Meta<ChatMessageTextArgs> = { const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; -// Vectors and icons by <a href="https://www.svgrepo.com" target="_blank">SVG Repo</a> -const svgImage = ` -<svg fill="#000000" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" -width="100px" height="100px" viewBox="0 0 225 256" xml:space="preserve"> -<path d="M91.6,18.2c12.5,0,22.6,10.1,22.6,22.6s-10.1,22.6-22.6,22.6S69,53.3,69,40.8S79.1,18.2,91.6,18.2z M211.6,119.2l-25.9-67.9 -l-0.1,0L199.1,5l-10.4-3l-26.7,91.5l10.4,3l8.2-28.3l17.1,44.1h-25.3v6.9h-25.9c0-0.1,0-0.2,0-0.3c0-6.7-4.9-12.5-11.6-12.5l-41.6,0 -c0,0-11.7-32.4-15.9-39.4c-3.3-5.4-8.4-8.8-15.1-8.8c-10.3,0-18.1,8.5-23.7,20.8c-9.3,20.4-13.3,45.5-11,68.6 -c1.1,9.4,3.4,17.3,8.9,21.8H18V96.6H2.3V254H18v-68.9h74.6l-10.4,51.6c-1.6,7.8,3.5,15.4,11.3,17c1,0.2,1.9,0.3,2.9,0.3 -c6.7,0,12.7-4.7,14.1-11.6l8.8-43.7l11.2,30.1c2.2,5.8,7.7,9.4,13.5,9.4c1.7,0,3.4-0.3,5-0.9c7.5-2.8,11.2-11.1,8.5-18.5l-24.4-65.5 -c-2.1-5.6-7.5-9.4-13.5-9.4H81v-9.1h126V254h15.7V119.2H211.6z"/> -</svg>`; +const imgBlob = new Blob([webviCustom16X16.data], { + type: 'image/svg+xml' +}); +const imgBlobUrl = URL.createObjectURL(imgBlob); // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversation {} @@ -50,7 +44,7 @@ export const chatConversation: StoryObj<ChatConversation> = { <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> <${chatMessageTag} message-type='inbound'> - <img src='data:image/svg+xml;utf8,${encodeURIComponent(svgImage)}'/> + <img width="100" height="100" :src=${() => imgBlobUrl}> </${chatMessageTag}> <${chatMessageTag} message-type='system'> <${buttonTag} appearance='block'>Order a tab</${buttonTag}> @@ -165,7 +159,7 @@ export const chatMessageImage: StoryObj<ChatMessageArgs> = { }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> - <img src='data:image/svg+xml;utf8,${encodeURIComponent(svgImage)}'/> + <img width="100" height="100" :src=${() => imgBlobUrl}> </${chatMessageTag}> `), argTypes: { From 8dd5207d5119d53f57c7882b645a97e9a80563cd Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:00:34 -0600 Subject: [PATCH 53/61] Consistent chat-conversation naming --- .../spright/chat/chat-conversation.react.tsx | 4 --- .../src/spright/chat/chat-message.react.tsx | 4 --- .../chat-conversation-matrix.stories.ts} | 28 +++++++++---------- .../chat-conversation.mdx} | 8 +++--- .../conversation/chat-conversation.react.tsx | 4 +++ .../chat-conversation.stories.ts} | 18 ++++++------ .../chat/message/chat-message.react.tsx | 4 +++ 7 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 packages/storybook/src/spright/chat/chat-conversation.react.tsx delete mode 100644 packages/storybook/src/spright/chat/chat-message.react.tsx rename packages/storybook/src/spright/chat/{chat-matrix.stories.ts => conversation/chat-conversation-matrix.stories.ts} (89%) rename packages/storybook/src/spright/chat/{chat.mdx => conversation/chat-conversation.mdx} (85%) create mode 100644 packages/storybook/src/spright/chat/conversation/chat-conversation.react.tsx rename packages/storybook/src/spright/chat/{chat.stories.ts => conversation/chat-conversation.stories.ts} (90%) create mode 100644 packages/storybook/src/spright/chat/message/chat-message.react.tsx diff --git a/packages/storybook/src/spright/chat/chat-conversation.react.tsx b/packages/storybook/src/spright/chat/chat-conversation.react.tsx deleted file mode 100644 index 1133d9aabb..0000000000 --- a/packages/storybook/src/spright/chat/chat-conversation.react.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ChatConversation } from '../../../../spright-components/src/chat/conversation'; -import { wrap } from '../../utilities/react-wrapper'; - -export const SprightChatConversation = wrap(ChatConversation); diff --git a/packages/storybook/src/spright/chat/chat-message.react.tsx b/packages/storybook/src/spright/chat/chat-message.react.tsx deleted file mode 100644 index 7ce30eba84..0000000000 --- a/packages/storybook/src/spright/chat/chat-message.react.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ChatMessage } from '../../../../spright-components/src/chat/message'; -import { wrap } from '../../utilities/react-wrapper'; - -export const SprightChatMessage = wrap(ChatMessage); diff --git a/packages/storybook/src/spright/chat/chat-matrix.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts similarity index 89% rename from packages/storybook/src/spright/chat/chat-matrix.stories.ts rename to packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts index 023f248b99..1921374fbf 100644 --- a/packages/storybook/src/spright/chat/chat-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts @@ -1,18 +1,18 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; -import { chatMessageTag } from '../../../../spright-components/src/chat/message'; -import { ChatMessageType } from '../../../../spright-components/src/chat/types'; +import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; +import { ChatMessageType } from '../../../../../spright-components/src/chat/types'; import { createMatrix, sharedMatrixParameters, createMatrixThemeStory -} from '../../utilities/matrix'; -import { createStory } from '../../utilities/storybook'; -import { hiddenWrapper } from '../../utilities/hidden'; -import { loremIpsum } from '../../utilities/lorem-ipsum'; -import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; -import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; -import { textCustomizationWrapper } from '../../utilities/text-customization'; +} from '../../../utilities/matrix'; +import { createStory } from '../../../utilities/storybook'; +import { hiddenWrapper } from '../../../utilities/hidden'; +import { loremIpsum } from '../../../utilities/lorem-ipsum'; +import { richTextViewerTag } from '@ni/nimble-components/src/rich-text/viewer'; +import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; +import { textCustomizationWrapper } from '../../../utilities/text-customization'; const chatMessageTypes = [ ['outbound', ChatMessageType.outbound], @@ -22,7 +22,7 @@ const chatMessageTypes = [ type ChatMessageTypeState = (typeof chatMessageTypes)[number]; const metadata: Meta = { - title: 'Tests Spright/Chat', + title: 'Tests Spright/Chat Conversation', parameters: { ...sharedMatrixParameters() } @@ -153,15 +153,15 @@ export const conversationManyLinesSizing: StoryFn = createStory(html` ])} `); -export const messageHidden: StoryFn = createStory( +export const conversationHidden: StoryFn = createStory( hiddenWrapper( - html`<${chatMessageTag} hidden>Hidden Chat Message</${chatMessageTag}>` + html`<${chatConversationTag} hidden>Hidden Chat Conversation</${chatConversationTag}>` ) ); -export const conversationHidden: StoryFn = createStory( +export const messageHidden: StoryFn = createStory( hiddenWrapper( - html`<${chatConversationTag} hidden>Hidden Chat Conversation</${chatConversationTag}>` + html`<${chatMessageTag} hidden>Hidden Chat Message</${chatMessageTag}>` ) ); diff --git a/packages/storybook/src/spright/chat/chat.mdx b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx similarity index 85% rename from packages/storybook/src/spright/chat/chat.mdx rename to packages/storybook/src/spright/chat/conversation/chat-conversation.mdx index 87c7c20beb..daa5c9e51f 100644 --- a/packages/storybook/src/spright/chat/chat.mdx +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx @@ -1,8 +1,8 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; -import * as chatStories from './chat.stories'; -import ComponentApisLink from '../../docs/component-apis-link.mdx'; -import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; -import { chatMessageTag } from '../../../../spright-components/src/chat/message'; +import * as chatStories from './chat-conversation.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; +import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; +import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; <Meta of={chatStories} /> <Title of={chatStories} /> diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.react.tsx b/packages/storybook/src/spright/chat/conversation/chat-conversation.react.tsx new file mode 100644 index 0000000000..a470c8d309 --- /dev/null +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.react.tsx @@ -0,0 +1,4 @@ +import { ChatConversation } from '../../../../../spright-components/src/chat/conversation'; +import { wrap } from '../../../utilities/react-wrapper'; + +export const SprightChatConversation = wrap(ChatConversation); diff --git a/packages/storybook/src/spright/chat/chat.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts similarity index 90% rename from packages/storybook/src/spright/chat/chat.stories.ts rename to packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts index 71fa347550..6fce7164a4 100644 --- a/packages/storybook/src/spright/chat/chat.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts @@ -1,19 +1,19 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { webviCustom16X16 } from '../../../../nimble-tokens/dist/icons/js'; -import { buttonTag } from '../../../../nimble-components/src/button'; -import { chatConversationTag } from '../../../../spright-components/src/chat/conversation'; -import { chatMessageTag } from '../../../../spright-components/src/chat/message'; -import { ChatMessageType } from '../../../../spright-components/src/chat/types'; -import { richTextViewerTag } from '../../../../nimble-components/src/rich-text/viewer'; -import { spinnerTag } from '../../../../nimble-components/src/spinner'; +import { webviCustom16X16 } from '@ni/nimble-tokens/dist/icons/js'; +import { buttonTag } from '@ni/nimble-components/src/button'; +import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; +import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; +import { ChatMessageType } from '../../../../../spright-components/src/chat/types'; +import { richTextViewerTag } from '@ni/nimble-components/src/rich-text/viewer'; +import { spinnerTag } from '@ni/nimble-components/src/spinner'; import { apiCategory, createUserSelectedThemeStory -} from '../../utilities/storybook'; +} from '../../../utilities/storybook'; const metadata: Meta<ChatMessageTextArgs> = { - title: 'Spright/Chat' + title: 'Spright/Chat Conversation' }; const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; diff --git a/packages/storybook/src/spright/chat/message/chat-message.react.tsx b/packages/storybook/src/spright/chat/message/chat-message.react.tsx new file mode 100644 index 0000000000..94aa54de05 --- /dev/null +++ b/packages/storybook/src/spright/chat/message/chat-message.react.tsx @@ -0,0 +1,4 @@ +import { ChatMessage } from '../../../../../spright-components/src/chat/message'; +import { wrap } from '../../../utilities/react-wrapper'; + +export const SprightChatMessage = wrap(ChatMessage); From ab15b5b345d30d891caa38958b7bf2ff352038f8 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:01:12 -0600 Subject: [PATCH 54/61] Enable overflow on message content --- packages/spright-components/src/chat/conversation/styles.ts | 2 +- packages/spright-components/src/chat/message/styles.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/spright-components/src/chat/conversation/styles.ts b/packages/spright-components/src/chat/conversation/styles.ts index e87cfdde11..800d5c7f6e 100644 --- a/packages/spright-components/src/chat/conversation/styles.ts +++ b/packages/spright-components/src/chat/conversation/styles.ts @@ -15,6 +15,6 @@ export const styles = css` row-gap: ${standardPadding}; padding: ${mediumPadding}; background: ${applicationBackgroundColor}; - overflow-y: scroll; + overflow-y: auto; } `; diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 6edfa8e347..67b7e56ded 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -21,6 +21,7 @@ export const styles = css` flex-shrink: 0; font: ${bodyFont}; color: ${bodyFontColor}; + overflow-x: auto; } :host([message-type='outbound']) { From df6e01ac657fd854a59718cd7f634aadceea258b Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:01:21 -0600 Subject: [PATCH 55/61] Make message stories internal --- .../src/chat/message/index.ts | 2 +- .../chat/message/tests/chat-message.spec.ts | 2 +- .../src/chat/message/tests/types.spec.ts | 2 +- .../src/chat/{ => message}/types.ts | 0 .../chat-conversation-matrix.stories.ts | 2 +- .../chat/conversation/chat-conversation.mdx | 23 +-- .../conversation/chat-conversation.stories.ts | 158 +----------------- .../chat/conversation/story-helpers.ts | 8 + .../chat/message/chat-message.stories.ts | 153 +++++++++++++++++ 9 files changed, 186 insertions(+), 164 deletions(-) rename packages/spright-components/src/chat/{ => message}/types.ts (100%) create mode 100644 packages/storybook/src/spright/chat/conversation/story-helpers.ts create mode 100644 packages/storybook/src/spright/chat/message/chat-message.stories.ts diff --git a/packages/spright-components/src/chat/message/index.ts b/packages/spright-components/src/chat/message/index.ts index 4662df59ee..356a986af4 100644 --- a/packages/spright-components/src/chat/message/index.ts +++ b/packages/spright-components/src/chat/message/index.ts @@ -2,7 +2,7 @@ import { attr } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import { ChatMessageType } from '../types'; +import { ChatMessageType } from './types'; declare global { interface HTMLElementTagNameMap { diff --git a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts index 29240eb86b..3350280ad2 100644 --- a/packages/spright-components/src/chat/message/tests/chat-message.spec.ts +++ b/packages/spright-components/src/chat/message/tests/chat-message.spec.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; import { ChatMessage, chatMessageTag } from '..'; import { fixture, type Fixture } from '../../../utilities/tests/fixture'; -import { ChatMessageType } from '../../types'; +import { ChatMessageType } from '../types'; async function setup(): Promise<Fixture<ChatMessage>> { return await fixture<ChatMessage>( diff --git a/packages/spright-components/src/chat/message/tests/types.spec.ts b/packages/spright-components/src/chat/message/tests/types.spec.ts index 87779a1cda..7f98d4735e 100644 --- a/packages/spright-components/src/chat/message/tests/types.spec.ts +++ b/packages/spright-components/src/chat/message/tests/types.spec.ts @@ -1,4 +1,4 @@ -import type { ChatMessageType } from '../../types'; +import type { ChatMessageType } from '../types'; describe('ChatMessage message type', () => { it('ChatMessageType fails compile if assigning arbitrary string values', () => { diff --git a/packages/spright-components/src/chat/types.ts b/packages/spright-components/src/chat/message/types.ts similarity index 100% rename from packages/spright-components/src/chat/types.ts rename to packages/spright-components/src/chat/message/types.ts diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts index 1921374fbf..2e99204d37 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts @@ -1,7 +1,7 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; -import { ChatMessageType } from '../../../../../spright-components/src/chat/types'; +import { ChatMessageType } from '../../../../../spright-components/src/chat/message/types'; import { createMatrix, sharedMatrixParameters, diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx index daa5c9e51f..0613d95bc8 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx @@ -1,11 +1,12 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; -import * as chatStories from './chat-conversation.stories'; +import * as conversationStories from './chat-conversation.stories'; +import * as messageStories from '../message/chat-message.stories'; import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; -<Meta of={chatStories} /> -<Title of={chatStories} /> +<Meta of={conversationStories} /> +<Title of={conversationStories} /> Chat components are used to display a conversation with a chat bot or other users. The components can display messages but the application is responsible @@ -23,8 +24,8 @@ of messages. Use the <Tag name={chatConversationTag} /> element to display a series of messages in a conversation. -<Canvas of={chatStories.chatConversation} /> -<Controls of={chatStories.chatConversation} /> +<Canvas of={conversationStories.chatConversation} /> +<Controls of={conversationStories.chatConversation} /> ### Chat message @@ -33,24 +34,24 @@ Clients can place any HTML content within the message. #### Text message content -<Canvas of={chatStories.chatMessageText} /> -<Controls of={chatStories.chatMessageText} /> +<Canvas of={messageStories.chatMessageText} /> +<Controls of={messageStories.chatMessageText} /> #### Rich text message content -<Canvas of={chatStories.chatMessageRichText} /> +<Canvas of={messageStories.chatMessageRichText} /> #### Spinner message content -<Canvas of={chatStories.chatMessageSpinner} /> +<Canvas of={messageStories.chatMessageSpinner} /> #### Image message content -<Canvas of={chatStories.chatMessageImage} /> +<Canvas of={messageStories.chatMessageImage} /> #### Prompt buttons message content -<Canvas of={chatStories.chatMessagePrompts} /> +<Canvas of={messageStories.chatMessagePrompts} /> ## Usage diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts index 6fce7164a4..63ea6ad4c1 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts @@ -1,31 +1,25 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { webviCustom16X16 } from '@ni/nimble-tokens/dist/icons/js'; -import { buttonTag } from '@ni/nimble-components/src/button'; +import { buttonTag } from '../../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; -import { ChatMessageType } from '../../../../../spright-components/src/chat/types'; -import { richTextViewerTag } from '@ni/nimble-components/src/rich-text/viewer'; -import { spinnerTag } from '@ni/nimble-components/src/spinner'; +import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; +import { spinnerTag } from '../../../../../nimble-components/src/spinner'; import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { imgBlobUrl, markdownExample } from './story-helpers'; -const metadata: Meta<ChatMessageTextArgs> = { +interface ChatConversationArgs {} + +const metadata: Meta<ChatConversationArgs> = { title: 'Spright/Chat Conversation' }; -const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; -const imgBlob = new Blob([webviCustom16X16.data], { - type: 'image/svg+xml' -}); -const imgBlobUrl = URL.createObjectURL(imgBlob); -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface ChatConversation {} -export const chatConversation: StoryObj<ChatConversation> = { +export const chatConversation: StoryObj<ChatConversationArgs> = { parameters: { actions: {} }, @@ -38,7 +32,7 @@ export const chatConversation: StoryObj<ChatConversation> = { Where is the Any key? </${chatMessageTag}> <${chatMessageTag} message-type='outbound'> - <${richTextViewerTag} :markdown="${_x => markdownExample}"></${richTextViewerTag}> + <${richTextViewerTag} :markdown="${() => markdownExample}"></${richTextViewerTag}> </${chatMessageTag}> <${chatMessageTag} message-type='system'> <${spinnerTag} appearance='accent'></${spinnerTag}> @@ -62,138 +56,4 @@ export const chatConversation: StoryObj<ChatConversation> = { } }; -interface ChatMessageArgs { - messageType: ChatMessageType; -} - export default metadata; - -interface ChatMessageTextArgs extends ChatMessageArgs { - text: string; -} - -export const chatMessageText: StoryObj<ChatMessageTextArgs> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - ${x => x.text} - </${chatMessageTag}> - `), - argTypes: { - text: { - name: 'default', - description: 'The content to display in the chat message.', - table: { category: apiCategory.slots } - }, - messageType: { - name: 'message-type', - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The type of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - text: 'Aurora Borealis? At this time of year? At this time of day? In this part of the country? Localized entirely within your kitchen?', - messageType: ChatMessageType.outbound - } -}; - -interface ChatMessageRichTextArgs extends ChatMessageArgs { - markdown: string; -} -export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> - </${chatMessageTag}> - `), - argTypes: { - markdown: { - description: 'Markdown text for the rich text viewer', - table: { category: apiCategory.slots } - }, - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - markdown: markdownExample, - messageType: ChatMessageType.outbound - } -}; - -export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <${spinnerTag} appearance='accent'></${spinnerTag}> - </${chatMessageTag}> - `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - messageType: ChatMessageType.system - } -}; - -export const chatMessageImage: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <img width="100" height="100" :src=${() => imgBlobUrl}> - </${chatMessageTag}> - `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - messageType: ChatMessageType.inbound - } -}; - -export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, - render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <${buttonTag} appearance='block'>Eat my shorts</${buttonTag}> - <${buttonTag} appearance='block'>Do the Bartman</${buttonTag}> - </${chatMessageTag}> - `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, - args: { - messageType: ChatMessageType.system - } -}; diff --git a/packages/storybook/src/spright/chat/conversation/story-helpers.ts b/packages/storybook/src/spright/chat/conversation/story-helpers.ts new file mode 100644 index 0000000000..337e6eb0d2 --- /dev/null +++ b/packages/storybook/src/spright/chat/conversation/story-helpers.ts @@ -0,0 +1,8 @@ +import { webviCustom16X16 } from '@ni/nimble-tokens/dist/icons/js'; + +const imgBlob = new Blob([webviCustom16X16.data], { + type: 'image/svg+xml' +}); +export const imgBlobUrl = URL.createObjectURL(imgBlob); + +export const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; diff --git a/packages/storybook/src/spright/chat/message/chat-message.stories.ts b/packages/storybook/src/spright/chat/message/chat-message.stories.ts new file mode 100644 index 0000000000..1ba8b8b53a --- /dev/null +++ b/packages/storybook/src/spright/chat/message/chat-message.stories.ts @@ -0,0 +1,153 @@ +import { html } from '@microsoft/fast-element'; +import type { Meta, StoryObj } from '@storybook/html'; +import { + apiCategory, + createUserSelectedThemeStory +} from '../../../utilities/storybook'; + +import { buttonTag } from '../../../../../nimble-components/src/button'; +import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; +import { ChatMessageType } from '../../../../../spright-components/src/chat/message/types'; +import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; +import { spinnerTag } from '../../../../../nimble-components/src/spinner'; +import { imgBlobUrl, markdownExample } from '../conversation/story-helpers'; + +const metadata: Meta = { + title: 'Internal/Chat Message' +}; + +export default metadata; + +interface ChatMessageArgs { + messageType: ChatMessageType; +} + +interface ChatMessageTextArgs extends ChatMessageArgs { + text: string; +} + +export const chatMessageText: StoryObj<ChatMessageTextArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + ${x => x.text} + </${chatMessageTag}> + `), + argTypes: { + text: { + name: 'default', + description: 'The content to display in the chat message.', + table: { category: apiCategory.slots } + }, + messageType: { + name: 'message-type', + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The type of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + text: 'Aurora Borealis? At this time of year? At this time of day? In this part of the country? Localized entirely within your kitchen?', + messageType: ChatMessageType.outbound + } +}; + +interface ChatMessageRichTextArgs extends ChatMessageArgs { + markdown: string; +} +export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> + </${chatMessageTag}> + `), + argTypes: { + markdown: { + description: 'Markdown text for the rich text viewer', + table: { category: apiCategory.slots } + }, + messageType: { + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + markdown: markdownExample, + messageType: ChatMessageType.outbound + } +}; + +export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + <${spinnerTag} appearance='accent'></${spinnerTag}> + </${chatMessageTag}> + `), + argTypes: { + messageType: { + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + messageType: ChatMessageType.system + } +}; + +export const chatMessageImage: StoryObj<ChatMessageArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + <img width="100" height="100" :src=${() => imgBlobUrl}> + </${chatMessageTag}> + `), + argTypes: { + messageType: { + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + messageType: ChatMessageType.inbound + } +}; + +export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { + parameters: { + actions: {} + }, + render: createUserSelectedThemeStory(html` + <${chatMessageTag} message-type=${x => x.messageType}> + <${buttonTag} appearance='block'>Eat my shorts</${buttonTag}> + <${buttonTag} appearance='block'>Do the Bartman</${buttonTag}> + </${chatMessageTag}> + `), + argTypes: { + messageType: { + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The status of the chat message.', + table: { category: apiCategory.attributes } + } + }, + args: { + messageType: ChatMessageType.system + } +}; From 017942580c1e57291c8d1d5932efbbb6941c2d19 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:23:00 -0600 Subject: [PATCH 56/61] lint --- .../chat/conversation/chat-conversation-matrix.stories.ts | 2 +- .../src/spright/chat/conversation/chat-conversation.stories.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts index 2e99204d37..c6662d915f 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts @@ -1,5 +1,6 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; +import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; import { ChatMessageType } from '../../../../../spright-components/src/chat/message/types'; import { @@ -10,7 +11,6 @@ import { import { createStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; import { loremIpsum } from '../../../utilities/lorem-ipsum'; -import { richTextViewerTag } from '@ni/nimble-components/src/rich-text/viewer'; import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; import { textCustomizationWrapper } from '../../../utilities/text-customization'; diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts index 63ea6ad4c1..bfd817fbf4 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts @@ -11,14 +11,13 @@ import { } from '../../../utilities/storybook'; import { imgBlobUrl, markdownExample } from './story-helpers'; +// eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversationArgs {} const metadata: Meta<ChatConversationArgs> = { title: 'Spright/Chat Conversation' }; - - export const chatConversation: StoryObj<ChatConversationArgs> = { parameters: { actions: {} From de8219682a14f9b993bc975f64655f61be30fc49 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:19:59 -0600 Subject: [PATCH 57/61] Remove duplicate config for messages --- .../chat/conversation/chat-conversation.mdx | 4 + .../chat/message/chat-message.stories.ts | 89 ++++++------------- 2 files changed, 29 insertions(+), 64 deletions(-) diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx index 0613d95bc8..4dc0e41523 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.mdx @@ -40,18 +40,22 @@ Clients can place any HTML content within the message. #### Rich text message content <Canvas of={messageStories.chatMessageRichText} /> +<Controls of={messageStories.chatMessageRichText} /> #### Spinner message content <Canvas of={messageStories.chatMessageSpinner} /> +<Controls of={messageStories.chatMessageSpinner} /> #### Image message content <Canvas of={messageStories.chatMessageImage} /> +<Controls of={messageStories.chatMessageImage} /> #### Prompt buttons message content <Canvas of={messageStories.chatMessagePrompts} /> +<Controls of={messageStories.chatMessagePrompts} /> ## Usage diff --git a/packages/storybook/src/spright/chat/message/chat-message.stories.ts b/packages/storybook/src/spright/chat/message/chat-message.stories.ts index 1ba8b8b53a..0933aa4afa 100644 --- a/packages/storybook/src/spright/chat/message/chat-message.stories.ts +++ b/packages/storybook/src/spright/chat/message/chat-message.stories.ts @@ -12,26 +12,35 @@ import { richTextViewerTag } from '../../../../../nimble-components/src/rich-tex import { spinnerTag } from '../../../../../nimble-components/src/spinner'; import { imgBlobUrl, markdownExample } from '../conversation/story-helpers'; -const metadata: Meta = { - title: 'Internal/Chat Message' +interface ChatMessageArgs { + messageType: keyof typeof ChatMessageType; +} + +const metadata: Meta<ChatMessageArgs> = { + title: 'Internal/Chat Message', + argTypes: { + messageType: { + name: 'message-type', + options: Object.keys(ChatMessageType), + control: { type: 'radio' }, + description: 'The type of the chat message.', + table: { category: apiCategory.attributes } + } + }, + parameters: { + actions: {} + }, }; export default metadata; -interface ChatMessageArgs { - messageType: ChatMessageType; -} - interface ChatMessageTextArgs extends ChatMessageArgs { text: string; } export const chatMessageText: StoryObj<ChatMessageTextArgs> = { - parameters: { - actions: {} - }, render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> + <${chatMessageTag} message-type=${x => ChatMessageType[x.messageType]}> ${x => x.text} </${chatMessageTag}> `), @@ -41,17 +50,11 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { description: 'The content to display in the chat message.', table: { category: apiCategory.slots } }, - messageType: { - name: 'message-type', - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The type of the chat message.', - table: { category: apiCategory.attributes } - } + }, args: { text: 'Aurora Borealis? At this time of year? At this time of day? In this part of the country? Localized entirely within your kitchen?', - messageType: ChatMessageType.outbound + messageType: 'outbound' } }; @@ -59,9 +62,6 @@ interface ChatMessageRichTextArgs extends ChatMessageArgs { markdown: string; } export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { - parameters: { - actions: {} - }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> @@ -72,82 +72,43 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { description: 'Markdown text for the rich text viewer', table: { category: apiCategory.slots } }, - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } }, args: { markdown: markdownExample, - messageType: ChatMessageType.outbound + messageType: 'outbound' } }; export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> <${spinnerTag} appearance='accent'></${spinnerTag}> </${chatMessageTag}> `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, args: { - messageType: ChatMessageType.system + messageType: 'system' } }; export const chatMessageImage: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> <img width="100" height="100" :src=${() => imgBlobUrl}> </${chatMessageTag}> `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, args: { - messageType: ChatMessageType.inbound + messageType: 'inbound' } }; export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { - parameters: { - actions: {} - }, render: createUserSelectedThemeStory(html` <${chatMessageTag} message-type=${x => x.messageType}> <${buttonTag} appearance='block'>Eat my shorts</${buttonTag}> <${buttonTag} appearance='block'>Do the Bartman</${buttonTag}> </${chatMessageTag}> `), - argTypes: { - messageType: { - options: Object.keys(ChatMessageType), - control: { type: 'radio' }, - description: 'The status of the chat message.', - table: { category: apiCategory.attributes } - } - }, args: { - messageType: ChatMessageType.system + messageType: 'system' } }; From f80c5bb9586e12e4ddf6e5b5f3dd9f1d2aecf161 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:17:07 -0600 Subject: [PATCH 58/61] Template consistency --- .../conversation/chat-conversation.stories.ts | 25 ++++++++++++------- .../chat/message/chat-message.stories.ts | 20 ++++++++------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts index bfd817fbf4..15ec0f3ef5 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation.stories.ts @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; import { buttonTag } from '../../../../../nimble-components/src/button'; import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; +import { ChatMessageType } from '../../../../../spright-components/src/chat/message/types'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../../nimble-components/src/spinner'; @@ -10,6 +11,8 @@ import { createUserSelectedThemeStory } from '../../../utilities/storybook'; import { imgBlobUrl, markdownExample } from './story-helpers'; +import { ButtonAppearance } from '../../../../../nimble-components/src/menu-button/types'; +import { SpinnerAppearance } from '../../../../../nimble-components/src/spinner/types'; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ChatConversationArgs {} @@ -24,24 +27,28 @@ export const chatConversation: StoryObj<ChatConversationArgs> = { }, render: createUserSelectedThemeStory(html` <${chatConversationTag}> - <${chatMessageTag} message-type='inbound'> + <${chatMessageTag} message-type="${() => ChatMessageType.inbound}"> To start, press any key. </${chatMessageTag}> - <${chatMessageTag} message-type='outbound'> + <${chatMessageTag} message-type="${() => ChatMessageType.outbound}"> Where is the Any key? </${chatMessageTag}> - <${chatMessageTag} message-type='outbound'> + <${chatMessageTag} message-type="${() => ChatMessageType.outbound}"> <${richTextViewerTag} :markdown="${() => markdownExample}"></${richTextViewerTag}> </${chatMessageTag}> - <${chatMessageTag} message-type='system'> - <${spinnerTag} appearance='accent'></${spinnerTag}> + <${chatMessageTag} message-type="${() => ChatMessageType.system}"> + <${spinnerTag} appearance="${() => SpinnerAppearance.accent}"></${spinnerTag}> </${chatMessageTag}> - <${chatMessageTag} message-type='inbound'> + <${chatMessageTag} message-type="${() => ChatMessageType.inbound}"> <img width="100" height="100" :src=${() => imgBlobUrl}> </${chatMessageTag}> - <${chatMessageTag} message-type='system'> - <${buttonTag} appearance='block'>Order a tab</${buttonTag}> - <${buttonTag} appearance='block'>Check core temperature</${buttonTag}> + <${chatMessageTag} message-type="${() => ChatMessageType.system}"> + <${buttonTag} appearance="${() => ButtonAppearance.block}"> + Order a tab + </${buttonTag}> + <${buttonTag} appearance="${() => ButtonAppearance.block}"> + Check core temperature + </${buttonTag}> </${chatMessageTag}> </${chatConversationTag}> `), diff --git a/packages/storybook/src/spright/chat/message/chat-message.stories.ts b/packages/storybook/src/spright/chat/message/chat-message.stories.ts index 0933aa4afa..3e5685b174 100644 --- a/packages/storybook/src/spright/chat/message/chat-message.stories.ts +++ b/packages/storybook/src/spright/chat/message/chat-message.stories.ts @@ -11,6 +11,8 @@ import { ChatMessageType } from '../../../../../spright-components/src/chat/mess import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; import { spinnerTag } from '../../../../../nimble-components/src/spinner'; import { imgBlobUrl, markdownExample } from '../conversation/story-helpers'; +import { SpinnerAppearance } from '../../../../../nimble-components/src/spinner/types'; +import { ButtonAppearance } from '../../../../../nimble-components/src/menu-button/types'; interface ChatMessageArgs { messageType: keyof typeof ChatMessageType; @@ -40,7 +42,7 @@ interface ChatMessageTextArgs extends ChatMessageArgs { export const chatMessageText: StoryObj<ChatMessageTextArgs> = { render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => ChatMessageType[x.messageType]}> + <${chatMessageTag} message-type="${x => ChatMessageType[x.messageType]}"> ${x => x.text} </${chatMessageTag}> `), @@ -63,7 +65,7 @@ interface ChatMessageRichTextArgs extends ChatMessageArgs { } export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> + <${chatMessageTag} message-type="${x => ChatMessageType[x.messageType]}"> <${richTextViewerTag} :markdown="${x => x.markdown}"></${richTextViewerTag}> </${chatMessageTag}> `), @@ -81,8 +83,8 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <${spinnerTag} appearance='accent'></${spinnerTag}> + <${chatMessageTag} message-type="${x => ChatMessageType[x.messageType]}"> + <${spinnerTag} appearance="${() => SpinnerAppearance.accent}"></${spinnerTag}> </${chatMessageTag}> `), args: { @@ -92,8 +94,8 @@ export const chatMessageSpinner: StoryObj<ChatMessageArgs> = { export const chatMessageImage: StoryObj<ChatMessageArgs> = { render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <img width="100" height="100" :src=${() => imgBlobUrl}> + <${chatMessageTag} message-type="${x => ChatMessageType[x.messageType]}"> + <img width="100" height="100" :src="${() => imgBlobUrl}"> </${chatMessageTag}> `), args: { @@ -103,9 +105,9 @@ export const chatMessageImage: StoryObj<ChatMessageArgs> = { export const chatMessagePrompts: StoryObj<ChatMessageArgs> = { render: createUserSelectedThemeStory(html` - <${chatMessageTag} message-type=${x => x.messageType}> - <${buttonTag} appearance='block'>Eat my shorts</${buttonTag}> - <${buttonTag} appearance='block'>Do the Bartman</${buttonTag}> + <${chatMessageTag} message-type="${x => ChatMessageType[x.messageType]}"> + <${buttonTag} appearance="${() => ButtonAppearance.block}">Eat my shorts</${buttonTag}> + <${buttonTag} appearance="${() => ButtonAppearance.block}">Do the Bartman</${buttonTag}> </${chatMessageTag}> `), args: { From 19dc127ed4ee763fa142770739b9276986036665 Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:11:03 -0600 Subject: [PATCH 59/61] Refactor sizing stories --- .../chat-conversation-matrix.stories.ts | 190 +++++++----------- .../chat/conversation/story-helpers.ts | 23 +++ 2 files changed, 101 insertions(+), 112 deletions(-) diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts index c6662d915f..65e0670aee 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts @@ -1,6 +1,5 @@ import type { StoryFn, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; -import { richTextViewerTag } from '../../../../../nimble-components/src/rich-text/viewer'; import { chatMessageTag } from '../../../../../spright-components/src/chat/message'; import { ChatMessageType } from '../../../../../spright-components/src/chat/message/types'; import { @@ -10,16 +9,22 @@ import { } from '../../../utilities/matrix'; import { createStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; -import { loremIpsum } from '../../../utilities/lorem-ipsum'; import { chatConversationTag } from '../../../../../spright-components/src/chat/conversation'; import { textCustomizationWrapper } from '../../../utilities/text-customization'; +import { + bodyFont, + bodyFontColor +} from '../../../../../nimble-components/src/theme-provider/design-tokens'; -const chatMessageTypes = [ +const messageTypeStates = [ ['outbound', ChatMessageType.outbound], ['inbound', ChatMessageType.inbound], ['system', ChatMessageType.system] ] as const; -type ChatMessageTypeState = (typeof chatMessageTypes)[number]; +type MessageTypeStates = (typeof messageTypeStates)[number]; +const outboundState = messageTypeStates[0]; +const inboudState = messageTypeStates[1]; +const systemState = messageTypeStates[2]; const metadata: Meta = { title: 'Tests Spright/Chat Conversation', @@ -30,126 +35,87 @@ const metadata: Meta = { export default metadata; -const multiLineMessage = ` -Introduction to TestStand - -NI TestStand is a flexible and open test management framework for building, customizing, and deploying a full-featured test management system. - -**TestStand Sequence Editor** - -The sequence editor is a development environment in which you create, edit, execute, and debug sequences and the tests sequences call. Use the sequence editor to access all features, such as step types and process models. Refer to the Process Models section of this tutorial for more information about process models. - -You can debug a sequence using the following techniques, similar to how you debug in application development environments (ADEs) such as LabVIEW, LabWindows/CVI (ANSI), and Microsoft Visual Studio: - -- Setting breakpoints -- Stepping into, out of, or over steps -- Tracing through program executions -- Displaying variables -- Monitoring variables, expressions, and output messages during executions -- Performing static analysis of sequence files to locate errors and enforce coding guidelines - -In the sequence editor, you can start multiple concurrent executions, execute multiple instances of the same sequence, or execute different sequences at the same time. Each execution instance opens an Execution window. In Trace Mode, the Execution window shows the steps in the currently executing sequence. If the execution suspends, the Execution window shows the next step to execute and provides debugging options. - -In the sequence editor, you can fully customize the pane and tab layout to optimize development and debugging tasks. You can also customize the menus, toolbars, and keyboard shortcuts. -`; - -const component = ([ - chatMessageTypeName, - messageType -]: ChatMessageTypeState): ViewTemplate => html` +const viewportStates = [ + ['chat popup', '300px', '300px'], + ['mobile vertical', '300px', '600px'], + ['mobile horizontal', '600px', '300px'], + ['desktop', '600px', '600px'], +] as const; +type ViewportStates = (typeof viewportStates)[number]; - <${chatMessageTag} - message-type=${() => messageType}> - ${() => `Message Type: ${chatMessageTypeName}`}</${chatMessageTag}> -`; +const contentWidthStates = [ + ['thin', '100px'], + ['wide', '600px'] +] as const; +type ContentWidthStates = (typeof contentWidthStates)[number]; -const differentChatMessageSizeTestCase = ( - [message]: [string], - [messageType]: [string] -): ViewTemplate => html` - <${chatMessageTag} - message-type=${() => messageType} - style="outline: 1px dashed red; margin: 0px 20px 20px 0px"> - <${richTextViewerTag} - :markdown="${_ => message}"> - </${richTextViewerTag} - </${chatMessageTag}> -`; +const contentHeightStates = [ + ['short', '100px'], + ['tall', '600px'] +] as const; +type ContentHeightStates = (typeof contentHeightStates)[number]; -const messageWithFixSizeTestCase = ( - [message]: [string], - [messageType]: [string] +const componentSizing = ( + [_messageTypeLabel, messageType]: MessageTypeStates, + [viewportLabel, viewportWidth, viewportHeight]: ViewportStates, + [contentWidthLabel, contentWidth]: ContentWidthStates, + [contentHeightLabel, contentHeight]: ContentHeightStates ): ViewTemplate => html` - <${chatMessageTag} - message-type=${() => messageType} - style="outline: 1px dashed red; margin: 0px 20px 20px 0px"> - <${richTextViewerTag} - style="width: 400px; height: 80px;" - :markdown="${_ => message}"> - </${richTextViewerTag} - </${chatMessageTag}> -`; - -const differentChatConversationSizeTestCase = ([message]: [ - string -]): ViewTemplate => html` - <${chatConversationTag} - style="width: 900px; height: 400px; margin: 0px 0px 5px 0px"> - <${chatMessageTag} message-type='outbound' style="outline: 1px dashed red;"> - <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> - </${chatMessageTag}> - <${chatMessageTag} message-type='inbound' style="outline: 1px dashed red;"> - <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> - </${chatMessageTag}> - <${chatMessageTag} message-type='system' style="outline: 1px dashed red;"> - <${richTextViewerTag} :markdown="${_x => message}"></${richTextViewerTag}> - </${chatMessageTag}> - </${chatConversationTag}> + <p + style=" + font: var(${bodyFont.cssCustomProperty}); + color: var(${bodyFontColor.cssCustomProperty}); + margin-bottom: 0px; + " + > + viewport:${() => viewportLabel}, content:${() => contentWidthLabel},${() => contentHeightLabel} + </p> + <div style=" + width: ${viewportWidth}; + height: ${viewportHeight}; + border: 1px dashed red; + "> + <${chatConversationTag} style=" + width: 100%; + height: 100%; + "> + <${chatMessageTag} message-type="${() => messageType}"> + <div style=" + width: ${contentWidth}; + height: ${contentHeight}; + background: blue; + display: inline-block; + " + ></div> + </${chatMessageTag}> + </${chatConversationTag}> + </div> `; -export const messageThemeMatrix: StoryFn = createMatrixThemeStory( - createMatrix(component, [chatMessageTypes]) -); - -export const messageTinySizing: StoryFn = createStory(html` - ${createMatrix(differentChatMessageSizeTestCase, [ - [['a']], - [['outbound'], ['inbound'], ['system']] - ])} -`); - -export const messageExtraWideSizing: StoryFn = createStory(html` - ${createMatrix(differentChatMessageSizeTestCase, [ - [[loremIpsum]], - [['outbound'], ['inbound'], ['system']] +export const outboundSizing: StoryFn = createStory(html` + ${createMatrix(componentSizing, [ + [outboundState], + viewportStates, + contentWidthStates, + contentHeightStates ])} `); -export const messageWithFixedSizeSizing: StoryFn = createStory(html` - ${createMatrix(messageWithFixSizeTestCase, [ - [[loremIpsum]], - [['outbound'], ['inbound'], ['system']] +export const inboundSizing: StoryFn = createStory(html` + ${createMatrix(componentSizing, [ + [inboudState], + viewportStates, + contentWidthStates, + contentHeightStates ])} `); -export const messageManyLinesSizing: StoryFn = createStory(html` - ${createMatrix(differentChatMessageSizeTestCase, [ - [[multiLineMessage]], - [['outbound'], ['inbound'], ['system']] - ])} -`); - -export const conversationTinySizing: StoryFn = createStory(html` - ${createMatrix(differentChatConversationSizeTestCase, [[['a']]])} -`); - -export const conversationExtraWideSizing: StoryFn = createStory(html` - ${createMatrix(differentChatConversationSizeTestCase, [[[loremIpsum]]])} -`); - -export const conversationManyLinesSizing: StoryFn = createStory(html` - ${createMatrix(differentChatConversationSizeTestCase, [ - [[multiLineMessage]] +export const systemSizing: StoryFn = createStory(html` + ${createMatrix(componentSizing, [ + [systemState], + viewportStates, + contentWidthStates, + contentHeightStates ])} `); diff --git a/packages/storybook/src/spright/chat/conversation/story-helpers.ts b/packages/storybook/src/spright/chat/conversation/story-helpers.ts index 337e6eb0d2..ff094a0cc8 100644 --- a/packages/storybook/src/spright/chat/conversation/story-helpers.ts +++ b/packages/storybook/src/spright/chat/conversation/story-helpers.ts @@ -6,3 +6,26 @@ const imgBlob = new Blob([webviCustom16X16.data], { export const imgBlobUrl = URL.createObjectURL(imgBlob); export const markdownExample = "I see **Esc**, **Crtl**, and **Pg Up**. There doesn't seem to be any **Any** key."; + +export const multiLineMarkdownExample = ` +Introduction to TestStand + +NI TestStand is a flexible and open test management framework for building, customizing, and deploying a full-featured test management system. + +**TestStand Sequence Editor** + +The sequence editor is a development environment in which you create, edit, execute, and debug sequences and the tests sequences call. Use the sequence editor to access all features, such as step types and process models. Refer to the Process Models section of this tutorial for more information about process models. + +You can debug a sequence using the following techniques, similar to how you debug in application development environments (ADEs) such as LabVIEW, LabWindows/CVI (ANSI), and Microsoft Visual Studio: + +- Setting breakpoints +- Stepping into, out of, or over steps +- Tracing through program executions +- Displaying variables +- Monitoring variables, expressions, and output messages during executions +- Performing static analysis of sequence files to locate errors and enforce coding guidelines + +In the sequence editor, you can start multiple concurrent executions, execute multiple instances of the same sequence, or execute different sequences at the same time. Each execution instance opens an Execution window. In Trace Mode, the Execution window shows the steps in the currently executing sequence. If the execution suspends, the Execution window shows the next step to execute and provides debugging options. + +In the sequence editor, you can fully customize the pane and tab layout to optimize development and debugging tasks. You can also customize the menus, toolbars, and keyboard shortcuts. +`; From 7d8c7aaab474c3c28ca832a5de00ce4527ee722d Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:13:22 -0600 Subject: [PATCH 60/61] lint --- .../chat/conversation/chat-conversation-matrix.stories.ts | 2 +- .../src/spright/chat/message/chat-message.stories.ts | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts index 65e0670aee..a159a7288a 100644 --- a/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts +++ b/packages/storybook/src/spright/chat/conversation/chat-conversation-matrix.stories.ts @@ -39,7 +39,7 @@ const viewportStates = [ ['chat popup', '300px', '300px'], ['mobile vertical', '300px', '600px'], ['mobile horizontal', '600px', '300px'], - ['desktop', '600px', '600px'], + ['desktop', '600px', '600px'] ] as const; type ViewportStates = (typeof viewportStates)[number]; diff --git a/packages/storybook/src/spright/chat/message/chat-message.stories.ts b/packages/storybook/src/spright/chat/message/chat-message.stories.ts index 3e5685b174..054392cc05 100644 --- a/packages/storybook/src/spright/chat/message/chat-message.stories.ts +++ b/packages/storybook/src/spright/chat/message/chat-message.stories.ts @@ -31,7 +31,7 @@ const metadata: Meta<ChatMessageArgs> = { }, parameters: { actions: {} - }, + } }; export default metadata; @@ -51,8 +51,7 @@ export const chatMessageText: StoryObj<ChatMessageTextArgs> = { name: 'default', description: 'The content to display in the chat message.', table: { category: apiCategory.slots } - }, - + } }, args: { text: 'Aurora Borealis? At this time of year? At this time of day? In this part of the country? Localized entirely within your kitchen?', @@ -73,7 +72,7 @@ export const chatMessageRichText: StoryObj<ChatMessageRichTextArgs> = { markdown: { description: 'Markdown text for the rich text viewer', table: { category: apiCategory.slots } - }, + } }, args: { markdown: markdownExample, From 9ee640b33e32ffe706b46f8d3bdc231db92de4dc Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Wed, 12 Feb 2025 15:08:18 -0600 Subject: [PATCH 61/61] Move overflow to inner message div --- packages/spright-components/src/chat/message/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/spright-components/src/chat/message/styles.ts b/packages/spright-components/src/chat/message/styles.ts index 67b7e56ded..2aa2dd2f0a 100644 --- a/packages/spright-components/src/chat/message/styles.ts +++ b/packages/spright-components/src/chat/message/styles.ts @@ -21,7 +21,6 @@ export const styles = css` flex-shrink: 0; font: ${bodyFont}; color: ${bodyFontColor}; - overflow-x: auto; } :host([message-type='outbound']) { @@ -37,6 +36,7 @@ export const styles = css` width: fit-content; height: fit-content; padding: ${mediumPadding}; + overflow-x: auto; } :host([message-type='outbound']) div {