@spaced-out/genesis-mcp 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/design-system.json +90 -4
- package/package.json +1 -1
package/data/design-system.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"metadata": {
|
|
3
|
-
"buildDate": "2025-12-
|
|
4
|
-
"version": "0.5.
|
|
3
|
+
"buildDate": "2025-12-19T18:18:39.517Z",
|
|
4
|
+
"version": "0.5.38",
|
|
5
5
|
"designSystemPath": "/home/runner/work/ui-design-system/ui-design-system"
|
|
6
6
|
},
|
|
7
7
|
"components": {
|
|
@@ -260,11 +260,11 @@
|
|
|
260
260
|
"files": {
|
|
261
261
|
"main": {
|
|
262
262
|
"path": "Button.d.ts",
|
|
263
|
-
"content": "import * as React from 'react';\nimport type { Flow } from 'flow-to-typescript-codemod';\nimport type { IconType } from '../../components/Icon';\ntype ClassNames = Readonly<{\n wrapper?: string;\n icon?: string;\n text?: string;\n}>;\n/**\n * Note(Nishant): Although Button supports gradient as a type, its not currently customizable really.\n * This only supports pre-defined gradient that moves from left to right.\n * If someone wants to add more gradients, the expectation is that they would add it through a wrapper className.\n *\n * We could have taken an extra prop to take in the Gradient colors but that should not be encouraged\n * as it would add an additional overhead on the component to figure out exact color values from string tokens\n * and since this is rarely used type anyway, it should be avoided.\n */\nexport declare const BUTTON_TYPES: Readonly<{\n primary: \"primary\";\n secondary: \"secondary\";\n tertiary: \"tertiary\";\n ghost: \"ghost\";\n danger: \"danger\";\n gradient: \"gradient\";\n
|
|
263
|
+
"content": "import * as React from 'react';\nimport type { Flow } from 'flow-to-typescript-codemod';\nimport type { IconType } from '../../components/Icon';\ntype ClassNames = Readonly<{\n wrapper?: string;\n icon?: string;\n text?: string;\n}>;\n/**\n * Note(Nishant): Although Button supports gradient as a type, its not currently customizable really.\n * This only supports pre-defined gradient that moves from left to right.\n * If someone wants to add more gradients, the expectation is that they would add it through a wrapper className.\n *\n * We could have taken an extra prop to take in the Gradient colors but that should not be encouraged\n * as it would add an additional overhead on the component to figure out exact color values from string tokens\n * and since this is rarely used type anyway, it should be avoided.\n */\nexport declare const BUTTON_TYPES: Readonly<{\n primary: \"primary\";\n secondary: \"secondary\";\n tertiary: \"tertiary\";\n ghost: \"ghost\";\n danger: \"danger\";\n gradient: \"gradient\";\n tertiaryGradient: \"tertiaryGradient\";\n}>;\nexport declare const BUTTON_ACTION_TYPE: Readonly<{\n button: \"button\";\n submit: \"submit\";\n reset: \"reset\";\n}>;\nexport declare const BUTTON_SIZE: Readonly<{\n small: \"small\";\n medium: \"medium\";\n}>;\nexport type ButtonType = (typeof BUTTON_TYPES)[keyof typeof BUTTON_TYPES];\nexport type ButtonActionType = (typeof BUTTON_ACTION_TYPE)[keyof typeof BUTTON_ACTION_TYPE];\nexport type ButtonSize = keyof typeof BUTTON_SIZE;\nexport interface BaseButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'disabled' | 'actionType' | 'onClick' | 'ariaLabel' | 'tabIndex' | 'isLoading' | 'role'> {\n children?: React.ReactNode;\n disabled?: boolean;\n actionType?: ButtonActionType;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n ariaLabel?: string;\n tabIndex?: number;\n isLoading?: boolean;\n role?: string;\n testId?: string;\n}\nexport interface UnstyledButtonProps extends Omit<BaseButtonProps, 'className'> {\n className?: string;\n}\nexport interface ButtonProps extends Omit<BaseButtonProps, 'classNames' | 'iconLeftName' | 'iconLeftType' | 'iconRightName' | 'iconRightType' | 'type' | 'isFluid' | 'size'> {\n classNames?: ClassNames;\n iconLeftName?: string;\n iconLeftType?: IconType;\n iconRightName?: string;\n iconRightType?: IconType;\n type?: ButtonType;\n isFluid?: boolean;\n size?: ButtonSize;\n}\nexport declare const UnstyledButton: Flow.AbstractComponent<UnstyledButtonProps, HTMLButtonElement>;\nexport declare const Button: Flow.AbstractComponent<ButtonProps, HTMLButtonElement>;\nexport {};\n//# sourceMappingURL=Button.d.ts.map"
|
|
264
264
|
},
|
|
265
265
|
"story": {
|
|
266
266
|
"path": "Button.stories.tsx",
|
|
267
|
-
"content": "import * as React from 'react';\n\nimport type {ButtonProps} from 'src/components/Button/Button';\nimport {\n Button,\n BUTTON_ACTION_TYPE,\n BUTTON_SIZE,\n BUTTON_TYPES,\n} from 'src/components/Button/Button';\n\n\nconst actionTypeOptions: Array<unknown> = [\n ...Object.values(BUTTON_ACTION_TYPE),\n];\nconst buttonTypeOptions: Array<unknown> = [...Object.values(BUTTON_TYPES)];\nconst buttonSizeOptions: Array<unknown> = [...Object.values(BUTTON_SIZE)];\n\nexport default {\n tags: ['autodocs'],\n title: 'Components/Button',\n component: Button,\n argTypes: {\n onClick: {\n description:\n '**onClick** handler that is applied to the root `<button>` element',\n action: 'clicked',\n table: {\n type: {summary: '(SyntheticEvent<HTMLElement>) => mixed'},\n },\n },\n classNames: {\n description: 'External classNames to be applied',\n control: {\n type: 'object',\n },\n table: {\n type: {summary: '{wrapper?: string, icon?: string, text?: string}'},\n },\n },\n iconLeftName: {\n description:\n 'Left icon to be applied to the button, it internally uses the `Icon` component to render icons',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n iconLeftType: {\n description:\n 'Type of Left Icon. Type represents 4 unique icon styles :- Solid, Regular, Duotone and Brands',\n options: ['regular', 'solid', 'duotone', 'brands'],\n control: {type: 'select'},\n table: {\n type: {summary: 'string'},\n defaultValue: {summary: 'regular'},\n },\n },\n iconRightName: {\n description:\n 'Right icon to be applied to the button, it internally uses the `Icon` component to render icons',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n iconRightType: {\n description:\n 'Type of Right Icon. Type represents 4 unique icon styles :- Solid, Regular, Duotone and Brands',\n options: ['regular', 'solid', 'duotone', 'brands'],\n control: {type: 'select'},\n table: {\n type: {summary: 'string'},\n defaultValue: {summary: 'regular'},\n },\n },\n type: {\n options: buttonTypeOptions,\n description: 'Type of Button. Supported types are listed on the dropdown',\n control: {\n type: 'select',\n },\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'primary'},\n },\n },\n actionType: {\n options: actionTypeOptions,\n description:\n 'Type of action to perform upon Button click. Supported types are listed on the dropdown',\n control: {\n type: 'select',\n },\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'submit'},\n },\n },\n size: {\n description:\n 'Button supports only two size variants namely small and medium. `small` < `medium`',\n options: buttonSizeOptions,\n control: {type: 'select'},\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'medium'},\n },\n },\n disabled: {\n description: 'If **true**, the component is disabled',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n isLoading: {\n description:\n 'If **true**, the component would show a circular loader and also preserve the current size of button so that there are no jumps',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n isFluid: {\n description:\n 'If **true**, the component would take the container\\'s `width`',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n children: {\n description: 'The content of the Button',\n table: {\n type: {summary: 'React.Component | string'},\n },\n },\n ariaLabel: {\n control: {\n type: 'text',\n },\n description:\n '**aria-label** should be used where Button do not have have discernible text. This would avoid accessibility violations in screen readers',\n table: {\n type: {summary: 'string'},\n },\n },\n testId: {\n description: 'Test ID for the component',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n },\n parameters: {\n docs: {\n subtitle: 'Generates a Button component',\n description: {\n component: `\n\\`\\`\\`js\nimport { Button } from \"@spaced-out/ui-design-system/lib/components/Button\";\n\\`\\`\\`\nButtons allow users to take actions. Button comes with multiple variants and has various states(hover, focus, etc). Variation also include\nan Icon only variant, it is rendered when no content(child) is passed to the button. An unstyled button is also present for one off use cases\nwhere we want to style the button differently.\n\n**Note: ** Always use \\`ariaLabel\\` with Icon only button for accessibility\n `,\n },\n },\n storySource: {\n componentPath: '/src/components/Button/Button',\n },\n },\n};\n\n/** Text only Button */\nexport const TextOnlyStory = (args: ButtonProps) => <Button {...args} />;\n\nTextOnlyStory.args = {\n children: 'Primary Button Text',\n type: 'primary',\n size: 'medium',\n testId: 'button-text-only-story',\n};\n\nexport const TextIconLeftStory = (args: ButtonProps) => <Button {...args} />;\n\nTextIconLeftStory.args = {\n children: 'Button Text',\n type: 'primary',\n size: 'medium',\n iconLeftName: 'face-party',\n testId: 'button-text-icon-left-story',\n};\n\nexport const TextIconRightStory = (args: ButtonProps) => <Button {...args} />;\n\nTextIconRightStory.args = {\n children: 'Button Text',\n type: 'primary',\n size: 'medium',\n iconRightName: 'face-party',\n testId: 'button-text-icon-right-story',\n};\n\nexport const IconOnlyStory = (args: ButtonProps) => <Button {...args} />;\n\nIconOnlyStory.args = {\n type: 'primary',\n size: 'medium',\n iconRightName: 'face-party',\n ariaLabel: 'Icon Button',\n testId: 'button-icon-only-story',\n};\n\nexport const GradientStory = (args: ButtonProps) => <Button {...args} />;\n\nGradientStory.args = {\n type: 'gradient',\n iconLeftName: 'sparkles',\n iconLeftType: 'solid',\n children: 'Sense AI',\n testId: 'button-gradient-story',\n};\n\nexport const TertiaryGradientStory = (args: ButtonProps) => (\n <Button {...args} />\n);\n\nTertiaryGradientStory.args = {\n type: '
|
|
267
|
+
"content": "import * as React from 'react';\n\nimport type {ButtonProps} from 'src/components/Button/Button';\nimport {\n Button,\n BUTTON_ACTION_TYPE,\n BUTTON_SIZE,\n BUTTON_TYPES,\n} from 'src/components/Button/Button';\n\n\nconst actionTypeOptions: Array<unknown> = [\n ...Object.values(BUTTON_ACTION_TYPE),\n];\nconst buttonTypeOptions: Array<unknown> = [...Object.values(BUTTON_TYPES)];\nconst buttonSizeOptions: Array<unknown> = [...Object.values(BUTTON_SIZE)];\n\nexport default {\n tags: ['autodocs'],\n title: 'Components/Button',\n component: Button,\n argTypes: {\n onClick: {\n description:\n '**onClick** handler that is applied to the root `<button>` element',\n action: 'clicked',\n table: {\n type: {summary: '(SyntheticEvent<HTMLElement>) => mixed'},\n },\n },\n classNames: {\n description: 'External classNames to be applied',\n control: {\n type: 'object',\n },\n table: {\n type: {summary: '{wrapper?: string, icon?: string, text?: string}'},\n },\n },\n iconLeftName: {\n description:\n 'Left icon to be applied to the button, it internally uses the `Icon` component to render icons',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n iconLeftType: {\n description:\n 'Type of Left Icon. Type represents 4 unique icon styles :- Solid, Regular, Duotone and Brands',\n options: ['regular', 'solid', 'duotone', 'brands'],\n control: {type: 'select'},\n table: {\n type: {summary: 'string'},\n defaultValue: {summary: 'regular'},\n },\n },\n iconRightName: {\n description:\n 'Right icon to be applied to the button, it internally uses the `Icon` component to render icons',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n iconRightType: {\n description:\n 'Type of Right Icon. Type represents 4 unique icon styles :- Solid, Regular, Duotone and Brands',\n options: ['regular', 'solid', 'duotone', 'brands'],\n control: {type: 'select'},\n table: {\n type: {summary: 'string'},\n defaultValue: {summary: 'regular'},\n },\n },\n type: {\n options: buttonTypeOptions,\n description: 'Type of Button. Supported types are listed on the dropdown',\n control: {\n type: 'select',\n },\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'primary'},\n },\n },\n actionType: {\n options: actionTypeOptions,\n description:\n 'Type of action to perform upon Button click. Supported types are listed on the dropdown',\n control: {\n type: 'select',\n },\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'submit'},\n },\n },\n size: {\n description:\n 'Button supports only two size variants namely small and medium. `small` < `medium`',\n options: buttonSizeOptions,\n control: {type: 'select'},\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: 'medium'},\n },\n },\n disabled: {\n description: 'If **true**, the component is disabled',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n isLoading: {\n description:\n 'If **true**, the component would show a circular loader and also preserve the current size of button so that there are no jumps',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n isFluid: {\n description:\n 'If **true**, the component would take the container\\'s `width`',\n control: {\n type: 'boolean',\n },\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n children: {\n description: 'The content of the Button',\n table: {\n type: {summary: 'React.Component | string'},\n },\n },\n ariaLabel: {\n control: {\n type: 'text',\n },\n description:\n '**aria-label** should be used where Button do not have have discernible text. This would avoid accessibility violations in screen readers',\n table: {\n type: {summary: 'string'},\n },\n },\n testId: {\n description: 'Test ID for the component',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n },\n parameters: {\n docs: {\n subtitle: 'Generates a Button component',\n description: {\n component: `\n\\`\\`\\`js\nimport { Button } from \"@spaced-out/ui-design-system/lib/components/Button\";\n\\`\\`\\`\nButtons allow users to take actions. Button comes with multiple variants and has various states(hover, focus, etc). Variation also include\nan Icon only variant, it is rendered when no content(child) is passed to the button. An unstyled button is also present for one off use cases\nwhere we want to style the button differently.\n\n**Note: ** Always use \\`ariaLabel\\` with Icon only button for accessibility\n `,\n },\n },\n storySource: {\n componentPath: '/src/components/Button/Button',\n },\n },\n};\n\n/** Text only Button */\nexport const TextOnlyStory = (args: ButtonProps) => <Button {...args} />;\n\nTextOnlyStory.args = {\n children: 'Primary Button Text',\n type: 'primary',\n size: 'medium',\n testId: 'button-text-only-story',\n};\n\nexport const TextIconLeftStory = (args: ButtonProps) => <Button {...args} />;\n\nTextIconLeftStory.args = {\n children: 'Button Text',\n type: 'primary',\n size: 'medium',\n iconLeftName: 'face-party',\n testId: 'button-text-icon-left-story',\n};\n\nexport const TextIconRightStory = (args: ButtonProps) => <Button {...args} />;\n\nTextIconRightStory.args = {\n children: 'Button Text',\n type: 'primary',\n size: 'medium',\n iconRightName: 'face-party',\n testId: 'button-text-icon-right-story',\n};\n\nexport const IconOnlyStory = (args: ButtonProps) => <Button {...args} />;\n\nIconOnlyStory.args = {\n type: 'primary',\n size: 'medium',\n iconRightName: 'face-party',\n ariaLabel: 'Icon Button',\n testId: 'button-icon-only-story',\n};\n\nexport const GradientStory = (args: ButtonProps) => <Button {...args} />;\n\nGradientStory.args = {\n type: 'gradient',\n iconLeftName: 'sparkles',\n iconLeftType: 'solid',\n children: 'Sense AI',\n testId: 'button-gradient-story',\n};\n\nexport const TertiaryGradientStory = (args: ButtonProps) => (\n <Button {...args} />\n);\n\nTertiaryGradientStory.args = {\n type: 'tertiaryGradient',\n iconLeftName: 'sparkles',\n iconLeftType: 'solid',\n children: 'Sense AI',\n testId: 'button-tertiary-gradient-story',\n};\n\nTextOnlyStory.storyName = 'Text Only';\nTextIconLeftStory.storyName = 'Text Icon Left';\nTextIconRightStory.storyName = 'Text Icon Right';\nIconOnlyStory.storyName = 'Icon Only';\nGradientStory.storyName = 'Gradient';\nTertiaryGradientStory.storyName = 'Tertiary Gradient';\n"
|
|
268
268
|
},
|
|
269
269
|
"css": {
|
|
270
270
|
"path": "Button.module.css",
|
|
@@ -2017,6 +2017,36 @@
|
|
|
2017
2017
|
"index.ts"
|
|
2018
2018
|
]
|
|
2019
2019
|
},
|
|
2020
|
+
"ScrollingLoader": {
|
|
2021
|
+
"name": "ScrollingLoader",
|
|
2022
|
+
"path": "src/components/ScrollingLoader",
|
|
2023
|
+
"files": {
|
|
2024
|
+
"main": {
|
|
2025
|
+
"path": "ScrollingLoader.d.ts",
|
|
2026
|
+
"content": "import type { Flow } from 'flow-to-typescript-codemod';\nexport declare const SCROLLING_LOADER_SIZE: Readonly<{\n medium: \"medium\";\n large: \"large\";\n fluid: \"fluid\";\n}>;\nexport type ScrollingLoaderSize = (typeof SCROLLING_LOADER_SIZE)[keyof typeof SCROLLING_LOADER_SIZE];\ntype ClassNames = Readonly<{\n wrapper?: string;\n skeletonContainer?: string;\n textContainer?: string;\n}>;\nexport interface IconItem {\n name: string;\n type?: 'regular' | 'solid' | 'duotone' | 'brands';\n}\nexport interface ScrollingLoaderProps {\n /** List of icons to display in skeleton rows */\n iconList: IconItem[];\n /** List of text messages to cycle through */\n textList: string[];\n /** Size variant of the loader */\n size?: ScrollingLoaderSize;\n /** Custom class names for styling */\n classNames?: ClassNames;\n /** Test ID for the component */\n testId?: string;\n /** Animation duration in ms for each text item (default: 2500) */\n textAnimationDuration?: number;\n /** Whether to loop through texts or stop at the last one (default: false) */\n loopTexts?: boolean;\n}\nexport declare const ScrollingLoader: Flow.AbstractComponent<ScrollingLoaderProps, HTMLDivElement>;\nexport {};\n//# sourceMappingURL=ScrollingLoader.d.ts.map"
|
|
2027
|
+
},
|
|
2028
|
+
"story": {
|
|
2029
|
+
"path": "ScrollingLoader.stories.tsx",
|
|
2030
|
+
"content": "import * as React from 'react';\n\nimport type {ScrollingLoaderProps} from 'src/components/ScrollingLoader/ScrollingLoader';\nimport {\n SCROLLING_LOADER_SIZE,\n ScrollingLoader,\n} from 'src/components/ScrollingLoader/ScrollingLoader';\n\nimport css from 'src/components/ScrollingLoader/ScrollingLoader.stories.module.css';\n\n\nconst sizeOptions: Array<unknown> = [...Object.values(SCROLLING_LOADER_SIZE)];\n\nexport default {\n tags: ['autodocs'],\n title: 'AI Prompt Components/Scrolling Loader',\n component: ScrollingLoader,\n argTypes: {\n iconList: {\n description:\n 'List of icons to display in the skeleton rows. Each item should have a `name` and optional `type`.',\n control: {\n type: 'object',\n },\n table: {\n type: {\n summary:\n 'Array<{ name: string; type?: \"regular\" | \"solid\" | \"duotone\" | \"brands\" }>',\n },\n },\n },\n textList: {\n description: 'List of text messages to cycle through with fade animation',\n control: {\n type: 'object',\n },\n table: {\n type: {summary: 'Array<string>'},\n },\n },\n size: {\n description:\n 'Size variant of the loader. Medium (284px), Large (320px), or Fluid (100%)',\n options: sizeOptions,\n control: {type: 'select'},\n table: {\n type: {summary: 'enum'},\n defaultValue: {summary: SCROLLING_LOADER_SIZE.medium},\n },\n },\n textAnimationDuration: {\n description: 'Duration in milliseconds for each text item display',\n control: {type: 'number'},\n table: {\n type: {summary: 'number'},\n defaultValue: {summary: 2500},\n },\n },\n classNames: {\n description: 'External classNames to be applied',\n control: {\n type: 'object',\n },\n table: {\n type: {\n summary:\n '{wrapper?: string, skeletonContainer?: string, textContainer?: string}',\n },\n },\n },\n testId: {\n description: 'Test ID for the component',\n control: {\n type: 'text',\n },\n table: {\n type: {summary: 'string'},\n },\n },\n loopTexts: {\n description:\n 'Whether to loop through texts continuously or stop at the last one. When false, animation stops at the last text received.',\n control: {type: 'boolean'},\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: false},\n },\n },\n },\n parameters: {\n docs: {\n subtitle: 'A scrolling loader with skeleton animation and cycling text',\n description: {\n component: `\n\\`\\`\\`jsx\nimport { ScrollingLoader } from \"@spaced-out/ui-design-system/lib/components/ScrollingLoader\";\n\\`\\`\\`\n**ScrollingLoader**\n\nUse this component to display a loading state with animated skeleton rows and cycling text messages.\nPerfect for showing progress during agent creation, publishing, or other multi-step processes.\n\n**Features:**\n- Infinite scrolling skeleton rows with icons\n- Smooth fade-in/fade-out text transitions\n- Gradient fades at top and bottom for seamless loop effect\n- Three size variants: medium, large, and fluid\n- Streaming support: texts can be added dynamically without breaking animations\n\n**Usage:**\n\n\\`\\`\\`jsx\n<ScrollingLoader\n iconList={[\n { name: 'envelope' },\n { name: 'list-check' },\n { name: 'filter' },\n { name: 'calendar' },\n { name: 'circle-question' },\n { name: 'hand-wave' },\n ]}\n textList={[\n 'Publishing your agent...',\n 'Generating Greetings prompt...',\n 'Generating Data Collection prompt...',\n 'Setting things up for you…',\n ]}\n size=\"medium\"\n/>\n\\`\\`\\`\n\n**Streaming Usage:**\n\nWhen receiving texts from a stream (e.g., WebSocket, SSE), you can pass them dynamically.\nBy default (\\`loopTexts={false}\\`), the animation stops at the last text and resumes when new texts arrive.\n\n\\`\\`\\`jsx\nconst [streamedTexts, setStreamedTexts] = useState<string[]>([]);\n\n// In your stream handler:\nonStreamMessage((text) => {\n setStreamedTexts(prev => [...prev, text]);\n});\n\n<ScrollingLoader\n iconList={iconList}\n textList={streamedTexts}\n size=\"medium\"\n/>\n\\`\\`\\`\n\nSet \\`loopTexts={true}\\` if you want the texts to cycle continuously.\n `,\n },\n },\n storySource: {\n componentPath: '/src/components/ScrollingLoader/ScrollingLoader',\n },\n },\n};\n\nconst DEFAULT_ICONS = [\n {name: 'envelope'},\n {name: 'list-check'},\n {name: 'filter'},\n {name: 'calendar'},\n {name: 'circle-question'},\n {name: 'hand-wave'},\n];\n\nconst PUBLISHING_TEXT_LIST = [\n 'Generating Greetings prompt...',\n 'Generating FAQ prompt...',\n 'Setting things up for you…',\n 'Almost there…',\n];\n\nconst CREATING_TEXT_LIST = [\n 'Getting Greetings Ready...',\n 'Setting Up Data Collection...',\n 'Preparing Screening...',\n 'Preparing Scheduling...',\n 'Preparing FAQ...',\n 'Setting up Closing...',\n];\n\nexport const DefaultStory = (args: ScrollingLoaderProps) => (\n <div className={css.storyContainer}>\n <ScrollingLoader {...args} />\n </div>\n);\n\nDefaultStory.args = {\n iconList: DEFAULT_ICONS,\n textList: PUBLISHING_TEXT_LIST,\n size: SCROLLING_LOADER_SIZE.medium,\n testId: 'scrolling-loader-default-story',\n};\n\nexport const FluidSizeStory = (args: ScrollingLoaderProps) => (\n <div className={css.storyContainerFluid}>\n <ScrollingLoader {...args} />\n </div>\n);\n\nFluidSizeStory.args = {\n iconList: DEFAULT_ICONS,\n textList: PUBLISHING_TEXT_LIST,\n size: SCROLLING_LOADER_SIZE.fluid,\n testId: 'scrolling-loader-fluid-story',\n};\n\nexport const CreatingAgentStory = (args: ScrollingLoaderProps) => (\n <div className={css.storyContainer}>\n <ScrollingLoader {...args} />\n </div>\n);\n\nCreatingAgentStory.args = {\n iconList: DEFAULT_ICONS,\n textList: CREATING_TEXT_LIST,\n size: SCROLLING_LOADER_SIZE.medium,\n textAnimationDuration: 2000,\n testId: 'scrolling-loader-creating-story',\n};\n\nexport const CustomIconsStory = (args: ScrollingLoaderProps) => (\n <div className={css.storyContainer}>\n <ScrollingLoader {...args} />\n </div>\n);\n\nCustomIconsStory.args = {\n iconList: [\n {name: 'robot', type: 'solid'},\n {name: 'brain', type: 'solid'},\n {name: 'microchip', type: 'solid'},\n {name: 'network-wired', type: 'solid'},\n {name: 'database', type: 'solid'},\n {name: 'cloud', type: 'solid'},\n ],\n textList: [\n 'Initializing AI models...',\n 'Loading neural networks...',\n 'Connecting to services...',\n 'Preparing your experience...',\n ],\n size: SCROLLING_LOADER_SIZE.medium,\n loopTexts: true,\n testId: 'scrolling-loader-custom-icons-story',\n};\n\n// Streaming example - simulates receiving texts one by one from a stream\nconst STREAMING_TEXT_LIST = [\n 'Connecting to AI service...',\n 'Analyzing your request...',\n 'Generating response...',\n 'Processing data...',\n 'Optimizing results...',\n 'Finalizing output...',\n];\n\nconst StreamingLoaderWrapper = () => {\n const [streamedTexts, setStreamedTexts] = React.useState<string[]>([\n STREAMING_TEXT_LIST[0],\n ]);\n\n React.useEffect(() => {\n if (streamedTexts.length >= STREAMING_TEXT_LIST.length) {\n return;\n }\n\n const timeout = setTimeout(() => {\n setStreamedTexts((prev) => [...prev, STREAMING_TEXT_LIST[prev.length]]);\n }, 3000); // Add a new text every 3 seconds\n\n return () => clearTimeout(timeout);\n }, [streamedTexts.length]);\n\n return (\n <div className={css.storyContainer}>\n <div>\n Texts received: {streamedTexts.length} / {STREAMING_TEXT_LIST.length}\n </div>\n <ScrollingLoader\n iconList={DEFAULT_ICONS}\n textList={streamedTexts}\n size={SCROLLING_LOADER_SIZE.medium}\n textAnimationDuration={2000}\n loopTexts={false}\n testId=\"scrolling-loader-streaming-story\"\n />\n </div>\n );\n};\n\nexport const StreamingStory = () => <StreamingLoaderWrapper />;\n\nStreamingStory.parameters = {\n docs: {\n description: {\n story: `\n**Streaming Use Case**\n\nThis example demonstrates how the ScrollingLoader handles texts being added one by one,\nsimulating a streaming scenario where texts arrive from an API or WebSocket.\n\nWith \\`loopTexts={false}\\`, the animation:\n- Stops at the last text received\n- Resumes when new texts arrive\n- Stops again at the new last text\n\n**Usage with streaming:**\n\\`\\`\\`jsx\nconst [streamedTexts, setStreamedTexts] = useState<string[]>([]);\n\n// In your stream handler:\nonStreamMessage((text) => {\n setStreamedTexts(prev => [...prev, text]);\n});\n\n<ScrollingLoader\n iconList={iconList}\n textList={streamedTexts}\n size=\"medium\"\n loopTexts={false}\n/>\n\\`\\`\\`\n `,\n },\n },\n};\n\nDefaultStory.storyName = 'Default (Medium)';\nFluidSizeStory.storyName = 'Fluid Size';\nCreatingAgentStory.storyName = 'Creating Agent';\nCustomIconsStory.storyName = 'Custom Icons';\nStreamingStory.storyName = 'Streaming (Dynamic Texts)';\n"
|
|
2031
|
+
},
|
|
2032
|
+
"css": {
|
|
2033
|
+
"path": "ScrollingLoader.module.css",
|
|
2034
|
+
"content": "@value (\n colorBackgroundTertiary,\n colorBackgroundSecondary,\n colorBorderTertiary,\n colorTextPrimary,\n colorFillNone\n) from '../../styles/variables/_color.css';\n\n@value (\n spaceNone,\n spaceXXSmall,\n spaceXSmall,\n spaceSmall,\n spaceMedium,\n spaceFluid,\n spaceNegHalfFluid\n) from '../../styles/variables/_space.css';\n\n@value (\n size8,\n size12,\n size16,\n size20,\n size24,\n size34,\n size42,\n size90,\n size100,\n size150,\n size200,\n size240,\n size260,\n size276,\n size284,\n size300,\n size320,\n size426,\n sizeFluid\n) from '../../styles/variables/_size.css';\n\n@value (\n borderRadiusXSmall,\n borderRadiusMedium,\n borderWidthPrimary\n) from '../../styles/variables/_border.css';\n\n@value (\n motionDurationNormal,\n motionDurationSlow,\n motionEaseInEaseOut\n) from '../../styles/variables/_motion.css';\n\n@value (\n opacity0,\n opacity100\n) from '../../styles/variables/_opacity.css';\n\n@value (\n fontWeightMedium\n) from '../../styles/variables/_font.css';\n\n.wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: spaceMedium;\n}\n\n.medium {\n width: size284;\n}\n\n.large {\n width: size426;\n}\n\n.fluid {\n width: sizeFluid;\n}\n\n/* Skeleton Container */\n.skeletonContainer {\n position: relative;\n width: sizeFluid;\n overflow: hidden;\n border: borderWidthPrimary dashed colorBorderTertiary;\n border-radius: borderRadiusMedium;\n background-color: colorBackgroundTertiary;\n}\n\n/* Size-specific skeleton container heights */\n.medium .skeletonContainer {\n height: size200;\n}\n\n.large .skeletonContainer,\n.fluid .skeletonContainer {\n height: size300;\n}\n\n.skeletonScroller {\n --animation-duration: 9s;\n display: flex;\n flex-direction: column;\n gap: spaceMedium;\n animation: scrollUp var(--animation-duration) linear infinite;\n}\n\n/* Size-specific skeleton scroller padding */\n.medium .skeletonScroller {\n padding: spaceSmall;\n}\n\n.large .skeletonScroller,\n.fluid .skeletonScroller {\n padding: spaceMedium;\n}\n\n.skeletonRow {\n display: flex;\n align-items: center;\n gap: spaceXSmall;\n flex-shrink: 0;\n}\n\n.skeletonRowSmall {\n gap: spaceXSmall;\n}\n\n.skeletonRowLarge {\n gap: spaceSmall;\n}\n\n.skeletonBars {\n display: flex;\n flex-direction: column;\n gap: spaceXSmall;\n flex: 1;\n}\n\n.skeletonBarTitle {\n width: size90;\n height: size12;\n background-color: colorBackgroundSecondary;\n border-radius: borderRadiusXSmall;\n}\n\n.skeletonBarSubtitle {\n width: sizeFluid;\n height: size8;\n background-color: colorBackgroundSecondary;\n border-radius: borderRadiusXSmall;\n}\n\n.skeletonRowLarge .skeletonBarTitle {\n height: calc(size8 * 2);\n}\n\n.skeletonRowLarge .skeletonBarSubtitle {\n height: size12;\n}\n\n/* Gradient Overlays */\n.gradientTop {\n position: absolute;\n top: calc(borderWidthPrimary * -1);\n left: calc(borderWidthPrimary * -1);\n right: calc(borderWidthPrimary * -1);\n background: linear-gradient(\n to bottom,\n colorBackgroundTertiary opacity0,\n colorFillNone opacity100\n );\n pointer-events: none;\n}\n\n.gradientBottom {\n position: absolute;\n bottom: calc(borderWidthPrimary * -1);\n left: calc(borderWidthPrimary * -1);\n right: calc(borderWidthPrimary * -1);\n background: linear-gradient(\n to top,\n colorBackgroundTertiary opacity0,\n colorFillNone opacity100\n );\n pointer-events: none;\n}\n\n/* Size-specific gradient overlay heights (50% of container height) */\n.medium .gradientTop,\n.medium .gradientBottom {\n height: size100;\n}\n\n.large .gradientTop,\n.large .gradientBottom,\n.fluid .gradientTop,\n.fluid .gradientBottom {\n height: size150;\n}\n\n/* Text Container */\n.textContainer {\n display: flex;\n justify-content: center;\n align-items: center;\n position: relative;\n width: sizeFluid;\n overflow: hidden;\n}\n\n/* Size-specific text container heights */\n.medium .textContainer {\n height: calc(size20 + borderWidthPrimary);\n}\n\n.large .textContainer,\n.fluid .textContainer {\n height: size24;\n}\n\n.textScroller {\n position: absolute;\n top: spaceNone;\n left: spaceNone;\n right: spaceNone;\n bottom: spaceNone;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.textItem {\n position: absolute;\n white-space: nowrap;\n color: colorTextPrimary;\n font-weight: fontWeightMedium;\n opacity: opacity0;\n transform: translateY(spaceFluid);\n /* No transition by default - allows instant reset without animation */\n}\n\n/* Size-specific text typography - applied conditionally via TSX */\n.textItemMedium {\n composes: bodyMedium from '../../styles/typography.module.css';\n}\n\n.textItemLarge {\n composes: bodyLarge from '../../styles/typography.module.css';\n}\n\n/* Active state - text sliding in and visible */\n.textItemActive {\n opacity: opacity100;\n transform: translateY(spaceNone);\n transition: opacity motionDurationNormal motionEaseInEaseOut,\n transform motionDurationNormal motionEaseInEaseOut;\n}\n\n/* Exiting state - text sliding out upward */\n.textItemExiting {\n opacity: opacity0;\n transform: translateY(spaceNegHalfFluid);\n transition: opacity motionDurationNormal motionEaseInEaseOut,\n transform motionDurationNormal motionEaseInEaseOut;\n}\n\n/* Static state for single item - no animation */\n.textItemStatic {\n opacity: opacity100;\n transform: translateY(spaceNone);\n}\n\n/* Scroll Animation */\n@keyframes scrollUp {\n 0% {\n transform: translateY(spaceNone);\n }\n 100% {\n transform: translateY(spaceNegHalfFluid);\n }\n}\n"
|
|
2035
|
+
},
|
|
2036
|
+
"index": {
|
|
2037
|
+
"path": "index.d.ts",
|
|
2038
|
+
"content": "export * from '../../components/ScrollingLoader/ScrollingLoader';\n//# sourceMappingURL=index.d.ts.map"
|
|
2039
|
+
},
|
|
2040
|
+
"additional": {}
|
|
2041
|
+
},
|
|
2042
|
+
"allFiles": [
|
|
2043
|
+
"ScrollingLoader.module.css",
|
|
2044
|
+
"ScrollingLoader.stories.module.css",
|
|
2045
|
+
"ScrollingLoader.stories.tsx",
|
|
2046
|
+
"ScrollingLoader.tsx",
|
|
2047
|
+
"index.ts"
|
|
2048
|
+
]
|
|
2049
|
+
},
|
|
2020
2050
|
"SearchInput": {
|
|
2021
2051
|
"name": "SearchInput",
|
|
2022
2052
|
"path": "src/components/SearchInput",
|
|
@@ -2137,6 +2167,50 @@
|
|
|
2137
2167
|
"index.ts"
|
|
2138
2168
|
]
|
|
2139
2169
|
},
|
|
2170
|
+
"StageArrows": {
|
|
2171
|
+
"name": "StageArrows",
|
|
2172
|
+
"path": "src/components/StageArrows",
|
|
2173
|
+
"files": {
|
|
2174
|
+
"main": {
|
|
2175
|
+
"path": "StageArrows.d.ts",
|
|
2176
|
+
"content": "import * as React from 'react';\nimport type { Flow } from 'flow-to-typescript-codemod';\ntype ClassNames = Readonly<{\n wrapper?: string;\n}>;\nexport interface StageArrowsProps {\n disabled?: boolean;\n children: React.ReactNode;\n classNames?: ClassNames;\n onStageArrowClick?: ((id: string, e?: React.SyntheticEvent<HTMLElement> | null | undefined) => unknown) | null | undefined;\n testId?: string;\n}\nexport declare const StageArrows: Flow.AbstractComponent<StageArrowsProps, HTMLDivElement>;\nexport {};\n//# sourceMappingURL=StageArrows.d.ts.map"
|
|
2177
|
+
},
|
|
2178
|
+
"story": {
|
|
2179
|
+
"path": "StageArrows.stories.tsx",
|
|
2180
|
+
"content": "import * as React from 'react';\n\nimport {StageArrow} from 'src/components/StageArrows/StageArrow/StageArrow';\nimport type {StageArrowsProps} from 'src/components/StageArrows/StageArrows';\nimport {StageArrows} from 'src/components/StageArrows/StageArrows';\n\nimport css from 'src/components/StageArrows/StageArrows.stories.module.css';\n\n\nexport default {\n tags: ['autodocs'],\n title: 'Components/Stage Arrows/Stage Arrows',\n component: StageArrows,\n argTypes: {\n classNames: {\n description: 'Provide an optional className to be applied to the wrapper',\n control: {type: 'object'},\n table: {\n type: {summary: '{ wrapper?: string }'},\n },\n },\n disabled: {\n description: 'If **true**, the component is disabled',\n control: {type: 'boolean'},\n table: {\n type: {summary: 'boolean'},\n defaultValue: {summary: 'false'},\n },\n },\n },\n parameters: {\n docs: {\n subtitle: 'Generates a StageArrows component.',\n description: {\n component: `\n\\`\\`\\`js\nimport { StageArrows } from \"@spaced-out/ui-design-system/lib/components/StageArrows\";\n\\`\\`\\`\nThe StageArrows component is a horizontal navigation component that displays a series of connected stages in a workflow or process. Each stage is represented by a <a href=\"../?path=/docs/components-stage-arrows-stage-arrow--docs\">\\`<StageArrow/>\\`</a> component that can be customized with different types (primary, warning, danger, success, information), icons, and states (disabled, locked)\n\n**note:** -\n1. If only one stage is passed in the StageArrows component, it will be rendered as a In-Between stage arrow.\n2. If two stages are passed in the StageArrows component, the first stage will be rendered as a Start stage arrow and the last stage will be rendered as a End stage arrow.\n `,\n },\n },\n storySource: {\n componentPath: '/src/components/StageArrows/StageArrows.tsx',\n },\n },\n};\n\n\nexport const _TextOnly = (args: StageArrowsProps): React.ReactNode => (\n <div className={css.container}>\n <StageArrows {...args}>\n <StageArrow id=\"1\" type=\"primary\">\n Stage 1\n </StageArrow>\n <StageArrow id=\"3\" type=\"warning\">\n Stage 2\n </StageArrow>\n <StageArrow id=\"4\" type=\"danger\">\n Stage 3\n </StageArrow>\n <StageArrow id=\"6\" type=\"success\">\n Stage 4\n </StageArrow>\n <StageArrow id=\"7\" type=\"information\">\n Stage 5\n </StageArrow>\n </StageArrows>\n </div>\n);\n\n_TextOnly.args = {\n classNames: {wrapper: ''},\n};\n\nexport const _TextAndIcon = (args: StageArrowsProps): React.ReactNode => (\n <div className={css.container}>\n <StageArrows {...args}>\n <StageArrow id=\"1\" type=\"primary\" iconRightName=\"sitemap\">\n Stage 1\n </StageArrow>\n <StageArrow id=\"3\" type=\"warning\" iconRightName=\"sitemap\">\n Stage 2\n </StageArrow>\n <StageArrow id=\"4\" type=\"danger\" iconRightName=\"sitemap\">\n Stage 3\n </StageArrow>\n <StageArrow id=\"6\" type=\"success\" iconRightName=\"sitemap\">\n Stage 4\n </StageArrow>\n <StageArrow id=\"7\" type=\"information\" iconRightName=\"sitemap\">\n Stage 5\n </StageArrow>\n </StageArrows>\n </div>\n);\n\n_TextAndIcon.args = {\n classNames: {wrapper: ''},\n};\n\nexport const _Disabled = (args: StageArrowsProps): React.ReactNode => (\n <div className={css.container}>\n <StageArrows {...args}>\n <StageArrow id=\"1\" type=\"primary\" iconLeftName=\"sitemap\">\n Stage 1\n </StageArrow>\n <StageArrow id=\"3\" type=\"warning\" iconLeftName=\"sitemap\" disabled>\n Stage 2\n </StageArrow>\n <StageArrow id=\"4\" type=\"danger\" iconLeftName=\"sitemap\">\n Stage 3\n </StageArrow>\n <StageArrow id=\"6\" type=\"success\" iconLeftName=\"sitemap\">\n Stage 4\n </StageArrow>\n <StageArrow id=\"7\" type=\"information\" iconLeftName=\"sitemap\" disabled>\n Stage 5\n </StageArrow>\n </StageArrows>\n </div>\n);\n\n_Disabled.args = {\n classNames: {wrapper: ''},\n};\n"
|
|
2181
|
+
},
|
|
2182
|
+
"css": {
|
|
2183
|
+
"path": "StageArrows.module.css",
|
|
2184
|
+
"content": ".stageArrowsWrapper {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n overflow: auto;\n -ms-overflow-style: none;\n scrollbar-width: none;\n}\n\n.stageArrowsWrapper::-webkit-scrollbar {\n display: none;\n}\n"
|
|
2185
|
+
},
|
|
2186
|
+
"index": {
|
|
2187
|
+
"path": "index.d.ts",
|
|
2188
|
+
"content": "export * from '../../components/StageArrows/StageArrow';\nexport * from '../../components/StageArrows/StageArrows';\n//# sourceMappingURL=index.d.ts.map"
|
|
2189
|
+
},
|
|
2190
|
+
"additional": {
|
|
2191
|
+
"StageArrow/StageArrow.d.ts": {
|
|
2192
|
+
"path": "StageArrow/StageArrow.d.ts",
|
|
2193
|
+
"content": "import * as React from 'react';\nimport type { Flow } from 'flow-to-typescript-codemod';\nimport type { IconType } from '../../../components/Icon';\nimport type { BaseTooltipProps } from '../../../components/Tooltip/Tooltip';\ntype ClassNames = Readonly<{\n wrapper?: string;\n icon?: string;\n}>;\nexport declare const STAGE_ARROW_TYPE: Readonly<{\n primary: \"primary\";\n danger: \"danger\";\n success: \"success\";\n warning: \"warning\";\n information: \"information\";\n}>;\nexport type StageArrowType = (typeof STAGE_ARROW_TYPE)[keyof typeof STAGE_ARROW_TYPE];\nexport interface StageArrowProps {\n id: string;\n type?: StageArrowType;\n disabled?: boolean;\n iconLeftName?: string;\n iconLeftType?: IconType;\n iconRightName?: string;\n iconRightType?: IconType;\n classNames?: ClassNames;\n isEndStageArrow?: boolean;\n isStartStageArrow?: boolean;\n onStageArrowClick?: ((id: string, e?: React.SyntheticEvent<HTMLElement> | null | undefined) => unknown) | null | undefined;\n children: React.ReactNode;\n tooltip?: BaseTooltipProps;\n testId?: string;\n locked?: boolean;\n}\nexport declare const StageArrow: Flow.AbstractComponent<StageArrowProps, HTMLButtonElement>;\nexport {};\n//# sourceMappingURL=StageArrow.d.ts.map"
|
|
2194
|
+
},
|
|
2195
|
+
"StageArrow/index.d.ts": {
|
|
2196
|
+
"path": "StageArrow/index.d.ts",
|
|
2197
|
+
"content": "export * from '../../../components/StageArrows/StageArrow/StageArrow';\n//# sourceMappingURL=index.d.ts.map"
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
},
|
|
2201
|
+
"allFiles": [
|
|
2202
|
+
"StageArrow/StageArrow.module.css",
|
|
2203
|
+
"StageArrow/StageArrow.stories.module.css",
|
|
2204
|
+
"StageArrow/StageArrow.stories.tsx",
|
|
2205
|
+
"StageArrow/StageArrow.tsx",
|
|
2206
|
+
"StageArrow/index.ts",
|
|
2207
|
+
"StageArrows.module.css",
|
|
2208
|
+
"StageArrows.stories.module.css",
|
|
2209
|
+
"StageArrows.stories.tsx",
|
|
2210
|
+
"StageArrows.tsx",
|
|
2211
|
+
"index.ts"
|
|
2212
|
+
]
|
|
2213
|
+
},
|
|
2140
2214
|
"StatusIndicator": {
|
|
2141
2215
|
"name": "StatusIndicator",
|
|
2142
2216
|
"path": "src/components/StatusIndicator",
|
|
@@ -4456,6 +4530,9 @@
|
|
|
4456
4530
|
"12": {
|
|
4457
4531
|
"value": "12px"
|
|
4458
4532
|
},
|
|
4533
|
+
"16": {
|
|
4534
|
+
"value": "16px"
|
|
4535
|
+
},
|
|
4459
4536
|
"18": {
|
|
4460
4537
|
"value": "18px"
|
|
4461
4538
|
},
|
|
@@ -4534,6 +4611,9 @@
|
|
|
4534
4611
|
"140": {
|
|
4535
4612
|
"value": "140px"
|
|
4536
4613
|
},
|
|
4614
|
+
"150": {
|
|
4615
|
+
"value": "150px"
|
|
4616
|
+
},
|
|
4537
4617
|
"160": {
|
|
4538
4618
|
"value": "160px"
|
|
4539
4619
|
},
|
|
@@ -4558,6 +4638,9 @@
|
|
|
4558
4638
|
"276": {
|
|
4559
4639
|
"value": "276px"
|
|
4560
4640
|
},
|
|
4641
|
+
"284": {
|
|
4642
|
+
"value": "284px"
|
|
4643
|
+
},
|
|
4561
4644
|
"300": {
|
|
4562
4645
|
"value": "300px"
|
|
4563
4646
|
},
|
|
@@ -4570,6 +4653,9 @@
|
|
|
4570
4653
|
"400": {
|
|
4571
4654
|
"value": "400px"
|
|
4572
4655
|
},
|
|
4656
|
+
"426": {
|
|
4657
|
+
"value": "426px"
|
|
4658
|
+
},
|
|
4573
4659
|
"480": {
|
|
4574
4660
|
"value": "480px"
|
|
4575
4661
|
},
|
package/package.json
CHANGED