@xyd-js/atlas 0.1.0-xyd.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 (52) hide show
  1. package/.babelrc +6 -0
  2. package/.storybook/index.css +32 -0
  3. package/.storybook/main.ts +19 -0
  4. package/.storybook/preview.ts +18 -0
  5. package/.storybook/public/fonts/fustat-ext-500.woff2 +0 -0
  6. package/.storybook/public/fonts/fustat-ext-600.woff2 +0 -0
  7. package/.storybook/public/fonts/fustat-ext-700.woff2 +0 -0
  8. package/.storybook/public/fonts/fustat-regular.woff2 +0 -0
  9. package/README.md +3 -0
  10. package/declarations.d.ts +4 -0
  11. package/dist/index.css +58 -0
  12. package/dist/index.d.ts +18 -0
  13. package/dist/index.js +1 -0
  14. package/index.ts +3 -0
  15. package/package.json +61 -0
  16. package/postcss.config.cjs +5 -0
  17. package/rollup.config.js +75 -0
  18. package/src/components/ApiRef/ApiRefItem/ApiRefItem.styles.tsx +70 -0
  19. package/src/components/ApiRef/ApiRefItem/ApiRefItem.tsx +97 -0
  20. package/src/components/ApiRef/ApiRefItem/index.ts +7 -0
  21. package/src/components/ApiRef/ApiRefProperties/ApiRefProperties.styles.tsx +154 -0
  22. package/src/components/ApiRef/ApiRefProperties/ApiRefProperties.tsx +134 -0
  23. package/src/components/ApiRef/ApiRefProperties/index.ts +7 -0
  24. package/src/components/ApiRef/ApiRefSamples/ApiRefSamples.styles.tsx +28 -0
  25. package/src/components/ApiRef/ApiRefSamples/ApiRefSamples.tsx +48 -0
  26. package/src/components/ApiRef/ApiRefSamples/index.ts +7 -0
  27. package/src/components/ApiRef/index.ts +5 -0
  28. package/src/components/Atlas/Atlas.styles.tsx +7 -0
  29. package/src/components/Atlas/Atlas.tsx +25 -0
  30. package/src/components/Atlas/AtlasLazy/AtlasLazy.styles.tsx +10 -0
  31. package/src/components/Atlas/AtlasLazy/AtlasLazy.tsx +45 -0
  32. package/src/components/Atlas/AtlasLazy/hooks.ts +29 -0
  33. package/src/components/Atlas/AtlasLazy/index.ts +7 -0
  34. package/src/components/Atlas/index.ts +3 -0
  35. package/src/components/Code/CodeCopy/CodeCopy.style.tsx +21 -0
  36. package/src/components/Code/CodeCopy/CodeCopy.tsx +32 -0
  37. package/src/components/Code/CodeCopy/index.ts +7 -0
  38. package/src/components/Code/CodeSample/CodeSample.styles.tsx +134 -0
  39. package/src/components/Code/CodeSample/CodeSample.tsx +149 -0
  40. package/src/components/Code/CodeSample/index.ts +8 -0
  41. package/src/components/Code/CodeSample/withLocalStored.tsx +52 -0
  42. package/src/components/Code/CodeSampleButtons/CodeSampleButtons.styles.tsx +67 -0
  43. package/src/components/Code/CodeSampleButtons/CodeSampleButtons.tsx +106 -0
  44. package/src/components/Code/CodeSampleButtons/index.ts +7 -0
  45. package/src/components/Code/default-theme.ts +266 -0
  46. package/src/components/Code/index.ts +6 -0
  47. package/src/docs/AtlasExample/AtlasExample.stories.tsx +47 -0
  48. package/src/docs/AtlasExample/todo-app.uniform.json +625 -0
  49. package/src/docs/AtlasExample/uniform-to-references.ts +101 -0
  50. package/src/utils/mdx.ts +31 -0
  51. package/tsconfig.json +44 -0
  52. package/vite.config.ts +25 -0
