Skip to content

Commit 660cb51

Browse files
committed
!fixup
1 parent 995d428 commit 660cb51

File tree

8 files changed

+492
-354
lines changed

8 files changed

+492
-354
lines changed

specs/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
"prepare": "rm -rf public && mkdir public && cp -r ../node_modules/instantsearch.css/themes public/themes"
1919
},
2020
"devDependencies": {
21-
"@types/node": "18.11.13",
22-
"@codesandbox/sandpack-react": "2.10.0",
21+
"@types/node": "20.10.0",
22+
"@codesandbox/sandpack-react": "2.19.1",
2323
"@codesandbox/sandpack-themes": "2.0.21",
2424
"dedent": "1.5.1",
2525
"astro": "1.6.14",
26+
"@astrojs/react": "1.2.2",
2627
"instantsearch.css": "8.5.0",
2728
"sass": "1.56.2"
2829
}

specs/src/components/Sandbox.tsx

+30-22
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ const settings = {
1212
}
1313
</style>
1414
<div id="custom"></div>
15+
<hr />
1516
<div id="searchbox"></div>
1617
<div id="hits"></div>
1718
`,
1819
preamble: /* JS */ `
1920
import 'instantsearch.css/themes/satellite-min.css';
20-
import algoliasearch from 'algoliasearch/lite';
21+
import { liteClient as algoliasearch } from 'algoliasearch/lite';
2122
import instantsearch from 'instantsearch.js';
2223
import { history } from 'instantsearch.js/es/lib/routers';
2324
import { searchBox, hits } from 'instantsearch.js/es/widgets';
@@ -32,30 +33,30 @@ const settings = {
3233
routing: {
3334
router: history({
3435
cleanUrlOnDispose: false,
35-
})
36-
}
36+
}),
37+
},
3738
});
3839
3940
search.addWidgets([
40-
...createWidgets(document.querySelector('#custom')),
41+
...createWidgets(() =>
42+
document.querySelector('#custom').appendChild(document.createElement('div'))
43+
),
4144
searchBox({
4245
container: '#searchbox',
4346
}),
4447
hits({
4548
container: '#hits',
4649
templates: {
47-
item: (hit, { components }) => components.Highlight({ attribute: 'name', hit }),
50+
item: (hit, { components }) =>
51+
components.Highlight({ attribute: 'name', hit }),
4852
},
4953
}),
5054
]);
5155
5256
search.start();
5357
`,
5458
dependencies: {
55-
// TODO: use current version somehow, both locally and in the built website
56-
'instantsearch.js': 'latest',
57-
'instantsearch.css': 'latest',
58-
algoliasearch: 'latest',
59+
algoliasearch: '5.1.1',
5960
},
6061
filename: '/widget.ts',
6162
},
@@ -72,7 +73,7 @@ const settings = {
7273
import 'instantsearch.css/themes/satellite-min.css';
7374
import React from "react";
7475
import { createRoot } from "react-dom/client";
75-
import algoliasearch from "algoliasearch/lite";
76+
import { liteClient as algoliasearch } from "algoliasearch/lite";
7677
import { history } from "instantsearch.js/es/lib/routers";
7778
import { InstantSearch, SearchBox, Hits, Highlight } from "react-instantsearch";
7879
import { widgets } from "./widget.tsx";
@@ -91,6 +92,7 @@ const settings = {
9192
}}
9293
>
9394
{widgets}
95+
<hr />
9496
<SearchBox />
9597
<Hits hitComponent={Hit}/>
9698
</InstantSearch>
@@ -101,11 +103,9 @@ const settings = {
101103
}
102104
`,
103105
dependencies: {
104-
react: 'latest',
105-
'react-dom': 'latest',
106-
algoliasearch: 'latest',
107-
'instantsearch.css': 'latest',
108-
'react-instantsearch': 'latest',
106+
react: '18.2.0',
107+
'react-dom': '18.2.0',
108+
algoliasearch: '5.1.1',
109109
},
110110
filename: '/widget.tsx',
111111
},
@@ -121,7 +121,7 @@ const settings = {
121121
preamble: `
122122
import "instantsearch.css/themes/satellite-min.css";
123123
import Vue from "vue";
124-
import algoliasearch from "algoliasearch/lite";
124+
import { liteClient as algoliasearch } from "algoliasearch/lite";
125125
import { history } from "instantsearch.js/es/lib/routers";
126126
import { AisInstantSearch, AisHits, AisSearchBox } from "vue-instantsearch/vue2/es";
127127
import Widget from "./Widget.vue";
@@ -149,15 +149,13 @@ const settings = {
149149
}
150150
},
151151
},
152-
[h(Widget), h(AisSearchBox), h(AisHits)]
152+
[h(Widget), h('hr'), h(AisSearchBox), h(AisHits)]
153153
),
154154
}).$mount("#app");
155155
`,
156156
dependencies: {
157-
vue: '2',
158-
algoliasearch: 'latest',
159-
'instantsearch.css': 'latest',
160-
'vue-instantsearch': 'latest',
157+
vue: '2.7.14',
158+
algoliasearch: '5.1.1',
161159
},
162160
filename: '/Widget.vue',
163161
},
@@ -166,9 +164,14 @@ const settings = {
166164
export default function Sandbox({
167165
code,
168166
flavor,
167+
modules,
169168
}: {
170169
code: string;
171170
flavor: 'react' | 'js' | 'vue';
171+
modules: {
172+
files: Record<string, string>;
173+
dependencies: Record<string, string>;
174+
};
172175
}) {
173176
const { preamble, html, filename, dependencies } = settings[flavor];
174177
return (
@@ -184,12 +187,17 @@ export default function Sandbox({
184187
[filename]: {
185188
code,
186189
},
190+
...modules.files,
187191
}}
188192
customSetup={{
189-
dependencies,
193+
dependencies: {
194+
...dependencies,
195+
...modules.dependencies,
196+
},
190197
entry: '/index.js',
191198
}}
192199
options={{
200+
editorHeight: 500,
193201
activeFile: filename,
194202
showNavigator: true,
195203
}}

specs/src/components/WidgetContent.astro

+26-16
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { Code } from 'astro/components';
33
import type { WidgetFrontmatter } from '../types';
44
import ThemeSelector from './ThemeSelector.astro';
55
import Sandbox from './Sandbox.jsx';
6-
import { getSandpackCssText } from "@codesandbox/sandpack-react";
6+
import { getSandpackCssText } from '@codesandbox/sandpack-react';
7+
import getFiles from '../getDependencyContent';
78
9+
const modules = await getFiles();
810
911
type Props = {
1012
frontmatter: WidgetFrontmatter;
@@ -114,21 +116,29 @@ const title = frontmatter.title;
114116
)
115117
}
116118

117-
{frontmatter.examples ? (
118-
<>
119-
<h3 id="example">Usage</h3>
120-
<!-- TODO: theme is implied dark? -->
121-
<style is:inline set:html={getSandpackCssText()}></style>
122-
{frontmatter.examples.map(({ code, flavor, library }) => (
123-
<div class="example">
124-
<h4>{library}</h4>
125-
<div class="code-output">
126-
<Sandbox code={code} flavor={flavor} client:load />
127-
</div>
128-
</div>
129-
))}
130-
</>
131-
) : null}
119+
{
120+
frontmatter.examples ? (
121+
<>
122+
<h3 id="example">Usage</h3>
123+
<style id="sandpack" is:inline set:html={getSandpackCssText()} />
124+
{frontmatter.examples.map(({ code, flavor, library }) => (
125+
<details class="example">
126+
<summary style="cursor: pointer">
127+
<h4 style="display: inline-block; margin: 0;">{library}</h4>
128+
</summary>
129+
<div class="code-output">
130+
<Sandbox
131+
code={code}
132+
flavor={flavor}
133+
modules={modules[flavor]}
134+
client:load
135+
/>
136+
</div>
137+
</details>
138+
))}
139+
</>
140+
) : null
141+
}
132142

133143
<h3 id="css-classes">CSS classes</h3>
134144
{

specs/src/getDependencyContent.ts

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { readdir, readFile } from 'fs/promises';
2+
import { join } from 'path';
3+
4+
const cache = new Map();
5+
async function getFilesFromDir(dir: string) {
6+
if (cache.has(dir)) {
7+
return cache.get(dir);
8+
}
9+
const output = (
10+
await readdir(dir, {
11+
withFileTypes: true,
12+
recursive: true,
13+
})
14+
)
15+
.filter((file) => file.isFile())
16+
.map((file) => join(file.path.replace('../packages/', ''), file.name));
17+
cache.set(dir, output);
18+
return output;
19+
}
20+
21+
async function getFiles(flavor: 'react' | 'js' | 'vue') {
22+
const localDependencies = [
23+
'instantsearch.css',
24+
'instantsearch-ui-components',
25+
'instantsearch.js',
26+
flavor === 'react' && 'react-instantsearch',
27+
flavor === 'react' && 'react-instantsearch-core',
28+
flavor === 'vue' && 'vue-instantsearch',
29+
].filter(Boolean);
30+
31+
return {
32+
files: Object.fromEntries(
33+
await Promise.all(
34+
[
35+
'instantsearch.css/package.json',
36+
...(await getFilesFromDir('../packages/instantsearch.css/themes')),
37+
'instantsearch-ui-components/package.json',
38+
...(await getFilesFromDir(
39+
'../packages/instantsearch-ui-components/dist'
40+
)),
41+
'instantsearch.js/package.json',
42+
...(await getFilesFromDir('../packages/instantsearch.js/es')),
43+
...(flavor === 'react'
44+
? await getFilesFromDir('../packages/instantsearch.js/cjs')
45+
: []),
46+
flavor === 'react' && 'react-instantsearch/package.json',
47+
...(flavor === 'react'
48+
? await getFilesFromDir('../packages/react-instantsearch/dist')
49+
: []),
50+
flavor === 'react' && 'react-instantsearch-core/package.json',
51+
...(flavor === 'react'
52+
? await getFilesFromDir('../packages/react-instantsearch-core/dist')
53+
: []),
54+
flavor === 'vue' && 'vue-instantsearch/package.json',
55+
...(flavor === 'vue'
56+
? await getFilesFromDir('../packages/vue-instantsearch/vue2/es')
57+
: []),
58+
]
59+
.filter(Boolean)
60+
.map(async (file) => [
61+
`/node_modules/${file}`,
62+
{
63+
code: await readFile(`../packages/${file}`, 'utf-8'),
64+
hidden: true,
65+
},
66+
])
67+
)
68+
),
69+
dependencies: Object.assign(
70+
{},
71+
...(await Promise.all(
72+
localDependencies.map(async (pkg) =>
73+
Object.fromEntries(
74+
Object.entries(
75+
JSON.parse(
76+
await readFile(`../packages/${pkg}/package.json`, 'utf-8')
77+
).dependencies || {}
78+
).filter(([key]) => !localDependencies.includes(key))
79+
)
80+
)
81+
))
82+
),
83+
};
84+
}
85+
86+
export default async function getDependencyContent() {
87+
return {
88+
react: await getFiles('react'),
89+
js: await getFiles('js'),
90+
vue: await getFiles('vue'),
91+
};
92+
}

0 commit comments

Comments
 (0)