@netlify/spark-ui 0.0.46 → 0.0.47-alpha

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 (31) hide show
  1. package/dist/assets/ChatApp.css +1 -0
  2. package/dist/chunks/compat.module.BjTzMHXJ.js +296 -0
  3. package/dist/chunks/hooks.module.DeYLzLnU.js +177 -0
  4. package/dist/chunks/{useTimeout.DOkYFG64.js → useTimeout.DYuvQwFN.js} +1 -1
  5. package/dist/components/index.d.ts +1 -0
  6. package/dist/components/preact/ChatApp/ChatApp.d.ts +2 -0
  7. package/dist/components/preact/ChatApp/ChatApp.js +5346 -0
  8. package/dist/components/preact/Modal/Modal.js +1 -1
  9. package/dist/components/preact/SearchModal/components/SearchInput.js +2 -2
  10. package/dist/components/preact/SearchModal/components/SearchLink/SearchLink.js +1 -1
  11. package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.js +1 -1
  12. package/dist/components/preact/SearchModal/components/SearchToggle/SearchToggle.js +1 -1
  13. package/dist/components/preact/SearchModal/components/SearchWindow.js +1 -1
  14. package/dist/components/preact/SearchModal/hooks/useKeyboardNav.js +1 -1
  15. package/dist/components/preact/SearchModal/hooks/useSearch.js +2 -2
  16. package/dist/components/preact/SearchModal/hooks/useSearchHotkeys.js +1 -1
  17. package/dist/components/preact/SearchModal/hooks/useSearchLogger.js +1 -1
  18. package/dist/components/preact/SearchModal/hooks/useSearchParams.js +1 -1
  19. package/dist/components/preact/SearchModal/hooks/useSearchToggles.js +1 -1
  20. package/dist/components/preact/index.d.ts +1 -0
  21. package/dist/components/preact/index.js +7 -5
  22. package/package.json +4 -1
  23. package/packages/components/CodeBlock.astro +208 -0
  24. package/packages/components/index.ts +1 -0
  25. package/packages/components/preact/ChatApp/ChatApp.css +142 -0
  26. package/packages/components/preact/ChatApp/ChatApp.tsx +237 -0
  27. package/packages/components/preact/index.ts +1 -0
  28. package/packages/global.d.ts +5 -0
  29. package/packages/styles/code-block.css +249 -0
  30. package/dist/chunks/compat.module.DT16W4Wr.js +0 -175
  31. package/dist/chunks/hooks.module.CNV9mxng.js +0 -138
@@ -1,5 +1,5 @@
1
1
  import { u as l } from "../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { D as d } from "../../../chunks/compat.module.DT16W4Wr.js";
2
+ import { D as d } from "../../../chunks/compat.module.BjTzMHXJ.js";
3
3
  const u = d(function({ children: o, className: r, ...a }, t) {
4
4
  return /* @__PURE__ */ l("dialog", { ref: t, className: r, role: "dialog", "aria-modal": "true", ...a, children: o });
5
5
  });
@@ -1,6 +1,6 @@
1
1
  import { u as e } from "../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { d as u, y as h } from "../../../../chunks/hooks.module.CNV9mxng.js";
3
- import { u as o } from "../../../../chunks/useTimeout.DOkYFG64.js";
2
+ import { d as u, y as h } from "../../../../chunks/hooks.module.DeYLzLnU.js";
3
+ import { u as o } from "../../../../chunks/useTimeout.DYuvQwFN.js";
4
4
  import d from "../../Icon/index.js";