@@ -0,0 +1,134 @@
1
+ import {css} from "@linaria/core";
2
+
3
+ export const $sample = {
4
+ host: css`
5
+ flex: 1 1 0;
6
+ overflow: hidden;
7
+ min-width: 0;
8
+ max-width: 512px;
9
+
10
+ border: 1px solid var(--atlas-comp-code-sample-border-color);
11
+ border-radius: 16px;
12
+ `,
13
+ }
14
+
15
+ export const $languages = {
16
+ host: css`
17
+ display: flex;
18
+ flex: 1 1 0%;
19
+ padding: 8px 0px;
20
+
21
+ background: linear-gradient(45deg, rgb(247, 247, 248) 0%, rgb(247, 247, 248) 100%) !important;
22
+
23
+ border-top-right-radius: 10px;
24
+ border-top-left-radius: 10px;
25
+ border-bottom: 0px;
26
+
27
+ min-width: 0;
28
+ `,
29
+ list: css`
30
+ display: flex;
31
+ flex-grow: 1;
32
+ justify-content: end;
33
+ gap: 8px;
34
+ padding: 0 10px;
35
+ `,
36
+ button: css`
37
+ all: unset;
38
+
39
+ cursor: pointer;
40
+
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+
45
+ border-radius: 6px;
46
+ padding: 6px;
47
+
48
+ font-size: 14px;
49
+ color: var(--atlas-comp-code-sample-color);
50
+
51
+ &[data-state="active"] {
52
+ color: var(--atlas-comp-code-sample-color--active);
53
+ border-bottom: 1px solid var(--atlas-comp-code-sample-color--active);
54
+ border-bottom-left-radius: 0px;
55
+ border-bottom-right-radius: 0px;
56
+ }
57
+
58
+ &:hover {
59
+ transition: ease-in 0.1s;
60
+ background: var(--atlas-comp-code-sample-background);
61
+ }
62
+ `,
63
+ description: css`
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 4px;
67
+
68
+ font-size: 14px;
69
+ color: var(--atlas-comp-code-sample-color);
70
+
71
+ margin-left: 4px;
72
+ margin-right: 4px;
73
+ `,
74
+ description$item: css`
75
+ display: flex;
76
+ padding-left: 16px;
77
+ padding-right: 16px;
78
+ flex: 1 1 0%;
79
+ gap: 16px;
80
+ border-radius: 4px;
81
+ `,
82
+ copy: css`
83
+ display: flex;
84
+ padding-left: 8px;
85
+ padding-right: 8px;
86
+ align-items: center;
87
+ `
88
+ }
89
+
90
+ export const $code = {
91
+ host: css`
92
+ max-height: 400px;
93
+ background: linear-gradient(45deg, rgb(247, 247, 248) 0%, rgb(247, 247, 248) 100%) !important;
94
+
95
+ margin: 0;
96
+ padding: 8px 16px;
97
+
98
+ border-top: 1px solid var(--atlas-comp-code-sample-border-color);
99
+ border-bottom-left-radius: 10px;
100
+ border-bottom-right-radius: 10px;
101
+
102
+ font-size: 14px;
103
+ line-height: 20px;
104
+ white-space: pre-wrap;
105
+ word-break: break-all;
106
+
107
+ overflow-y: scroll;
108
+ `
109
+ }
110
+
111
+ export const $mark = {
112
+ host: css`
113
+ display: flex;
114
+ border-left-width: 4px;
115
+ border-color: transparent;
116
+ margin: 4px 0;
117
+ `,
118
+ line: css`
119
+ flex: 1 1 0%;
120
+ `,
121
+ $$annotated: css`
122
+ border-color: var(--atlas-comp-code-sample-mark-border--active);
123
+ background-color: var(--atlas-comp-code-sample-mark-background--active);
124
+ `
125
+ }
126
+
127
+ export const $lineNumber = {
128
+ host: css`
129
+ margin: 0 4px;
130
+ //text-align: right;
131
+ user-select: none;
132
+ opacity: 0.5;
133
+ `
134
+ }
@@ -0,0 +1,149 @@
1
+ import React, {useEffect, useState} from "react";
2
+ import * as TabsPrimitive from "@radix-ui/react-tabs"; // TODO: remove and use separation
3
+ import {
4
+ AnnotationHandler,
5
+ InnerLine,
6
+ Pre,
7
+ highlight,
8
+ HighlightedCode,
9
+ } from "codehike/code"
10
+
11
+ import {
12
+ CodeCopy,
13
+ } from "@/components/Code";
14
+ import {theme as defaultTheme} from "@/components/Code/default-theme" // TODO: support multiple themes
15
+ import {withLocalStored} from "@/components/Code/CodeSample/withLocalStored";
16
+ import {
17
+ $sample,
18
+ $languages,
19
+ $code,
20
+ $mark,
21
+ $lineNumber
22
+ } from "./CodeSample.styles";
23
+
24
+ // TODO: try to use codehiki in build time / ASYNC !!! - we need rr server-components
25
+ // TODO: separate highlight
26
+
27
+ export interface MDXCodeSampleBlock {
28
+ /** This is the raw code. May include annotation comments. */
29
+ value: string;
30
+ /** The programming language. */
31
+ lang: string;
32
+ /** Metadata string (the content after the language name in a markdown codeblock). */
33
+ meta: string;
34
+ }
35
+
36
+ export interface CodeSampleProps {
37
+ name: string;
38
+ description: string;
39
+ codeblocks: MDXCodeSampleBlock[];
40
+ }
41
+
42
+ const $$LocalStoredTab = withLocalStored(TabsPrimitive.Root);
43
+
44
+ export function CodeSample(props: CodeSampleProps) {
45
+ const [highlighted, setHighlighted] = useState<HighlightedCode[]>([]);
46
+
47
+ useEffect(() => {
48
+ async function fetchHighlight() {
49
+ const result = await Promise.all(
50
+ props.codeblocks?.map((codeblock) => highlight(codeblock, defaultTheme))
51
+ );
52
+
53
+ setHighlighted(result);
54
+ }
55
+
56
+ fetchHighlight();
57
+ }, [props.codeblocks]);
58
+
59
+ if (highlighted.length === 0) {
60
+ return <div>Loading</div>;
61
+ }
62
+
63
+ if (!highlighted) {
64
+ return <div>Loading</div>;
65
+ }
66
+
67
+
68
+ return (
69
+ <$$LocalStoredTab
70
+ className={$sample.host}
71
+ style={highlighted[0]?.style}
72
+ localStorageKey={`preferredLanguage[${name}]`}
73
+ defaultValue={highlighted[0]?.meta}
74
+ >
75
+ <div className={$languages.host}>
76
+ <$Description description={props.description}/>
77
+
78
+ <TabsPrimitive.List className={$languages.list}>
79
+ {props.codeblocks?.map(({meta}, i) => (
80
+ <TabsPrimitive.Trigger value={meta!} key={i} className={$languages.button}>
81
+ {meta}
82
+ </TabsPrimitive.Trigger>
83
+ ))}
84
+ </TabsPrimitive.List>
85
+
86
+ <div className={$languages.copy}>
87
+ {props.codeblocks?.map((codeblock, i) => (
88
+ <TabsPrimitive.Content value={codeblock.meta!} asChild key={i}>
89
+ <CodeCopy text={codeblock.value}/>
90
+ </TabsPrimitive.Content>
91
+ ))}
92
+ </div>
93
+ </div>
94
+
95
+ {highlighted?.map((codeblock, i) => (
96
+ <TabsPrimitive.Content value={codeblock.meta} key={i}>
97
+ <Pre
98
+ className={$code.host}
99
+ style={codeblock?.style || codeblock?.style}
100
+ code={codeblock}
101
+ handlers={[mark, lineNumber]}
102
+ />
103
+ </TabsPrimitive.Content>
104
+ ))}
105
+ </$$LocalStoredTab>
106
+ )
107
+ }
108
+
109
+ function $Description(props: { description: string }) {
110
+ return <div className={$languages.description}>
111
+ <div className={$languages.description$item}>
112
+ {props.description}
113
+ </div>
114
+ </div>
115
+ }
116
+
117
+ const mark: AnnotationHandler = {
118
+ name: "Mark",
119
+ Line: ({annotation, ...props}) => {
120
+ return (
121
+ <div className={`${$mark.host} ${annotation && $mark.$$annotated}`}>
122
+ <InnerLine
123
+ merge={props}
124
+ className={$mark.line}
125
+ />
126
+ </div>
127
+ )
128
+ },
129
+ }
130
+
131
+ const lineNumber: AnnotationHandler = {
132
+ name: "LineNumber",
133
+ Line: ({annotation, ...props}) => {
134
+ const width = props.totalLines.toString().length + 1
135
+
136
+ return (
137
+ <>
138
+ <span
139
+ style={{minWidth: `${width}ch`}}
140
+ className={$lineNumber.host}
141
+ >
142
+ {props.lineNumber}
143
+ </span>
144
+ <InnerLine merge={props}/>
145
+ </>
146
+ )
147
+ },
148
+ }
149
+
@@ -0,0 +1,8 @@
1
+ export {
2
+ CodeSample,
3
+ } from './CodeSample';
4
+
5
+ export type {
6
+ CodeSampleProps,
7
+ MDXCodeSampleBlock,
8
+ } from "./CodeSample";
@@ -0,0 +1,52 @@
1
+ import React, {useState, useEffect} from "react"
2
+
3
+ export interface CodeTabsProps {
4
+ localStorageKey: string
5
+ defaultValue: string
6
+ className: string
7
+ style: any
8
+
9
+ children: React.ReactNode
10
+ }
11
+
12
+ // TODO: interface
13
+ export function withLocalStored(Component: any) {
14
+ return function LocalStored(props: CodeTabsProps) {
15
+ const [value, setValue] = useState(
16
+ typeof localStorage !== "undefined"
17
+ ? localStorage?.getItem(props.localStorageKey) || props.defaultValue
18
+ : props.defaultValue,
19
+ )
20
+
21
+ useEffect(() => {
22
+ const handler = (e: StorageEvent) => {
23
+ if (e.key === props.localStorageKey) {
24
+ setValue(e.newValue || props.defaultValue)
25
+ }
26
+ }
27
+ window.addEventListener("storage", handler)
28
+ return () => {
29
+ window.removeEventListener("storage", handler)
30
+ }
31
+ }, [props.localStorageKey])
32
+
33
+ function onValueChange(value: string) {
34
+ localStorage.setItem(props.localStorageKey, value)
35
+ window.dispatchEvent(
36
+ new StorageEvent("storage", {
37
+ key: props.localStorageKey,
38
+ newValue: value,
39
+ }),
40
+ )
41
+ }
42
+
43
+ return (
44
+ <Component
45
+ onValueChange={onValueChange}
46
+ value={value}
47
+ >
48
+ {props.children}
49
+ </Component>
50
+ )
51
+ }
52
+ }
@@ -0,0 +1,67 @@
1
+ import {css} from "@linaria/core";
2
+
3
+ export const $sample = {
4
+ host: css`
5
+ position: relative;
6
+ max-width: 100%;
7
+ `,
8
+ container: css`
9
+ display: flex;
10
+ align-items: center;
11
+ border-radius: 8px;
12
+ background-color: var(--atlas-comp-code-sample_buttons-container-background);
13
+ `
14
+ }
15
+
16
+ export const $arrow = {
17
+ host: css`
18
+ padding: 8px;
19
+ background-color: var(--atlas-comp-code-sample_buttons-background--active);
20
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
21
+ `,
22
+ icon: css`
23
+ width: 16px;
24
+ height: 16px;
25
+ `
26
+ }
27
+
28
+ export const $scroller = {
29
+ host: css`
30
+ overflow-x: auto;
31
+ flex-grow: 1;
32
+ `,
33
+ container: css`
34
+ display: inline-flex;
35
+ gap: 4px;
36
+
37
+ padding: 4px;
38
+ margin-left: 4px;
39
+ `
40
+ }
41
+
42
+ export const $button = {
43
+ host: css`
44
+ padding: 0.5rem 1rem;
45
+
46
+ border-radius: 0.375rem;
47
+ font-size: 0.875rem;
48
+ line-height: 1.25rem;
49
+ font-weight: 500;
50
+ white-space: nowrap;
51
+
52
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
53
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
54
+ transition-duration: 300ms;
55
+
56
+ color: var(--atlas-comp-code-sample_buttons-color);
57
+
58
+ &:hover {
59
+ color: var(--atlas-comp-code-sample_buttons-color--active);
60
+ }
61
+ `,
62
+ $$active: css`
63
+ color: var(--atlas-comp-code-sample_buttons-color--active);
64
+ background-color: var(--atlas-comp-code-sample_buttons-background--active);
65
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
66
+ `
67
+ }
@@ -0,0 +1,106 @@
1
+ import React, {useState, useRef, useEffect} from 'react'
2
+ import {ChevronLeft, ChevronRight} from "lucide-react"
3
+
4
+ import {Example} from "@xyd-js/uniform";
5
+
6
+ import {MDXReference, mdxValue} from "@/utils/mdx";
7
+
8
+ import {
9
+ $sample,
10
+ $arrow,
11
+ $scroller,
12
+ $button
13
+ } from "./CodeSampleButtons.styles";
14
+
15
+ export interface CodeExampleButtonsProps {
16
+ examples: MDXReference<Example[]>
17
+
18
+ activeExample: MDXReference<Example> | null
19
+
20
+ onClick: (example: MDXReference<Example>) => void
21
+ }
22
+
23
+ export function CodeExampleButtons({examples, activeExample, onClick}: CodeExampleButtonsProps) {
24
+ const [showLeftArrow, setShowLeftArrow] = useState(false)
25
+ const [showRightArrow, setShowRightArrow] = useState(false)
26
+ const scrollContainerRef = useRef<HTMLDivElement>(null)
27
+
28
+ const handleScroll = () => {
29
+ if (scrollContainerRef.current) {
30
+ const {scrollLeft, scrollWidth, clientWidth} = scrollContainerRef.current
31
+ setShowLeftArrow(scrollLeft > 0)
32
+ setShowRightArrow(scrollLeft < scrollWidth - clientWidth)
33
+ }
34
+ }
35
+
36
+ useEffect(() => {
37
+ handleScroll()
38
+ window.addEventListener('resize', handleScroll)
39
+ return () => window.removeEventListener('resize', handleScroll)
40
+ }, [])
41
+
42
+ const scroll = (direction: 'left' | 'right') => {
43
+ if (scrollContainerRef.current) {
44
+ const scrollAmount = direction === 'left' ? -200 : 200
45
+ scrollContainerRef.current.scrollBy({left: scrollAmount, behavior: 'smooth'})
46
+ }
47
+ }
48
+
49
+ return (
50
+ <div className={$sample.host}>
51
+ <div className={$sample.container}>
52
+ {showLeftArrow && (
53
+ <button
54
+ onClick={() => scroll('left')}
55
+ className={$arrow.host}
56
+ >
57
+ <ChevronLeft className={$arrow.icon}/>
58
+ </button>
59
+ )}
60
+ <div
61
+ ref={scrollContainerRef}
62
+ onScroll={handleScroll}
63
+ className={$scroller.host}
64
+ >
65
+ <div className={$scroller.container}>
66
+ {examples.map((example) => (
67
+ <$SampleButton
68
+ key={example.codeblock.title}
69
+ onClick={() => onClick(example)}
70
+ example={example}
71
+ activeExample={activeExample}
72
+ >
73
+ {mdxValue(example.codeblock.title || null)}
74
+ </$SampleButton>
75
+ ))}
76
+ </div>
77
+ </div>
78
+ {showRightArrow && (
79
+ <button
80
+ onClick={() => scroll('right')}
81
+ className={$arrow.host}
82
+ >
83
+ <ChevronRight className={$arrow.icon}/>
84
+ </button>
85
+ )}
86
+ </div>
87
+ </div>
88
+ )
89
+ }
90
+
91
+ function $SampleButton({onClick, children, activeExample, example}: {
92
+ onClick: () => void,
93
+ children: React.ReactNode,
94
+ example: MDXReference<Example>,
95
+ activeExample: MDXReference<Example> | null,
96
+ }) {
97
+ const markExampleAsActive = (activeExample?.description && activeExample?.description === example?.description) ||
98
+ (activeExample?.codeblock?.title && activeExample?.codeblock?.title === example.codeblock.title)
99
+
100
+ return <button
101
+ onClick={onClick}
102
+ className={`${$button.host} ${markExampleAsActive && $button.$$active}`}
103
+ >
104
+ {children}
105
+ </button>
106
+ }
@@ -0,0 +1,7 @@
1
+ export {
2
+ CodeExampleButtons,
3
+ } from "./CodeSampleButtons"
4
+
5
+ export type {
6
+ CodeExampleButtonsProps
7
+ } from "./CodeSampleButtons"