aidos-ui 3.0.0 → 3.0.1

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 (64) hide show
  1. package/README.md +2 -2
  2. package/dist/Badge.d.ts +1 -2
  3. package/dist/BaseLink.d.ts +1 -1
  4. package/dist/BaseList.d.ts +1 -1
  5. package/dist/BaseListAddOn.d.ts +1 -1
  6. package/dist/BaseListItem.d.ts +1 -1
  7. package/dist/BaseView.d.ts +1 -1
  8. package/dist/Box.d.ts +1 -2
  9. package/dist/Card.d.ts +1 -1
  10. package/dist/Checkbox.d.ts +1 -2
  11. package/dist/Circle.d.ts +1 -2
  12. package/dist/Column.d.ts +1 -1
  13. package/dist/DarkMode.d.ts +2 -2
  14. package/dist/DatePicker.d.ts +1 -2
  15. package/dist/DesignBook.d.ts +1 -2
  16. package/dist/Dialog.d.ts +2 -2
  17. package/dist/Dropdown.d.ts +1 -2
  18. package/dist/FlexLayout.d.ts +1 -1
  19. package/dist/Icon.d.ts +1 -1
  20. package/dist/List.d.ts +2 -2
  21. package/dist/List.js +10 -2
  22. package/dist/List.js.map +1 -1
  23. package/dist/ListButtonItem.d.ts +1 -1
  24. package/dist/ListDivider.d.ts +1 -2
  25. package/dist/ListHeaderItem.d.ts +1 -1
  26. package/dist/ListItem.d.ts +1 -1
  27. package/dist/ListLinkItem.d.ts +1 -1
  28. package/dist/ListSpacer.d.ts +1 -2
  29. package/dist/Popover.d.ts +2 -2
  30. package/dist/ProgressBar.d.ts +1 -2
  31. package/dist/ProgressCircle.d.ts +1 -2
  32. package/dist/Providers.d.ts +1 -1
  33. package/dist/RootView.d.ts +1 -1
  34. package/dist/Router.d.ts +1 -2
  35. package/dist/RouterState.d.ts +1 -1
  36. package/dist/Row.d.ts +1 -1
  37. package/dist/StackContext.d.ts +1 -1
  38. package/dist/StaticCheckbox.d.ts +1 -2
  39. package/dist/Sublist.d.ts +3 -2
  40. package/dist/Sublist.js +2 -2
  41. package/dist/Sublist.js.map +1 -1
  42. package/dist/SubmitIconInput.d.ts +1 -2
  43. package/dist/Tabs.d.ts +1 -1
  44. package/dist/Text.d.ts +8 -8
  45. package/dist/TextInputWithState.d.ts +1 -1
  46. package/dist/TextPairing.d.ts +1 -1
  47. package/dist/Tooltip.d.ts +1 -1
  48. package/dist/jss.d.ts +2 -2
  49. package/dist/stateMachineContextFactory.d.ts +1 -1
  50. package/package.json +8 -3
  51. package/public/index.json +1 -0
  52. package/scripts/embeddings.js +93 -0
  53. package/scripts/publish.js +1 -0
  54. package/scripts/test_embeddings.js +47 -0
  55. package/src/List.tsx +12 -2
  56. package/src/Sublist.tsx +3 -0
  57. package/src/docs/mdx.tsx +99 -0
  58. package/src/docs/pages.ts +112 -0
  59. package/src/pages/Badge.mdx +1 -1
  60. package/src/pages/Button.mdx +4 -4
  61. package/src/pages/Link.mdx +3 -3
  62. package/src/pages/List.mdx +99 -1
  63. package/src/pages/_app.tsx +126 -241
  64. package/src/pages/index.mdx +1 -1
@@ -1,9 +1,8 @@
1
1
  import type { AppProps } from "next/app";
2
2
  import Link from "next/link";
3
3
  import Head from "next/head";
