@xyd-js/foo 0.1.0-xyd.0
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.
- package/README.md +3 -0
- package/index.ts +1 -0
- package/package.json +29 -0
- package/packages/renderoll/index.ts +3 -0
- package/packages/renderoll/renderoll.tsx +189 -0
- package/postcss.config.cjs +5 -0
- package/rollup.config.js +89 -0
- package/src/tree/foo-tree.tsx +0 -0
- package/src/tree/index.tsx +0 -0
- package/tsconfig.json +36 -0
package/README.md
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const test = "test"
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyd-js/foo",
|
|
3
|
+
"version": "0.1.0-xyd.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
"./index.css": "./dist/index.css",
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./renderoll": {
|
|
15
|
+
"import": "./dist/renderoll.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"react": "^18.3.1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"postcss-import": "^16.1.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"clean": "rimraf build",
|
|
26
|
+
"prebuild": "pnpm clean",
|
|
27
|
+
"build": "rollup -c rollup.config.js"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import React, {createContext, lazy, useContext, useEffect, useRef, useState, Suspense} from "react";
|
|
2
|
+
import type {RefObject} from "react";
|
|
3
|
+
import {css} from "@linaria/core";
|
|
4
|
+
|
|
5
|
+
const styles = {
|
|
6
|
+
loader: {
|
|
7
|
+
host: css`
|
|
8
|
+
z-index: 999999;
|
|
9
|
+
position: absolute;
|
|
10
|
+
left: 0;
|
|
11
|
+
top: 0;
|
|
12
|
+
right: 0;
|
|
13
|
+
bottom: 0;
|
|
14
|
+
|
|
15
|
+
background: white; // TODO: customization
|
|
16
|
+
`
|
|
17
|
+
},
|
|
18
|
+
serveComponent: {
|
|
19
|
+
host: css`
|
|
20
|
+
opacity: 0;
|
|
21
|
+
position: absolute;
|
|
22
|
+
height: 100%;
|
|
23
|
+
z-index: 999999;
|
|
24
|
+
`
|
|
25
|
+
},
|
|
26
|
+
content: {
|
|
27
|
+
host: css`
|
|
28
|
+
opacity: 0;
|
|
29
|
+
transition: opacity 0.3s;
|
|
30
|
+
`,
|
|
31
|
+
host$$active: css`
|
|
32
|
+
opacity: 1;
|
|
33
|
+
`
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface RenderollOptions {
|
|
38
|
+
decorator?: (props: { children: React.ReactNode }) => React.ReactNode
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function renderoll(
|
|
42
|
+
async: () => Promise<any>,
|
|
43
|
+
options?: RenderollOptions
|
|
44
|
+
) {
|
|
45
|
+
const [once, setOnce] = useState(false)
|
|
46
|
+
const [inited, setInited] = useState(false)
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setInited(true)
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const $RenderLazyComponent = $Lazy(async, options)
|
|
53
|
+
|
|
54
|
+
return ({children}) => {
|
|
55
|
+
return <$LazyContext.Provider value={{
|
|
56
|
+
onFinish: () => {
|
|
57
|
+
if (once) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
setOnce(true)
|
|
61
|
+
}
|
|
62
|
+
}}>
|
|
63
|
+
{
|
|
64
|
+
!once && <div className={inited ? styles.serveComponent.host : ""}>
|
|
65
|
+
{children}
|
|
66
|
+
</div>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
{!once && <$Loader/>}
|
|
70
|
+
|
|
71
|
+
<Suspense fallback={<$Loader/>}>
|
|
72
|
+
<$RenderLazyComponent>
|
|
73
|
+
{children}
|
|
74
|
+
</$RenderLazyComponent>
|
|
75
|
+
</Suspense>
|
|
76
|
+
</$LazyContext.Provider>
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// TODO: better api for `onFinish` because this does not match pixel perferct server component
|
|
81
|
+
const $LazyContext = createContext({
|
|
82
|
+
onFinish: () => {
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
function $Loader() {
|
|
87
|
+
return <div className={styles.loader.host}/>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// TODO: in the future different method than data-slug
|
|
91
|
+
// custom observer logic instead not pixel perfect threshold
|
|
92
|
+
function historyPushStateScroller() {
|
|
93
|
+
const elements = document.querySelectorAll('[data-slug]');
|
|
94
|
+
|
|
95
|
+
if (!elements.length) {
|
|
96
|
+
console.warn("No elements with [data-slug] found.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const observer = new IntersectionObserver((entries) => {
|
|
101
|
+
entries.forEach(entry => {
|
|
102
|
+
if (!entry.isIntersecting) {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const slug = entry.target.getAttribute("data-slug");
|
|
107
|
+
|
|
108
|
+
window.history.pushState(null, "", `${slug}`);
|
|
109
|
+
|
|
110
|
+
const event = new CustomEvent("xyd.history.pushState", {
|
|
111
|
+
detail: {
|
|
112
|
+
url: slug,
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
window.dispatchEvent(event);
|
|
116
|
+
});
|
|
117
|
+
}, {threshold: 0.3});
|
|
118
|
+
|
|
119
|
+
elements.forEach(element => observer.observe(element));
|
|
120
|
+
|
|
121
|
+
return observer
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function $Lazy(
|
|
125
|
+
async: () => Promise<any>,
|
|
126
|
+
options?: RenderollOptions
|
|
127
|
+
) {
|
|
128
|
+
return lazy(async () => {
|
|
129
|
+
const [Prev, Next] = await async()
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
default: ({children}) => {
|
|
133
|
+
const [count, setCount] = useState(0)
|
|
134
|
+
const serverContent = useRef<Element>(null);
|
|
135
|
+
const {onFinish} = useContext($LazyContext)
|
|
136
|
+
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
const observer = historyPushStateScroller()
|
|
139
|
+
|
|
140
|
+
if (!observer) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return () => {
|
|
145
|
+
observer.disconnect();
|
|
146
|
+
};
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (serverContent?.current) {
|
|
151
|
+
// TODO: below mechanism does not match perfect - do we need to compare with server view position?
|
|
152
|
+
serverContent?.current.scrollIntoView?.();
|
|
153
|
+
|
|
154
|
+
onFinish()
|
|
155
|
+
}
|
|
156
|
+
}, [serverContent]);
|
|
157
|
+
|
|
158
|
+
function onLoaded() {
|
|
159
|
+
setCount(count + 1)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const loaded = !!count
|
|
163
|
+
|
|
164
|
+
const tree = <>
|
|
165
|
+
<Prev onLoaded={onLoaded}/>
|
|
166
|
+
|
|
167
|
+
<div ref={serverContent as RefObject<HTMLDivElement>}>
|
|
168
|
+
{children}
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
<Next onLoaded={onLoaded}/>
|
|
172
|
+
</>
|
|
173
|
+
|
|
174
|
+
const content = options?.decorator
|
|
175
|
+
? options?.decorator?.({children: tree})
|
|
176
|
+
: tree
|
|
177
|
+
|
|
178
|
+
return <div
|
|
179
|
+
className={`
|
|
180
|
+
${styles.content.host}
|
|
181
|
+
${loaded && styles.content.host$$active}
|
|
182
|
+
`}>
|
|
183
|
+
|
|
184
|
+
{content}
|
|
185
|
+
</div>
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {fileURLToPath} from 'url';
|
|
2
|
+
import {dirname} from 'path';
|
|
3
|
+
|
|
4
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
5
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
6
|
+
import typescript from '@rollup/plugin-typescript';
|
|
7
|
+
import dts from 'rollup-plugin-dts';
|
|
8
|
+
import {terser} from 'rollup-plugin-terser';
|
|
9
|
+
import babel from '@rollup/plugin-babel';
|
|
10
|
+
import postcss from 'rollup-plugin-postcss';
|
|
11
|
+
import wyw from '@wyw-in-js/rollup';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
import {createRequire} from 'module';
|
|
17
|
+
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const {dependencies} = require('./package.json', {assert: {type: 'json'}});
|
|
20
|
+
|
|
21
|
+
const external = Object.keys(dependencies);
|
|
22
|
+
|
|
23
|
+
export default [
|
|
24
|
+
{
|
|
25
|
+
input: {
|
|
26
|
+
index: 'index.ts',
|
|
27
|
+
renderoll: 'packages/renderoll/index.ts'
|
|
28
|
+
},
|
|
29
|
+
output: [
|
|
30
|
+
{
|
|
31
|
+
dir: 'dist',
|
|
32
|
+
format: 'esm',
|
|
33
|
+
sourcemap: false,
|
|
34
|
+
entryFileNames: '[name].js'
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
plugins: [
|
|
38
|
+
wyw({
|
|
39
|
+
include: ['**/*.{ts,tsx}'],
|
|
40
|
+
babelOptions: {
|
|
41
|
+
presets: [
|
|
42
|
+
'@babel/preset-typescript',
|
|
43
|
+
'@babel/preset-react'
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
postcss({
|
|
48
|
+
extract: true,
|
|
49
|
+
plugins: [
|
|
50
|
+
require('postcss-import'),
|
|
51
|
+
require('autoprefixer')
|
|
52
|
+
]
|
|
53
|
+
}),
|
|
54
|
+
resolve(),
|
|
55
|
+
commonjs(),
|
|
56
|
+
typescript({
|
|
57
|
+
tsconfig: './tsconfig.json',
|
|
58
|
+
}),
|
|
59
|
+
babel({
|
|
60
|
+
babelHelpers: 'bundled',
|
|
61
|
+
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
62
|
+
presets: [
|
|
63
|
+
'@babel/preset-env',
|
|
64
|
+
'@babel/preset-react'
|
|
65
|
+
],
|
|
66
|
+
}),
|
|
67
|
+
terser(),
|
|
68
|
+
],
|
|
69
|
+
external
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
input: 'index.ts',
|
|
73
|
+
output: {
|
|
74
|
+
file: 'dist/index.d.ts',
|
|
75
|
+
format: 'es',
|
|
76
|
+
},
|
|
77
|
+
plugins: [dts()],
|
|
78
|
+
external
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
input: 'packages/renderoll/index.ts',
|
|
82
|
+
output: {
|
|
83
|
+
file: 'dist/renderoll.d.ts',
|
|
84
|
+
format: 'es',
|
|
85
|
+
},
|
|
86
|
+
plugins: [dts()],
|
|
87
|
+
external
|
|
88
|
+
}
|
|
89
|
+
];
|
|
File without changes
|
|
File without changes
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "esnext",
|
|
4
|
+
"esModuleInterop": true,
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"target": "ES6",
|
|
7
|
+
"lib": [
|
|
8
|
+
"dom",
|
|
9
|
+
"dom.iterable",
|
|
10
|
+
"esnext"
|
|
11
|
+
],
|
|
12
|
+
"allowJs": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"strict": false,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"incremental": false,
|
|
17
|
+
"resolveJsonModule": true,
|
|
18
|
+
"isolatedModules": true,
|
|
19
|
+
"jsx": "react",
|
|
20
|
+
"plugins": [
|
|
21
|
+
{
|
|
22
|
+
"name": "next"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"strictNullChecks": true
|
|
26
|
+
},
|
|
27
|
+
"include": [
|
|
28
|
+
"next-env.d.ts",
|
|
29
|
+
"**/*.ts",
|
|
30
|
+
"**/*.tsx",
|
|
31
|
+
".next/types/**/*.ts"
|
|
32
|
+
],
|
|
33
|
+
"exclude": [
|
|
34
|
+
"node_modules"
|
|
35
|
+
]
|
|
36
|
+
}
|