5
5
  const I = (a) => {
6
6
  const [r, t] = u(""), { reset: c, run: i } = o((l) => {
@@ -1,5 +1,5 @@
1
1
  import { u as a } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import "../../../../../chunks/hooks.module.CNV9mxng.js";
2
+ import "../../../../../chunks/hooks.module.DeYLzLnU.js";
3
3
  import { useSearchLogger as h } from "../../hooks/useSearchLogger.js";
4
4
  import c from "../../../Icon/index.js";
5
5
  import '../../../../../assets/SearchLink.css';const k = ({ icon: n, label: s, url: r, excerpt: l, resource: e }) => {
@@ -1,5 +1,5 @@
1
1
  import { u as e } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { A as v, y as u, d as S } from "../../../../../chunks/hooks.module.CNV9mxng.js";
2
+ import { A as v, y as u, d as S } from "../../../../../chunks/hooks.module.DeYLzLnU.js";
3
3
  import L from "../../../Modal/Modal.js";
4
4
  import d from "../../../KeyboardKey/KeyboardKey.js";
5
5
  import k from "../SearchWindow.js";
@@ -1,5 +1,5 @@
1
1
  import { u as e } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { D as t } from "../../../../../chunks/compat.module.DT16W4Wr.js";
2
+ import { D as t } from "../../../../../chunks/compat.module.BjTzMHXJ.js";
3
3
  import o from "../../../Icon/index.js";
4
4
  import '../../../../../assets/SearchToggle.css';const s = t(function(r, a) {
5
5
  return /* @__PURE__ */ e("button", { id: r.id, ref: a, class: "n-search-toggle", disabled: !0, "data-ntl-search-toggle": !0, children: [
@@ -1,5 +1,5 @@
1
1
  import { u as e } from "../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { T as o } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
+ import { T as o } from "../../../../chunks/hooks.module.DeYLzLnU.js";
3
3
  import t from "./SearchHeading/SearchHeading.js";
4
4
  import a from "./SearchLink/SearchLink.js";
5
5
  const h = ({
@@ -1,4 +1,4 @@
1
- import { y as l } from "../../../../chunks/hooks.module.CNV9mxng.js";
1
+ import { y as l } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
2
  function s(r, t, o, c) {
3
3
  l(() => {
4
4
  if (!r) return;
@@ -1,5 +1,5 @@
1
- import { d as g, A as w } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
- import { u as S } from "../../../../chunks/useTimeout.DOkYFG64.js";
1
+ import { d as g, A as w } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
+ import { u as S } from "../../../../chunks/useTimeout.DYuvQwFN.js";
3
3
  function x() {
4
4
  const [l, r] = g({
5
5
  searchTerm: "",
@@ -1,4 +1,4 @@
1
- import { y as u } from "../../../../chunks/hooks.module.CNV9mxng.js";
1
+ import { y as u } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
2
  function a(t, r, n, o) {
3
3
  u(() => {
4
4
  if (!t) return;
@@ -1,4 +1,4 @@
1
- import { A as y, y as h, q as k } from "../../../../chunks/hooks.module.CNV9mxng.js";
1
+ import { A as y, y as h, q as k } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
2
  class s {
3
3
  /**
4
4
  * Pushes an event payload into the dataLayer.
@@ -1,4 +1,4 @@
1
- import { y as c } from "../../../../chunks/hooks.module.CNV9mxng.js";
1
+ import { y as c } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
2
  function n(r, o, a) {
3
3
  c(() => {
4
4
  if (typeof location > "u" || r) return;
@@ -1,4 +1,4 @@
1
- import { y as l } from "../../../../chunks/hooks.module.CNV9mxng.js";
1
+ import { y as l } from "../../../../chunks/hooks.module.DeYLzLnU.js";
2
2
  function i(c, r) {
3
3
  l(() => {
4
4
  if (!c) return;
@@ -4,5 +4,6 @@ export { default as Icon } from './Icon';
4
4
  export { default as SearchLink } from './SearchModal/components/SearchLink/SearchLink';
5
5
  export { default as SearchHeading } from './SearchModal/components/SearchHeading/SearchHeading';
6
6
  export { default as SearchToggle } from './SearchModal/components/SearchToggle/SearchToggle';
7
+ export { default as ChatApp } from './ChatApp/ChatApp';
7
8
  export { SearchModal } from './SearchModal';
8
9
  export { type IconName } from './Icon';
@@ -1,18 +1,20 @@
1
1
  import { default as t } from "./KeyboardKey/KeyboardKey.js";
2
2
  import { default as d } from "./Modal/Modal.js";
3
- import { default as m } from "./Icon/index.js";
3
+ import { default as l } from "./Icon/index.js";
4
4
  import { default as s } from "./SearchModal/components/SearchLink/SearchLink.js";
5
5
  import { default as x } from "./SearchModal/components/SearchHeading/SearchHeading.js";
6
6
  import { default as h } from "./SearchModal/components/SearchToggle/SearchToggle.js";
7
+ import { default as S } from "./ChatApp/ChatApp.js";
7
8
  import "preact";
8
- import "../../chunks/hooks.module.CNV9mxng.js";
9
- import { default as S } from "./SearchModal/components/SearchModal/SearchModal.js";
9
+ import "../../chunks/hooks.module.DeYLzLnU.js";
10
+ import { default as n } from "./SearchModal/components/SearchModal/SearchModal.js";
10
11
  export {
11
- m as Icon,
12
+ S as ChatApp,
13
+ l as Icon,
12
14
  t as KeyboardKey,
13
15
  d as Modal,
14
16
  x as SearchHeading,
15
17
  s as SearchLink,
16
- S as SearchModal,
18
+ n as SearchModal,
17
19
  h as SearchToggle
18
20
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/spark-ui",
3
3
  "description": "Assets, design tokens, components, and utilities",
4
- "version": "0.0.46",
4
+ "version": "0.0.47-alpha",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -32,8 +32,11 @@
32
32
  "./analytics": "./packages/analytics/index.ts"
33
33
  },
34
34
  "dependencies": {
35
+ "@kapaai/react-sdk": "^0.0.5",
35
36
  "@preact/preset-vite": "^2.10.1",
37
+ "@shikijs/transformers": "^3.3.0",
36
38
  "glob": "^11.0.1",
39
+ "marked": "^15.0.11",
37
40
  "preact": "^10.26.4",
38
41
  "vite": "^6.2.5",
39
42
  "vite-plugin-dts": "^4.5.3",
@@ -0,0 +1,208 @@
1
+ ---
2
+ import { Code } from 'astro:components';
3
+ import '../styles/code-block.css';
4
+ import poimandresTheme from '../../themes/poimandres.json';
5
+ import {
6
+ transformerMetaHighlight,
7
+ transformerNotationDiff,
8
+ transformerNotationFocus,
9
+ } from '@shikijs/transformers';
10
+
11
+ interface Props {
12
+ code: string;
13
+ lang?: string;
14
+ highlight?: string;
15
+ del?: string;
16
+ ins?: string;
17
+ frame?: 'code' | 'terminal' | 'none';
18
+ theme?: string;
19
+ wrap?: boolean;
20
+ title?: string;
21
+ class?: string;
22
+ showLineNumbers?: boolean;
23
+ }
24
+
25
+ const {
26
+ code,
27
+ lang = '',
28
+ highlight = '',
29
+ del = '',
30
+ ins = '',
31
+ frame = 'none',
32
+ theme = 'poimandres',
33
+ wrap = false,
34
+ title = '',
35
+ class: className,
36
+ showLineNumbers = false,
37
+ ...rest
38
+ } = Astro.props;
39
+
40
+ // Process highlighting ranges (e.g. {2-3,6})
41
+ const highlightRanges = highlight
42
+ ? highlight
43
+ .replace(/[{}]/g, '')
44
+ .split(',')
45
+ .map((range: string) => {
46
+ if (range.includes('-')) {
47
+ const [start, end] = range.split('-').map(Number);
48
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
49
+ }
50
+ return [Number(range)];
51
+ })
52
+ .flat()
53
+ : [];
54
+
55
+ // Process deleted lines
56
+ const delRanges = del
57
+ ? del
58
+ .split(',')
59
+ .map((range: string) => {
60
+ if (range.includes('-')) {
61
+ const [start, end] = range.split('-').map(Number);
62
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
63
+ }
64
+ return [Number(range)];
65
+ })
66
+ .flat()
67
+ : [];
68
+
69
+ // Process inserted lines
70
+ const insRanges = ins
71
+ ? ins
72
+ .split(',')
73
+ .map((range: string) => {
74
+ if (range.includes('-')) {
75
+ const [start, end] = range.split('-').map(Number);
76
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
77
+ }
78
+ return [Number(range)];
79
+ })
80
+ .flat()
81
+ : [];
82
+
83
+ // Apply highlighting, deletions, and insertions using Shiki's transformers
84
+ const codeWithMeta = code
85
+ .split('\n')
86
+ .map((line: string, i: number) => {
87
+ const lineNumber = i + 1;
88
+ const meta = [];
89
+
90
+ if (highlightRanges.includes(lineNumber)) {
91
+ meta.push('focus');
92
+ }
93
+ if (delRanges.includes(lineNumber)) {
94
+ meta.push('--');
95
+ }
96
+ if (insRanges.includes(lineNumber)) {
97
+ meta.push('++');
98
+ }
99
+
100
+ return meta.length > 0 ? `${line} // [!code ${meta.join(' ')}]` : line;
101
+ })
102
+ .join('\n');
103
+
104
+ // Determine which theme to use
105
+ const selectedTheme = theme === 'poimandres' ? poimandresTheme : theme;
106
+
107
+ // Determine if we should show line numbers
108
+ const showNumbers = showLineNumbers && code.split('\n').length > 1;
109
+ ---
110
+
111
+ <div
112
+ class:list={[
113
+ 'code-block',
114
+ frame === 'terminal' && 'terminal-frame',
115
+ frame === 'code' && 'code-frame',
116
+ frame === 'none' && 'no-frame',
117
+ showNumbers && 'with-line-numbers',
118
+ className,
119
+ ]}
120
+ {...rest}
121
+ >
122
+ {
123
+ (title || lang) && frame !== 'none' && frame !== 'terminal' && (
124
+ <div class="code-block-title">
125
+ {lang && <span class="code-language">{lang}</span>}
126
+ {title && <span class="code-title">{title}</span>}
127
+ </div>
128
+ )
129
+ }
130
+ <div class="code-block-content">
131
+ <Code
132
+ code={codeWithMeta}
133
+ lang={lang}
134
+ theme={selectedTheme}
135
+ wrap={wrap}
136
+ transformers={[
137
+ transformerMetaHighlight(),
138
+ transformerNotationDiff(),
139
+ transformerNotationFocus(),
140
+ ]}
141
+ />
142
+ <button class="copy-button" aria-label="Copy code to clipboard" data-tooltip="Copy">
143
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="copy-icon">
144
+ <path
145
+ d="M18 3c0-1.657-1.343-3-3-3v0h-12c-1.657 0-3 1.343-3 3v0 12c0 1.657 1.343 3 3 3v0h12c1.657 0 3-1.343 3-3v0zM15 1.5c0.828 0 1.5 0.672 1.5 1.5v0 12c0 0.828-0.672 1.5-1.5 1.5v0h-12c-0.828 0-1.5-0.672-1.5-1.5v0-12c0-0.828 0.672-1.5 1.5-1.5v0zM21 7.5c0.828 0 1.5 0.672 1.5 1.5v0 12c0 0.828-0.672 1.5-1.5 1.5v0h-12c-0.828 0-1.5-0.672-1.5-1.5v0-1.5h-1.5v1.5c0 1.657 1.343 3 3 3v0h12c1.657 0 3-1.343 3-3v0-12c0-1.657-1.343-3-3-3v0h-1.5v1.5z"
146
+ ></path>
147
+ </svg>
148
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="check-icon">
149
+ <path
150
+ d="M22.942 6.582l-13.778 13.778c-0.156 0.156-0.371 0.253-0.609 0.253s-0.453-0.097-0.609-0.253v0l-6.028-6.028c-0.156-0.156-0.252-0.371-0.252-0.609 0-0.476 0.386-0.862 0.862-0.862 0.238 0 0.453 0.096 0.609 0.252v0l5.418 5.42 13.168-13.169c0.156-0.156 0.371-0.252 0.609-0.252 0.476 0 0.862 0.386 0.862 0.862 0 0.238-0.096 0.453-0.252 0.609v0z"
151
+ ></path>
152
+ </svg>
153
+ </button>
154
+ </div>
155
+ </div>
156
+
157
+ <script>
158
+ document.addEventListener('astro:page-load', () => {
159
+ setupCopyBtn();
160
+ });
161
+
162
+ // Also initialize immediately in case the page is not using transitions
163
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
164
+ setupCopyBtn();
165
+ } else {
166
+ document.addEventListener('DOMContentLoaded', setupCopyBtn);
167
+ }
168
+
169
+ function setupCopyBtn() {
170
+ const copyButtons = document.querySelectorAll(
171
+ '.code-block .copy-button'
172
+ ) as NodeListOf<HTMLButtonElement>;
173
+ copyButtons.forEach(button => {
174
+ button.addEventListener('click', async () => {
175
+ const codeBlock = button.closest('.code-block');
176
+ if (!codeBlock) return;
177
+
178
+ const pre = codeBlock.querySelector('pre');
179
+ if (!pre) return;
180
+
181
+ // Get the text content, remove the Shiki annotations if present
182
+ const rawText = pre.textContent || '';
183
+ const code = rawText.replace(/\/\/\s*\[!.*?\]/g, '').trim();
184
+
185
+ // Copy to clipboard
186
+ try {
187
+ await navigator.clipboard.writeText(code);
188
+ button.classList.add('copied');
189
+ button.setAttribute('data-tooltip', 'Copied!');
190
+ setTimeout(() => {
191
+ button.classList.remove('copied');
192
+ button.setAttribute('data-tooltip', 'Copy');
193
+ button.blur();
194
+ }, 2000);
195
+ } catch (error) {
196
+ console.error('Failed to copy code: ', error);
197
+ button.classList.add('error');
198
+ button.setAttribute('data-tooltip', 'Failed to copy!');
199
+ setTimeout(() => {
200
+ button.classList.remove('error');
201
+ button.setAttribute('data-tooltip', 'Copy');
202
+ button.blur();
203
+ }, 2000);
204
+ }
205
+ });
206
+ });
207
+ }
208
+ </script>
@@ -6,6 +6,7 @@ export { default as SearchLink } from './preact/SearchModal/components/SearchLin
6
6
  export { default as SearchHeading } from './preact/SearchModal/components/SearchHeading/SearchHeading';
7
7
  export { default as SearchToggle } from './preact/SearchModal/components/SearchToggle/SearchToggle';
8
8
  export { default as SearchModal } from './preact/SearchModal/components/SearchModal/SearchModal';
9
+ export { default as ChatApp } from './preact/ChatApp/ChatApp';
9
10
  export { type IconName } from './preact/Icon';
10
11
 
11
12
  // Astro components
@@ -0,0 +1,142 @@
1
+ /* styles.css */
2
+
3
+ /* Main container */
4
+ .chatbot-container {
5
+ display: flex;
6
+ padding: 3rem;
7
+ height: 100vh;
8
+ background-color: #f7fafc;
9
+ }
10
+
11
+ .chatbot-wrapper {
12
+ display: flex;
13
+ flex-direction: column;
14
+ width: 100%;
15
+ max-width: 1024px;
16
+ margin: 0 auto;
17
+ background-color: white;
18
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
19
+ border-radius: 8px;
20
+ overflow: hidden;
21
+ }
22
+
23
+ /* Header */
24
+ .header {
25
+ background-color: #2d3748;
26
+ color: white;
27
+ padding: 1rem;
28
+ display: flex;
29
+ justify-content: space-between;
30
+ align-items: center;
31
+ }
32
+
33
+ .header-left {
34
+ display: flex;
35
+ align-items: center;
36
+ }
37
+
38
+ .header-title {
39
+ font-weight: bold;
40
+ font-size: 1.25rem;
41
+ }
42
+
43
+ .new-chat-button {
44
+ display: flex;
45
+ align-items: center;
46
+ background-color: #4a5568;
47
+ border-radius: 0.375rem;
48
+ padding: 0.25rem 0.75rem;
49
+ font-size: 0.875rem;
50
+ }
51
+
52
+ .icon {
53
+ margin-right: 0.25rem;
54
+ }
55
+
56
+ /* Chat container */
57
+ .chat-container {
58
+ flex: 1;
59
+ overflow-y: auto;
60
+ padding: 1rem;
61
+ }
62
+
63
+ /* Error message */
64
+ .error-message {
65
+ background-color: #fed7d7;
66
+ border: 1px solid #fbd5d5;
67
+ color: #9b2c2c;
68
+ padding: 1rem;
69
+ border-radius: 0.375rem;
70
+ margin-bottom: 1rem;
71
+ }
72
+
73
+ .error-title {
74
+ font-weight: bold;
75
+ }
76
+
77
+ /* Message bubbles */
78
+ .message {
79
+ display: flex;
80
+ flex-direction: column;
81
+ margin-bottom: 1rem;
82
+ }
83
+
84
+ .message-right {
85
+ display: flex;
86
+ justify-content: flex-end;
87
+ }
88
+
89
+ .message-bubble {
90
+ padding: 1rem;
91
+ border-radius: 0.5rem;
92
+ max-width: 75%;
93
+ }
94
+
95
+ .user-message {
96
+ background-color: #4299e1;
97
+ color: white;
98
+ }
99
+
100
+ .bot-message {
101
+ background-color: #edf2f7;
102
+ color: #2d3748;
103
+ }
104
+
105
+ /* Input area */
106
+ .input-area {
107
+ border-top: 1px solid #e2e8f0;
108
+ padding: 1rem;
109
+ }
110
+
111
+ .input-form {
112
+ display: flex;
113
+ align-items: center;
114
+ }
115
+
116
+ .input-field {
117
+ flex: 1;
118
+ background-color: #edf2f7;
119
+ border-radius: 0.5rem;
120
+ padding: 0.5rem 1rem;
121
+ }
122
+
123
+ .input {
124
+ width: 100%;
125
+ background-color: transparent;
126
+ border: none;
127
+ outline: none;
128
+ }
129
+
130
+ .stop-button,
131
+ .send-button {
132
+ margin-left: 0.5rem;
133
+ background-color: #3182ce;
134
+ border-radius: 9999px;
135
+ padding: 0.5rem;
136
+ color: white;
137
+ }
138
+
139
+ .stop-icon {
140
+ width: 1rem;
141
+ height: 1rem;
142
+ }