4
- import React, { useEffect, useRef, useState } from "react";
4
+ import React, { useCallback, useEffect, useRef, useState } from "react";
5
5
  import {
6
- Size,
7
6
  TABLET,
8
7
  cssVar,
9
8
  darkTheme,
@@ -14,13 +13,9 @@ import {
14
13
  mobile,
15
14
  tablet,
16
15
  } from "../jss";
17
- import { MDXProvider } from "@mdx-js/react";
18
16
  import { Providers } from "../Providers";
19
17
  import { BaseView } from "../BaseView";
20
- import { H1, H2, H3, Li, P, Span } from "../Text";
21
18
  import { ListDivider } from "../ListDivider";
22
- import { ListHeaderItem } from "../ListHeaderItem";
23
- import { Roboto } from "next/font/google";
24
19
  import { List } from "../List";
25
20
  import { ListLinkItem } from "../ListLinkItem";
26
21
  import { Row } from "../Row";
@@ -36,208 +31,26 @@ import "./prism.css";
36
31
  import { IconButton } from "../IconButton";
37
32
  import { Column } from "../Column";
38
33
  import { Icon } from "../Icon";
39
- import { BaseLink, BaseLinkComponentOverrideContext } from "../BaseLink";
40
-
41
- const monospace = Roboto({ weight: "400", subsets: ["latin"] });
42
-
43
- type PageLink = {
44
- type: "link";
45
- page: string;
46
- name?: string;
47
- headlineSize?: Size;
48
- headlineBold?: boolean;
49
- };
50
-
51
- type Page =
52
- | PageLink
53
- | {
54
- type: "section";
55
- label: string;
56
- content: Array<PageLink>;
57
- };
58
-
59
- const pages: Array<Page> = [
60
- {
61
- type: "link",
62
- page: "",
63
- name: "Aidos UI",
64
- headlineSize: "large",
65
- headlineBold: true,
66
- },
67
- {
68
- type: "section",
69
- label: "CSS",
70
- content: [{ type: "link", page: "css-in-js", name: "jss" }],
71
- },
72
- {
73
- type: "section",
74
- label: "Primary components",
75
- content: [
76
- { type: "link", page: "FlexLayout" },
77
- { type: "link", page: "Text" },
78
- { type: "link", page: "TextPairing" },
79
- { type: "link", page: "Icon" },
80
- ],
81
- },
82
- {
83
- type: "section",
84
- label: "Buttons and links",
85
- content: [
86
- { type: "link", page: "Button" },
87
- { type: "link", page: "Link" },
88
- { type: "link", page: "IconButton" },
89
- ],
90
- },
91
- {
92
- type: "section",
93
- label: "Inputs",
94
- content: [
95
- { type: "link", page: "TextInput" },
96
- { type: "link", page: "RangeInput" },
97
- { type: "link", page: "TimeInput" },
98
- { type: "link", page: "Checkbox" },
99
- ],
100
- },
101
- {
102
- type: "section",
103
- label: "List",
104
- content: [
105
- { type: "link", page: "List" },
106
- { type: "link", page: "ListHeader" },
107
- { type: "link", page: "navigation", name: "List navigation" },
108
- ],
109
- },
110
- {
111
- type: "section",
112
- label: "Modals",
113
- content: [
114
- { type: "link", page: "Dialog" },
115
- { type: "link", page: "Popover" },
116
- { type: "link", page: "Tooltip" },
117
- ],
118
- },
119
- {
120
- type: "section",
121
- label: "Visual indicators",
122
- content: [
123
- { type: "link", page: "Badge" },
124
- { type: "link", page: "ProgressBar" },
125
- { type: "link", page: "ProgressCircle" },
126
- ],
127
- },
128
- {
129
- type: "section",
130
- label: "Complex components",
131
- content: [
132
- { type: "link", page: "Tabs" },
133
- { type: "link", page: "Calendar" },
134
- ],
135
- },
136
- {
137
- type: "section",
138
- label: "Hooks",
139
- content: [
140
- { type: "link", page: "useCookie" },
141
- { type: "link", page: "useNavigation" },
142
- { type: "link", page: "useKeyboard" },
143
- { type: "link", page: "useRefEffect" },
144
- { type: "link", page: "usePromise" },
145
- ],
146
- },
147
- {
148
- type: "section",
149
- label: "Utils",
150
- content: [{ type: "link", page: "Hashing" }],
151
- },
152
- ];
153
-
154
- const components = {
155
- h1: (props) => (
156
- <H1 jsStyle={{ marginBottom: cssVar("--spacing-xl") }} {...props} />
157
- ),
158
- h2: (props) => (
159
- <H2
160
- id={props.children
161
- .replace(/[A-Z]/g, (m) => m.toLowerCase())
162
- .replace(/\s/g, "-")
163
- .replace(/\?/g, "")}
164
- jsStyle={{ marginBottom: cssVar("--spacing-l") }}
165
- {...props}
166
- />
167
- ),
168
- h3: (props) => {
169
- return <H3 {...props} />;
170
- },
171
- p: (props) => (
172
- <P jsStyle={{ marginBottom: cssVar("--spacing-m") }} {...props} />
173
- ),
174
- span: (props) => <Span {...props} />,
175
- li: (props) => (
176
- <Li jsStyle={{ marginBottom: cssVar("--spacing-s") }} {...props} />
177
- ),
178
- a: (props) => {
179
- return (
180
- <BaseLink
181
- bare
182
- color="positive"
183
- jsStyle={{
184
- display: "inline-block",
185
- paddingBottom: cssVar("--spacing-s"),
186
- paddingTop: cssVar("--spacing-s"),
187
- }}
188
- href={props.href}
189
- >
190
- {props.children}
191
- </BaseLink>
192
- );
193
- },
194
- hr: () => (
195
- <BaseView
196
- jsStyle={{
197
- marginBottom: cssVar("--spacing-xxl"),
198
- marginTop: cssVar("--spacing-xxl"),
199
- }}
200
- >
201
- <ListDivider />
202
- </BaseView>
203
- ),
204
- pre: (props) => {
205
- return (
206
- <pre
207
- style={{ borderRadius: cssVar("--border-radius-l") }}
208
- className={props.children.props.className}
209
- tabIndex={0}
210
- >
211
- <code className={props.children.props.className}>
212
- {props.children.props.children}
213
- </code>
214
- </pre>
215
- );
216
- },
217
- code: ({ children }) => (
218
- <span
219
- className={monospace.className}
220
- style={{
221
- color: cssVar("--primary-text"),
222
- backgroundColor: cssVar("--secondary-background"),
223
- borderRadius: cssVar("--border-radius-m"),
224
- padding: cssVar("--spacing-xs"),
225
- border: `1px solid ${cssVar("--divider")}`,
226
- display: "inline-block",
227
- }}
228
- >
229
- {children}
230
- </span>
231
- ),
232
- };
34
+ import { BaseLinkComponentOverrideContext } from "../BaseLink";
35
+ import { DocsMDXProvider, labelToID } from "../docs/mdx";
36
+ import { dot } from "@xenova/transformers";
37
+ import { pages } from "../docs/pages";
233
38
 
234
39
  export default function App({ Component, pageProps }: AppProps) {
235
40
  const router = useRouter();
236
-
41
+ const searchIndex = useRef<Promise<{
42
+ index: Array<{
43
+ embedding: Array<number>;
44
+ filename: string;
45
+ heading: string;
46
+ headingDepth: number;
47
+ }>;
48
+ }> | null>(null);
237
49
  const [pathname, setPathname] = useState(router.pathname);
238
50
  const [showList, setShowList] = useState(false);
239
51
  const [query, setQuery] = useState("");
240
- const filteredPagesRef = useRef<Array<Page>>([]);
52
+ const [queriedPages, setQueriedPages] = useState<Array<PageLink>>([]);
53
+ const queriedPagesRef = useRef<Array<PageLink>>([]);
241
54
  const queryIndexRef = useRef<void | number>(undefined);
242
55
  const queryInputRef = useKeyboard<HTMLInputElement>([
243
56
  {
@@ -265,7 +78,7 @@ export default function App({ Component, pageProps }: AppProps) {
265
78
  onlyWhenFocused: true,
266
79
  action: () => {
267
80
  setQueryIndex((current) =>
268
- Math.min((current ?? 0) + 1, filteredPagesRef.current.length - 1)
81
+ Math.min((current ?? 0) + 1, queriedPagesRef.current.length - 1)
269
82
  );
270
83
  },
271
84
  },
@@ -275,7 +88,7 @@ export default function App({ Component, pageProps }: AppProps) {
275
88
  ctrlKey: true,
276
89
  action: () => {
277
90
  setQueryIndex((current) =>
278
- Math.min((current ?? 0) + 1, filteredPagesRef.current.length - 1)
91
+ Math.min((current ?? 0) + 1, queriedPagesRef.current.length - 1)
279
92
  );
280
93
  },
281
94
  },
@@ -285,10 +98,13 @@ export default function App({ Component, pageProps }: AppProps) {
285
98
  action: () => {
286
99
  if (queryIndexRef.current === undefined) {
287
100
  return;
101
+ } else if (queriedPagesRef.current.length === 0) {
102
+ return;
288
103
  } else {
289
- const element = filteredPagesRef.current[queryIndexRef.current];
104
+ const element = queriedPagesRef.current[queryIndexRef.current];
290
105
  if (element.type === "link") {
291
106
  window.open(`/${element.page}`, "_self");
107
+ setQuery("");
292
108
  }
293
109
  }
294
110
  },
@@ -308,42 +124,111 @@ export default function App({ Component, pageProps }: AppProps) {
308
124
  .trim()
309
125
  .toLowerCase();
310
126
 
127
+ const isQuerying = sanetisedQuery.length > 0;
128
+
311
129
  useEffect(() => {
312
- if (sanetisedQuery.length === 0) {
313
- setQueryIndex(undefined);
130
+ if (isQuerying) {
131
+ setQueryIndex(0);
314
132
  if (window.innerWidth <= TABLET) {
315
- setShowList(false);
133
+ setShowList(true);
316
134
  }
317
135
  } else {
318
- setQueryIndex(0);
136
+ setQueryIndex(undefined);
319
137
  if (window.innerWidth <= TABLET) {
320
- setShowList(true);
138
+ setShowList(false);
321
139
  }
322
140
  }
323
- }, [sanetisedQuery]);
141
+ }, [isQuerying]);
324
142
 
325
143
  useEffect(() => {
326
144
  queryIndexRef.current = queryIndex;
327
145
  }, [queryIndex]);
328
146
 
329
- filteredPagesRef.current =
330
- sanetisedQuery.length > 0
331
- ? pages
332
- .flatMap((element) =>
333
- element.type === "section" ? element.content : element
334
- )
335
- .filter((element) => {
336
- return (
337
- element.page.toLowerCase().includes(sanetisedQuery) ||
338
- element?.name?.toLowerCase()?.includes(sanetisedQuery)
339
- );
340
- })
341
- : pages;
147
+ useEffect(() => {
148
+ if (sanetisedQuery.length === 0) {
149
+ return;
150
+ }
151
+
152
+ let state = { cancel: false };
153
+
154
+ async function run() {
155
+ if (searchIndex.current == null) {
156
+ searchIndex.current = fetch("index.json").then((data) => data.json());
157
+ }
158
+ if (state.cancel) {
159
+ return;
160
+ }
161
+ const data = await searchIndex.current;
162
+ if (state.cancel) {
163
+ return;
164
+ }
165
+ const { pipeline } = await import("@xenova/transformers");
166
+ if (state.cancel) {
167
+ return;
168
+ }
169
+ const generateEmbeddings = await pipeline(
170
+ "feature-extraction",
171
+ "Xenova/all-MiniLM-L6-v2"
172
+ );
173
+ if (state.cancel) {
174
+ return;
175
+ }
176
+ const queryEmbeddings = await generateEmbeddings(query, {
177
+ normalize: true,
178
+ pooling: "mean",
179
+ }).then((embedding) => embedding.data);
180
+ if (state.cancel) {
181
+ return;
182
+ }
183
+
184
+ let seen = new Set();
185
+
186
+ queriedPagesRef.current = data.index
187
+ .map((element) => {
188
+ return {
189
+ ...element,
190
+ dot: dot(queryEmbeddings, element.embedding),
191
+ };
192
+ })
193
+ .filter((element) => element.dot > 0.2)
194
+ .sort((a, b) => b.dot - a.dot)
195
+ .slice(0, 5)
196
+ .filter((result) => {
197
+ if (seen.has(result.filename)) {
198
+ return false;
199
+ } else {
200
+ seen.add(result.filename);
201
+ return true;
202
+ }
203
+ })
204
+ .map((result) => {
205
+ const heading =
206
+ result.headingDepth > 1 && result.heading.length > 0
207
+ ? labelToID(result.heading)
208
+ : null;
209
+ const page = result.filename === "index" ? "" : result.filename;
210
+ return {
211
+ type: "link",
212
+ name: result.filename,
213
+ page: heading ? `${page}#${heading}` : page,
214
+ };
215
+ });
216
+ setQueriedPages(queriedPagesRef.current.slice());
217
+ }
218
+
219
+ run();
220
+
221
+ return () => {
222
+ state.cancel = true;
223
+ };
224
+ }, [sanetisedQuery]);
342
225
 
343
226
  useEffect(() => {
344
227
  highlightAll();
345
228
  });
346
229
 
230
+ const link = useCallback((props) => <Link {...props} />, []);
231
+
347
232
  return (
348
233
  <>
349
234
  <Head>
@@ -351,10 +236,9 @@ export default function App({ Component, pageProps }: AppProps) {
351
236
  <meta name="description" content="A humble UI toolkit" />
352
237
  <meta name="viewport" content="width=device-width, initial-scale=1" />
353
238
  </Head>
354
- <BaseLinkComponentOverrideContext.Provider value={Link}>
239
+ <BaseLinkComponentOverrideContext.Provider value={link}>
355
240
  <Providers themes={{ light: lightTheme, dark: darkTheme }}>
356
- {/* @ts-ignore */}
357
- <MDXProvider components={components}>
241
+ <DocsMDXProvider>
358
242
  <BaseView
359
243
  jsStyle={[
360
244
  {
@@ -409,6 +293,10 @@ export default function App({ Component, pageProps }: AppProps) {
409
293
  <TextInput
410
294
  rootJSStyle={{ flexGrow: 1 }}
411
295
  ref={queryInputRef}
296
+ role="combobox"
297
+ aria-haspopup="grid"
298
+ aria-expanded={isQuerying ? "true" : "false"}
299
+ aria-controls=""
412
300
  placeholder="Search (⌘K)"
413
301
  value={query}
414
302
  onValueChange={(value) => {
@@ -423,7 +311,7 @@ export default function App({ Component, pageProps }: AppProps) {
423
311
  <IconLink
424
312
  aria-label="github"
425
313
  target="_blank"
426
- href="https://github.com/germtb/simple-ui"
314
+ href="https://github.com/germtb/aidos-ui"
427
315
  icon="fa-github"
428
316
  size="medium"
429
317
  color="secondary"
@@ -478,27 +366,27 @@ export default function App({ Component, pageProps }: AppProps) {
478
366
  jsStyle={[{ overflow: "scroll" }]}
479
367
  ariaLabel={"API"}
480
368
  >
481
- {(filteredPagesRef.current.length > 0
482
- ? filteredPagesRef.current
483
- : pages
484
- ).map((element, index) => {
369
+ {(isQuerying ? queriedPages : pages).map((element, index) => {
485
370
  if (element.type === "link") {
486
371
  const page = element.page;
372
+ const name = element.name;
373
+
487
374
  return (
488
375
  <ListLinkItem
489
- key={page}
376
+ key={isQuerying ? `${index}-${page}` : page}
490
377
  bare
491
378
  onClick={() => {
492
379
  setPathname(`/${page}`);
380
+ setQuery("");
493
381
  setShowList(false);
494
382
  }}
495
383
  selected={
496
- sanetisedQuery.length > 0
384
+ isQuerying
497
385
  ? index === queryIndex
498
386
  : pathname === `/${page}`
499
387
  }
500
388
  href={`/${page}`}
501
- headline={element.name ?? page}
389
+ headline={name ?? page}
502
390
  headlineSize={element.headlineSize}
503
391
  headlineBold={element.headlineBold}
504
392
  />
@@ -508,6 +396,7 @@ export default function App({ Component, pageProps }: AppProps) {
508
396
  <Sublist
509
397
  key={`section-${element.label}`}
510
398
  label={element.label}
399
+ labelBold
511
400
  bare
512
401
  >
513
402
  {element.content.map((element) => {
@@ -520,11 +409,7 @@ export default function App({ Component, pageProps }: AppProps) {
520
409
  setPathname(`/${page}`);
521
410
  setShowList(false);
522
411
  }}
523
- selected={
524
- sanetisedQuery.length > 0
525
- ? index === queryIndex
526
- : pathname === `/${page}`
527
- }
412
+ selected={pathname === `/${page}`}
528
413
  href={`/${page}`}
529
414
  headline={element.name ?? page}
530
415
  headlineSize={element.headlineSize}
@@ -553,7 +438,7 @@ export default function App({ Component, pageProps }: AppProps) {
553
438
  <Component {...pageProps} />
554
439
  </BaseView>
555
440
  </BaseView>
556
- </MDXProvider>
441
+ </DocsMDXProvider>
557
442
  </Providers>
558
443
  </BaseLinkComponentOverrideContext.Provider>
559
444
  </>
@@ -45,7 +45,7 @@ As few dependencies as possible, to keep things light and under control. The onl
45
45
  This library can be installed through npm
46
46
 
47
47
  ```bash
48
- npm install --save simple-ui-core
48
+ npm install --save aidos-ui
49
49
  ```
50
50
 
51
51
  ---