@veluai/velu 0.2.25 → 0.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +80 -80
  2. package/dist/cli.js +44 -44
  3. package/package.json +64 -64
  4. package/runtime/velu-ui/base.css +320 -320
  5. package/runtime/velu-ui/components/Accordion.jsx +64 -64
  6. package/runtime/velu-ui/components/ApiClient.jsx +207 -207
  7. package/runtime/velu-ui/components/ApiField.jsx +87 -87
  8. package/runtime/velu-ui/components/ApiPath.jsx +63 -63
  9. package/runtime/velu-ui/components/ApiReferencePage.jsx +384 -384
  10. package/runtime/velu-ui/components/ApiSamples.jsx +36 -36
  11. package/runtime/velu-ui/components/ApiSidebar.jsx +125 -125
  12. package/runtime/velu-ui/components/AskBar.jsx +71 -71
  13. package/runtime/velu-ui/components/Callout.jsx +114 -114
  14. package/runtime/velu-ui/components/Card.jsx +131 -131
  15. package/runtime/velu-ui/components/ChangelogFilters.jsx +75 -75
  16. package/runtime/velu-ui/components/Chatbot.jsx +972 -972
  17. package/runtime/velu-ui/components/CodeBlock.jsx +375 -375
  18. package/runtime/velu-ui/components/Columns.jsx +56 -56
  19. package/runtime/velu-ui/components/ContextMenu.jsx +327 -327
  20. package/runtime/velu-ui/components/ErrorCard.jsx +138 -138
  21. package/runtime/velu-ui/components/Field.jsx +81 -81
  22. package/runtime/velu-ui/components/Image.jsx +163 -163
  23. package/runtime/velu-ui/components/Logo.jsx +31 -31
  24. package/runtime/velu-ui/components/MethodBadge.jsx +31 -31
  25. package/runtime/velu-ui/components/NavSelect.jsx +108 -108
  26. package/runtime/velu-ui/components/NotFound.jsx +63 -63
  27. package/runtime/velu-ui/components/PageFeedback.jsx +219 -219
  28. package/runtime/velu-ui/components/PageFooter.jsx +145 -145
  29. package/runtime/velu-ui/components/PageHeader.jsx +422 -422
  30. package/runtime/velu-ui/components/PageNav.jsx +77 -77
  31. package/runtime/velu-ui/components/PoweredBy.jsx +51 -51
  32. package/runtime/velu-ui/components/Prompt.jsx +115 -115
  33. package/runtime/velu-ui/components/Search.jsx +460 -460
  34. package/runtime/velu-ui/components/Sidebar.jsx +246 -246
  35. package/runtime/velu-ui/components/SocialLinks.jsx +90 -90
  36. package/runtime/velu-ui/components/Steps.jsx +65 -65
  37. package/runtime/velu-ui/components/ThemeToggle.jsx +48 -48
  38. package/runtime/velu-ui/components/Toc.jsx +537 -537
  39. package/runtime/velu-ui/components/TocBar.jsx +195 -195
  40. package/runtime/velu-ui/components/Tree.jsx +87 -87
  41. package/runtime/velu-ui/components/TryItBar.jsx +102 -102
  42. package/runtime/velu-ui/components/Update.jsx +92 -92
  43. package/runtime/velu-ui/components/accordion.css +92 -92
  44. package/runtime/velu-ui/components/api-page.css +208 -208
  45. package/runtime/velu-ui/components/api.css +635 -635
  46. package/runtime/velu-ui/components/ask-bar.css +103 -103
  47. package/runtime/velu-ui/components/card.css +105 -105
  48. package/runtime/velu-ui/components/changelog-filters.css +43 -43
  49. package/runtime/velu-ui/components/chatbot.css +687 -687
  50. package/runtime/velu-ui/components/code-block.css +263 -263
  51. package/runtime/velu-ui/components/context-menu.css +199 -199
  52. package/runtime/velu-ui/components/docs-layout.css +822 -822
  53. package/runtime/velu-ui/components/field.css +82 -82
  54. package/runtime/velu-ui/components/image.css +237 -237
  55. package/runtime/velu-ui/components/nav-select.css +157 -157
  56. package/runtime/velu-ui/components/not-found.css +94 -94
  57. package/runtime/velu-ui/components/page-feedback.css +261 -261
  58. package/runtime/velu-ui/components/page-footer.css +130 -130
  59. package/runtime/velu-ui/components/page-header.css +558 -558
  60. package/runtime/velu-ui/components/page-nav.css +50 -50
  61. package/runtime/velu-ui/components/powered-by.css +92 -92
  62. package/runtime/velu-ui/components/prompt.css +99 -99
  63. package/runtime/velu-ui/components/search.css +307 -307
  64. package/runtime/velu-ui/components/sidebar.css +205 -205
  65. package/runtime/velu-ui/components/steps.css +77 -77
  66. package/runtime/velu-ui/components/theme-toggle.css +102 -102
  67. package/runtime/velu-ui/components/toc-bar.css +234 -234
  68. package/runtime/velu-ui/components/tree.css +49 -49
  69. package/runtime/velu-ui/components/update.css +111 -111
  70. package/runtime/velu-ui/index.js +58 -58
  71. package/runtime/velu-ui/lib/api-send.js +118 -118
  72. package/runtime/velu-ui/lib/brand-icons.jsx +103 -103
  73. package/runtime/velu-ui/lib/component-schemas.js +100 -100
  74. package/runtime/velu-ui/lib/copyText.js +64 -64
  75. package/runtime/velu-ui/lib/docs-assistant.js +273 -273
  76. package/runtime/velu-ui/lib/lang-icons.jsx +147 -147
  77. package/runtime/velu-ui/lib/page-feedback.js +72 -72
  78. package/runtime/velu-ui/lib/pagefind.js +116 -116
  79. package/runtime/velu-ui/lib/prism-langs.js +957 -957
  80. package/runtime/velu-ui/lib/prism-loader.js +74 -74
  81. package/runtime/velu-ui/lib/resolveIcon.jsx +29 -29
  82. package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -66
  83. package/runtime/velu-ui/mdx-components.jsx +107 -107
  84. package/runtime/velu-ui/primitives/Cluster.jsx +49 -49
  85. package/runtime/velu-ui/primitives/Stack.jsx +63 -63
  86. package/runtime/velu-ui/primitives/Switcher.jsx +57 -57
  87. package/runtime/velu-ui/primitives/stack.css +3 -3
  88. package/runtime/velu-ui/primitives/switcher.css +25 -25
  89. package/runtime/velu-ui/styles.css +48 -48
  90. package/runtime/velu-ui/tokens.css +4 -4
  91. package/schema/velu.schema.json +419 -419
  92. package/src/lib/extract-mdx-error.js +170 -170
  93. package/src/lib/issues.js +159 -159
  94. package/src/lib/known-components.js +35 -35
  95. package/src/navigation.js +459 -459
  96. package/src/runtime/App.jsx +1754 -1754
  97. package/src/runtime/ErrorBoundary.jsx +54 -54
  98. package/src/runtime/client-entry.jsx +27 -27
  99. package/src/runtime/server-entry.jsx +24 -24
  100. package/src/template.html +48 -48
  101. package/templates/starter/ai-tools/claude-code.mdx +26 -26
  102. package/templates/starter/ai-tools/cursor.mdx +17 -17
  103. package/templates/starter/api-reference/introduction.mdx +43 -43
  104. package/templates/starter/development.mdx +19 -19
  105. package/templates/starter/essentials/code.mdx +29 -29
  106. package/templates/starter/essentials/images.mdx +29 -29
  107. package/templates/starter/essentials/markdown.mdx +25 -25
  108. package/templates/starter/essentials/navigation.mdx +39 -39
  109. package/templates/starter/essentials/settings.mdx +30 -30
  110. package/templates/starter/favicon.svg +6 -6
  111. package/templates/starter/index.mdx +31 -31
  112. package/templates/starter/openapi.json +160 -160
  113. package/templates/starter/quickstart.mdx +31 -31
  114. package/templates/starter/velu.json +40 -40
@@ -1,36 +1,36 @@
1
- import React from 'react';
2
- import CodeBlock, { CodeGroup } from './CodeBlock.jsx';
3
-
4
- /**
5
- * ApiSamples — the right-rail of an API reference page: the request code
6
- * snippets (curl / JS / Python / Ruby tabs) and the example responses
7
- * (one tab per status). The runtime renders this in the page's right aside
8
- * (where the TOC sits for normal pages).
9
- *
10
- * @param {{ samples: {key,label,language,code}[], responses: object[] }} props
11
- */
12
- export default function ApiSamples({ samples = [], responses = [] }) {
13
- const withExample = responses.filter((r) => r.example != null);
14
- return (
15
- <div className="velu-api-samples">
16
- {samples.length > 0 && (
17
- <CodeGroup className="velu-api-samples__req">
18
- {samples.map((s) => (
19
- <CodeBlock key={s.key} title={s.label} language={s.language}>
20
- {s.code}
21
- </CodeBlock>
22
- ))}
23
- </CodeGroup>
24
- )}
25
- {withExample.length > 0 && (
26
- <CodeGroup className="velu-api-samples__res">
27
- {withExample.map((r) => (
28
- <CodeBlock key={r.status} title={r.status} language="json">
29
- {JSON.stringify(r.example, null, 2)}
30
- </CodeBlock>
31
- ))}
32
- </CodeGroup>
33
- )}
34
- </div>
35
- );
36
- }
1
+ import React from 'react';
2
+ import CodeBlock, { CodeGroup } from './CodeBlock.jsx';
3
+
4
+ /**
5
+ * ApiSamples — the right-rail of an API reference page: the request code
6
+ * snippets (curl / JS / Python / Ruby tabs) and the example responses
7
+ * (one tab per status). The runtime renders this in the page's right aside
8
+ * (where the TOC sits for normal pages).
9
+ *
10
+ * @param {{ samples: {key,label,language,code}[], responses: object[] }} props
11
+ */
12
+ export default function ApiSamples({ samples = [], responses = [] }) {
13
+ const withExample = responses.filter((r) => r.example != null);
14
+ return (
15
+ <div className="velu-api-samples">
16
+ {samples.length > 0 && (
17
+ <CodeGroup className="velu-api-samples__req">
18
+ {samples.map((s) => (
19
+ <CodeBlock key={s.key} title={s.label} language={s.language}>
20
+ {s.code}
21
+ </CodeBlock>
22
+ ))}
23
+ </CodeGroup>
24
+ )}
25
+ {withExample.length > 0 && (
26
+ <CodeGroup className="velu-api-samples__res">
27
+ {withExample.map((r) => (
28
+ <CodeBlock key={r.status} title={r.status} language="json">
29
+ {JSON.stringify(r.example, null, 2)}
30
+ </CodeBlock>
31
+ ))}
32
+ </CodeGroup>
33
+ )}
34
+ </div>
35
+ );
36
+ }
@@ -1,125 +1,125 @@
1
- import React from 'react';
2
- import Stack from '../primitives/Stack.jsx';
3
- import resolveIcon from '../lib/resolveIcon.jsx';
4
- import MethodBadge from './MethodBadge.jsx';
5
-
6
- /**
7
- * ApiSidebar — navigation for API reference pages. Like <Sidebar> but
8
- * flat (no nested folders): every entry is a single endpoint shown as
9
- * a method pill + name. Entries are organized into groups, each with
10
- * an optional icon.
11
- *
12
- * <ApiSidebar
13
- * activeHref="/api/trigger"
14
- * linkComponent={RouterLink}
15
- * sections={[
16
- * {
17
- * title: 'Admin',
18
- * icon: 'rocket',
19
- * endpoints: [
20
- * { method: 'POST', label: 'Trigger', href: '/api/trigger' },
21
- * { method: 'GET', label: 'Get deployment-status',
22
- * href: '/api/status' },
23
- * { method: 'DELETE', label: 'Trigger Preview deployment',
24
- * href: '/api/preview' },
25
- * ],
26
- * },
27
- * ]}
28
- * />
29
- *
30
- * Vertical rhythm = the Stack primitive (DRY, same as <Sidebar>);
31
- * api.css holds only the rail / active state / row layout / icon size.
32
- * Selection is route-driven (`endpoint.href === activeHref`, or
33
- * `endpoint.active: true`). Router-agnostic via `linkComponent`.
34
- *
35
- * @typedef {Object} ApiEndpoint
36
- * @property {string} method HTTP method — drives the MethodBadge color
37
- * @property {string} label endpoint display name
38
- * @property {string} [href]
39
- * @property {boolean} [active]
40
- *
41
- * @param {{ sections: { title?: string, icon?: string|React.ReactNode,
42
- * endpoints: ApiEndpoint[] }[], activeHref?: string,
43
- * linkComponent?: React.ElementType, className?: string }} props
44
- */
45
-
46
- const Ctx = React.createContext({ activeHref: undefined, Link: 'a' });
47
-
48
- function Icon({ icon }) {
49
- const node = resolveIcon(icon);
50
- return node ? (
51
- <span className="velu-api-sidebar__icon" aria-hidden="true">
52
- {node}
53
- </span>
54
- ) : null;
55
- }
56
-
57
- function Endpoint({ endpoint }) {
58
- const { activeHref, Link } = React.useContext(Ctx);
59
- const { method, label, href = '#', active, icon } = endpoint;
60
- const isActive = Boolean(
61
- active || (href != null && href === activeHref),
62
- );
63
- const cls = `velu-api-sidebar__item${
64
- isActive ? ' velu-api-sidebar__item--active' : ''
65
- }`;
66
- // A plain page sitting in an API tab (e.g. an "Introduction") has no HTTP
67
- // method — show its icon (if any) where the method pill would be, never a
68
- // stray badge.
69
- return (
70
- <li>
71
- <Link
72
- className={cls}
73
- href={href}
74
- aria-current={isActive ? 'page' : undefined}
75
- >
76
- {method ? <MethodBadge method={method} /> : <Icon icon={icon} />}
77
- <span className="velu-api-sidebar__label">{label}</span>
78
- </Link>
79
- </li>
80
- );
81
- }
82
-
83
- export default function ApiSidebar({
84
- sections = [],
85
- activeHref,
86
- linkComponent = 'a',
87
- className = '',
88
- ...rest
89
- }) {
90
- const ctx = React.useMemo(
91
- () => ({ activeHref, Link: linkComponent }),
92
- [activeHref, linkComponent],
93
- );
94
- return (
95
- <Ctx.Provider value={ctx}>
96
- <Stack
97
- as="nav"
98
- space="var(--s1)"
99
- className={`velu-api-sidebar ${className}`.trim()}
100
- aria-label="API reference"
101
- {...rest}
102
- >
103
- {sections.map((section, i) => (
104
- <React.Fragment key={i}>
105
- {section.title != null && (
106
- <h5 className="velu-api-sidebar__section">
107
- <Icon icon={section.icon} />
108
- {section.title}
109
- </h5>
110
- )}
111
- <Stack
112
- as="ul"
113
- space="var(--s0)"
114
- className="velu-api-sidebar__list"
115
- >
116
- {(section.endpoints ?? []).map((ep, j) => (
117
- <Endpoint key={j} endpoint={ep} />
118
- ))}
119
- </Stack>
120
- </React.Fragment>
121
- ))}
122
- </Stack>
123
- </Ctx.Provider>
124
- );
125
- }
1
+ import React from 'react';
2
+ import Stack from '../primitives/Stack.jsx';
3
+ import resolveIcon from '../lib/resolveIcon.jsx';
4
+ import MethodBadge from './MethodBadge.jsx';
5
+
6
+ /**
7
+ * ApiSidebar — navigation for API reference pages. Like <Sidebar> but
8
+ * flat (no nested folders): every entry is a single endpoint shown as
9
+ * a method pill + name. Entries are organized into groups, each with
10
+ * an optional icon.
11
+ *
12
+ * <ApiSidebar
13
+ * activeHref="/api/trigger"
14
+ * linkComponent={RouterLink}
15
+ * sections={[
16
+ * {
17
+ * title: 'Admin',
18
+ * icon: 'rocket',
19
+ * endpoints: [
20
+ * { method: 'POST', label: 'Trigger', href: '/api/trigger' },
21
+ * { method: 'GET', label: 'Get deployment-status',
22
+ * href: '/api/status' },
23
+ * { method: 'DELETE', label: 'Trigger Preview deployment',
24
+ * href: '/api/preview' },
25
+ * ],
26
+ * },
27
+ * ]}
28
+ * />
29
+ *
30
+ * Vertical rhythm = the Stack primitive (DRY, same as <Sidebar>);
31
+ * api.css holds only the rail / active state / row layout / icon size.
32
+ * Selection is route-driven (`endpoint.href === activeHref`, or
33
+ * `endpoint.active: true`). Router-agnostic via `linkComponent`.
34
+ *
35
+ * @typedef {Object} ApiEndpoint
36
+ * @property {string} method HTTP method — drives the MethodBadge color
37
+ * @property {string} label endpoint display name
38
+ * @property {string} [href]
39
+ * @property {boolean} [active]
40
+ *
41
+ * @param {{ sections: { title?: string, icon?: string|React.ReactNode,
42
+ * endpoints: ApiEndpoint[] }[], activeHref?: string,
43
+ * linkComponent?: React.ElementType, className?: string }} props
44
+ */
45
+
46
+ const Ctx = React.createContext({ activeHref: undefined, Link: 'a' });
47
+
48
+ function Icon({ icon }) {
49
+ const node = resolveIcon(icon);
50
+ return node ? (
51
+ <span className="velu-api-sidebar__icon" aria-hidden="true">
52
+ {node}
53
+ </span>
54
+ ) : null;
55
+ }
56
+
57
+ function Endpoint({ endpoint }) {
58
+ const { activeHref, Link } = React.useContext(Ctx);
59
+ const { method, label, href = '#', active, icon } = endpoint;
60
+ const isActive = Boolean(
61
+ active || (href != null && href === activeHref),
62
+ );
63
+ const cls = `velu-api-sidebar__item${
64
+ isActive ? ' velu-api-sidebar__item--active' : ''
65
+ }`;
66
+ // A plain page sitting in an API tab (e.g. an "Introduction") has no HTTP
67
+ // method — show its icon (if any) where the method pill would be, never a
68
+ // stray badge.
69
+ return (
70
+ <li>
71
+ <Link
72
+ className={cls}
73
+ href={href}
74
+ aria-current={isActive ? 'page' : undefined}
75
+ >
76
+ {method ? <MethodBadge method={method} /> : <Icon icon={icon} />}
77
+ <span className="velu-api-sidebar__label">{label}</span>
78
+ </Link>
79
+ </li>
80
+ );
81
+ }
82
+
83
+ export default function ApiSidebar({
84
+ sections = [],
85
+ activeHref,
86
+ linkComponent = 'a',
87
+ className = '',
88
+ ...rest
89
+ }) {
90
+ const ctx = React.useMemo(
91
+ () => ({ activeHref, Link: linkComponent }),
92
+ [activeHref, linkComponent],
93
+ );
94
+ return (
95
+ <Ctx.Provider value={ctx}>
96
+ <Stack
97
+ as="nav"
98
+ space="var(--s1)"
99
+ className={`velu-api-sidebar ${className}`.trim()}
100
+ aria-label="API reference"
101
+ {...rest}
102
+ >
103
+ {sections.map((section, i) => (
104
+ <React.Fragment key={i}>
105
+ {section.title != null && (
106
+ <h5 className="velu-api-sidebar__section">
107
+ <Icon icon={section.icon} />
108
+ {section.title}
109
+ </h5>
110
+ )}
111
+ <Stack
112
+ as="ul"
113
+ space="var(--s0)"
114
+ className="velu-api-sidebar__list"
115
+ >
116
+ {(section.endpoints ?? []).map((ep, j) => (
117
+ <Endpoint key={j} endpoint={ep} />
118
+ ))}
119
+ </Stack>
120
+ </React.Fragment>
121
+ ))}
122
+ </Stack>
123
+ </Ctx.Provider>
124
+ );
125
+ }
@@ -1,71 +1,71 @@
1
- import React, { useState } from 'react';
2
- import resolveIcon from '../lib/resolveIcon.jsx';
3
-
4
- /**
5
- * AskBar — an "ask a question" input card.
6
- *
7
- * <AskBar onSubmit={(q) => …} />
8
- *
9
- * The component owns only the card visuals (border, glow-on-focus,
10
- * multi-line input, circular send button). PLACEMENT is the consumer's
11
- * job — the docs page pins it `position: absolute` to the bottom of
12
- * the article column so content scrolls behind its opaque surface.
13
- *
14
- * - `placeholder` input placeholder (default "Ask a question…")
15
- * - `onSubmit(value)` fired on the send button or Enter (Shift+Enter
16
- * inserts a newline). Dummy-friendly — omit it and the bar is inert.
17
- *
18
- * The send affordance is a circular accent button with an up-arrow;
19
- * the card border glows in the accent color while the input is focused.
20
- */
21
-
22
- export default function AskBar({
23
- placeholder = 'Ask a question…',
24
- onSubmit,
25
- className = '',
26
- ...rest
27
- }) {
28
- const [value, setValue] = useState('');
29
-
30
- function submit() {
31
- const q = value.trim();
32
- if (!q) return;
33
- onSubmit?.(q);
34
- setValue('');
35
- }
36
-
37
- function onKeyDown(e) {
38
- // Enter sends; Shift+Enter inserts a newline.
39
- if (e.key === 'Enter' && !e.shiftKey) {
40
- e.preventDefault();
41
- submit();
42
- }
43
- }
44
-
45
- // Disable the send button until there's non-whitespace input. The
46
- // CSS reads :disabled to render it muted + un-hoverable; React reads
47
- // the attribute to short-circuit clicks too.
48
- const isEmpty = value.trim().length === 0;
49
-
50
- return (
51
- <div className={`velu-ask-bar ${className}`.trim()} {...rest}>
52
- <textarea
53
- className="velu-ask-bar__input"
54
- placeholder={placeholder}
55
- value={value}
56
- onChange={(e) => setValue(e.target.value)}
57
- onKeyDown={onKeyDown}
58
- rows={2}
59
- />
60
- <button
61
- type="button"
62
- className="velu-ask-bar__send"
63
- onClick={submit}
64
- disabled={isEmpty}
65
- aria-label="Ask"
66
- >
67
- {resolveIcon('arrow-up', { size: '1em' })}
68
- </button>
69
- </div>
70
- );
71
- }
1
+ import React, { useState } from 'react';
2
+ import resolveIcon from '../lib/resolveIcon.jsx';
3
+
4
+ /**
5
+ * AskBar — an "ask a question" input card.
6
+ *
7
+ * <AskBar onSubmit={(q) => …} />
8
+ *
9
+ * The component owns only the card visuals (border, glow-on-focus,
10
+ * multi-line input, circular send button). PLACEMENT is the consumer's
11
+ * job — the docs page pins it `position: absolute` to the bottom of
12
+ * the article column so content scrolls behind its opaque surface.
13
+ *
14
+ * - `placeholder` input placeholder (default "Ask a question…")
15
+ * - `onSubmit(value)` fired on the send button or Enter (Shift+Enter
16
+ * inserts a newline). Dummy-friendly — omit it and the bar is inert.
17
+ *
18
+ * The send affordance is a circular accent button with an up-arrow;
19
+ * the card border glows in the accent color while the input is focused.
20
+ */
21
+
22
+ export default function AskBar({
23
+ placeholder = 'Ask a question…',
24
+ onSubmit,
25
+ className = '',
26
+ ...rest
27
+ }) {
28
+ const [value, setValue] = useState('');
29
+
30
+ function submit() {
31
+ const q = value.trim();
32
+ if (!q) return;
33
+ onSubmit?.(q);
34
+ setValue('');
35
+ }
36
+
37
+ function onKeyDown(e) {
38
+ // Enter sends; Shift+Enter inserts a newline.
39
+ if (e.key === 'Enter' && !e.shiftKey) {
40
+ e.preventDefault();
41
+ submit();
42
+ }
43
+ }
44
+
45
+ // Disable the send button until there's non-whitespace input. The
46
+ // CSS reads :disabled to render it muted + un-hoverable; React reads
47
+ // the attribute to short-circuit clicks too.
48
+ const isEmpty = value.trim().length === 0;
49
+
50
+ return (
51
+ <div className={`velu-ask-bar ${className}`.trim()} {...rest}>
52
+ <textarea
53
+ className="velu-ask-bar__input"
54
+ placeholder={placeholder}
55
+ value={value}
56
+ onChange={(e) => setValue(e.target.value)}
57
+ onKeyDown={onKeyDown}
58
+ rows={2}
59
+ />
60
+ <button
61
+ type="button"
62
+ className="velu-ask-bar__send"
63
+ onClick={submit}
64
+ disabled={isEmpty}
65
+ aria-label="Ask"
66
+ >
67
+ {resolveIcon('arrow-up', { size: '1em' })}
68
+ </button>
69
+ </div>
70
+ );
71
+ }