i found it working fine but lack of trigger function from call first scroll example setup. each time: the router's id changes.
This is a reset component issue. Similar is an Identity problem. using Identity but not working in my case. When reloading the component with f5 from the browser, it doesn't automatically fire the component with firstLoad. So I need a trigger call from watch route.params.slug=> refetchData.
Like triggering infinite scroll loading from setup with watch(()=> route.params.slug,Active-Scroll-Loading).
I have this piece of code but f5 it doesn't run firstLoad.
`
<div class="tag tag-content">
<h1 v-if="tag != null" class="mb-10">{{ tag.name }} <span class="fs-5 text-muted">{{ `(${tag.use})` }}</span>
</h1>
<div class="d-flex gap-3 flex-wrap" v-if="tags && tags.length">
<router-link v-for="(tag, i) in tags" :key="i" :to="{
name: 'discussion-by-tag',
params: {
id: tag.slug
}
}" class="btn btn-flex btn-sm btn-color-gray-500 btn-bg-light btn-active-primary px-4 h-30px ">
{{ tag.name }}
{{ `(${tag.use})` }} </router-link>
</div>
<div v-else class="text-center">
<div class="flex-grow-1 bgi-no-repeat bgi-size-contain bgi-position-x-center card-rounded-bottom h-200px mh-200px my-5 mb-lg-12"
style="background-image:url('media/illustrations/sketchy-1/5.png')">
</div>
{{ t("data_empty") }}
</div>
</div>
<div class="separator separator-dashed border-gray-300 my-6"></div>
<div v-if="questions && questions.length" v-for="(question, i) in questions" :key="i">
<Questions :data="question" />
</div>
<div v-else class="text-center">
<div class="flex-grow-1 bgi-no-repeat bgi-size-contain bgi-position-x-center card-rounded-bottom h-200px mh-200px my-5 mb-lg-12"
style="background-image:url('media/illustrations/sketchy-1/5.png')">
</div>
{{ t("data_empty") }}
</div>
<infinite-loading ref="scrollComponent" :identifier="route.params.id" :firstLoad="true" @infinite="infiniteHandler">
<template #complete>
<p class="text-center"> {{ t("no_results") }}</p>
</template>
<template #spinner>
<div class="d-flex align-items-center mt-5 ">
<span class="spinner-border text-primary" role="status"></span>
<span class="text-muted fs-6 fw-bold ms-5">Loading...</span>
</div>
</template>
</infinite-loading>
<script>
import { defineComponent, onMounted, ref, computed, watch, watchEffect } from "vue";
import Questions from "@/views/community/discussion/Questions";
import InfiniteLoading from "v3-infinite-loading";
import "v3-infinite-loading/lib/style.css";
import LayoutService from "@/core/services/LayoutService";
import { useI18n } from "vue-i18n/index";
import { useRoute } from 'vue-router';
import { useStore } from "vuex";
import { Actions, Mutations } from "@/store/enums/StoreEnums";
export default defineComponent({
name: "dev-discussion-all",
components: { Questions, InfiniteLoading },
setup() {
const { t } = useI18n();
const store = useStore();
const scrollComponent = ref(null);
const route = useRoute();
const questions = ref([]);
const tags = ref([]);
const tag = ref({});
const data = computed(() => store.getters.questionListByTag);
onMounted(() => {
if (!localStorage.getItem("config")) {
LayoutService.enableSidebar();
}
})
// created
//---- Load ALL TAGS
store.dispatch(Actions.LIST_TAG_ALL).then(result => {
tags.value = result;
})
// reset store pagination list by tag
const firstLoad = async () => {
await store.commit(Mutations.RESET_LIST_BY_TAG)
// fetch data by tags
await store.dispatch(Actions.LIST_QUESTION_BY_TAG, {
slug: route.params.id,
payload: {
page: data.value.page,
limit: data.value.limit
}
}).then(result => {
questions.value = result.rows;
tag.value = result.tag;
})
}
firstLoad();
//function reload data
const fetchPage = async () => {
let result = await store.dispatch(Actions.LIST_QUESTION_BY_TAG, {
slug: route.params.id,
payload: {
page: data.value.page,
limit: data.value.limit
}
});
tag.value = result.tag;
}
// check router changer reload
watch(() => route.params.id, async () => {
await store.commit(Mutations.RESET_LIST_BY_TAG);
await fetchPage();
});
// set data when computed changer
watchEffect(() => {
questions.value = data.value.rows;
tag.value = data.value.tag;
})
const infiniteHandler = async ($state) => {
try {
if (data.value.page <= data.value.pages) {
await fetchPage();
$state.loaded();
} else {
$state.complete();
}
} catch (error) {
$state.error();
}
}
return {
t,
scrollComponent,
route,
tag,
tags,
questions,
infiniteHandler
}
},
});
</script>
`
I am seeing a weird issue where when user is viewing my app in "desktop" mode (non-mobile size viewport), posts are not infinitely loading past page 2. If on mobile view, posts sometimes infinitely load correctly to the end. Other times it may load more than 2 pages, but not all the way to the end of the data.
I've copied the demo provided from the documentation and applied it to a Nuxt 3 app. I am testing it in the Edge browser.
Does anyone know why the posts are not consistently loading to the end of the data? It should be loading about 10 posts per page for a total of 100, but in my tests, only 2 pages of data is loaded for a total of around 20 posts when user scrolls to bottom
I've got a reproduction available here: https://stackblitz.com/edit/nuxt-starter-2qcayv?file=pages/index.vue
Note: Be sure to click the "Open in New Tab" button at top right to see the issue in action.
Error [ERR_REQUIRE_ESM]: require() of ES Module /my-project/node_modules/v3-infinite-loading/lib/v3-infinite-loading.mjs not supported. production. Production environment is error. I use typescript. Development environment is right. import InfiniteLoading from "v3-infinite-loading"
Is there an option to not have an infinite loop? Right now it currently repeats the data and does a call on each time the list runs out. I'd like it to only run after the first data and stop.
Hi, thanks for the work on this library
I'm getting error while scrolling to the top since the last update, below is the error message, i'll be glad if you can help.
v3-infinite-loading.mjs:69 Uncaught (in promise) TypeError: Cannot set properties of null (setting 'scrollTop') at v3-infinite-loading.mjs:69:32
Is it possible to add 'no-more' and 'no-results' slots?
I have a problem.
when i use v3-infinite-loading for multi tabs. in tab 1. is working however when i scroll to if(data.length < per_page) $state.complete() then click "tab 2" it not working even though page 2 has data.length >= per_page
how i can fix this. pl help me. ths!
While the default (first) load upon coming to the page works ok, generating reload by changing the identifier (for example by raising the testNumber
by 1 via click event) triggers reload twice and three times in a row. This pattern repeats on every next change of the testNumber
, two reloads, three reloads, two reloads, three reloads ..etc. Really weird, that causes me problems on the server side due to the specific code.
Here is my infinite load component:
<infinite-loading @infinite="infiniteHandler" :identifier="testNumber" style="text-align: center; margin-bottom: 5px;">
<template #complete><span>End of results</span></template>
<template #error><span>No results</span></template>
</infinite-loading>
Great library, though it currently does not support more than one component on the same page (or same DOM, at least), as this line shows:
|
const infiniteLoading = document.getElementById("vue3-infinite-loading"); |
It is quite common for SPA apps to contain multiple scrollable infinite lists, so I think this would be a great feature to implement :)
Below is the code I've put together to do inverted infinite scrolling. I want the behavior to behave exactly like your demo, however, I keep running into the following issues and cannot figure out why mine is behaving different than yours.
- The initial load won't start at the bottom of the scroll element unless the
slot
attribute is bound. It's weird. If I override a slot with a template alone, it starts at the top of the scroll element, which is wrong. If I override a slot with the attribute alone, it starts at the bottom of the scroll element, which it should. I prefer to override with a template, so in order to make it work I have to include the template and the attribute binding with an empty object as shown in the code below. This doesn't seem right.
- The transition is not smooth. Whenever the infinite handler triggers, it automatically scrolls all the way to the top of all the new messages. This also isn't like your demo.
Do you see what I am doing wrong to cause these issues? Thanks!
Edit: This is partial code. I stripped out a bunch of other stuff that is unrelated to the infinite scroll stuff.
const template = `
<div class="flex-row messaging">
<div class="flex-grow flex-column flex-justify-end messages">
<div id="message-container" class="message-container">
<infinite-loading target="#message-container" :slots="{}" :top="true" :identifier="infiniteId" :firstload="false" @infinite="infiniteHandler">
<template #complete>
<span></span>
</template>
</infinite-loading>
<div v-for="message in messages" v-bind:key="message.id" v-bind:message="message" class="flex-row message">
... stuff ...
</div>
</div>
</div>
</div>
`
export default {
name: "Messages",
template,
setup () {
const messages = ref([]);
const cursor = ref(null);
function getMessages($state) {
var query = "";
if (cursor.value) {
query = "?cursor="+cursor.value;
};
fetchWrapper.get(`${API_BASE_URL}/messages${query}`)
.then(json => {
cursor.value = json.cursor;
// prepend messages with the older messages
messages.value.unshift(...json.messages);
if (json.next) {
$state.loaded();
} else {
$state.complete()
};
})
.catch(error => appStore.createToast(error));
};
function infiniteHandler($state) {
getMessages($state);
};
return {
messages,
infiniteId,
infiniteHandler,
};
},
};
v3-infinite-loading doesn't appear to be written in CJS, but also doesn't appear to be a valid ES module (i.e. it doesn't have "type": "module" or an .mjs extension for the entry point). Please contact the package author to fix.
Is there a CDN for browser usage?
I'm using this package for a Kanban board I built, which has 3 columns.
Each <column>
is its own component and has an <infinite-loading>
component inside, which is scrollable independently.
On the initial page load, everything works as expected and all 3 columns call their corresponding @infinite="load"
function, which fetches the first page of data. When scrolling the three columns, they also continue to load more pages, which is perfect.
However, the same page contains an input field to perform a search. When a search is done, I'm using the Provide / Inject functionality of Vue3 to pass the search query to each <column>
component. This also works and all 3 components receive the search string.
In order to refresh each column, I make use of the :identifier="id"
prop of the <infinite-loading>
component. According to the docs, it should cause a reset and result in the @infinite="load"
function being called again. However, only 2 columns seem to load the new data after performing the first search and only 1 column after performing a second or third search.
The :id
to reset the component is a new +new Date()
everytime the search changes.
If needed, I could put together a codesandbox for further testing, but do you have any clue why this would happen?
I just tried it with another package, and the exact same setup works, only difference being I use the :key
prop to reset their component. I tried the same with the <infinite-loading>
one, but it doesn't seem to solve my problem.
This package is the most flexible and maintained one, so I hope I wouldn't want to switch to something else.
Hi! Can I add more arguments (like params of axios request) to infinite function? I have to implement infinite loading on two tables that I get access to by clicking on one of the tabs. Each table load data based on query params of axios request. What I mean is:
// ...
const load = async ($state, param) => {
const res = await axios.get('/user', 'param', page)
// ......
}
Every time I add the second argument, I get an error: $state.loaded() is not a function
. In DevTools watch list I get this: $state: 'param'
. Is there somethin I can do to fix this?
Hello
Is there anyway to fire the infinite event when the page is loaded? I'm using the infinite loader in a mobile app and when the component is not yet in my viewport, the @infinite event is fired when I scroll down to the component. The problem is that some text is depending on the content of my infinite loader, so I'm looking for a way to load the data when the page is loaded. I allready tried to play arround with the firstLoad prop and I tried to call my loadData function onMounted which resulted in a to many requests error from my api
Hi im facing this error just after importing the package
I created a test project to show it
Dependency list of project
"dependencies": { "core-js": "^3.8.3", "v3-infinite-loading": "^1.3.1", "vue": "^3.2.26" }, "devDependencies": { "@babel/core": "^7.12.16", "@babel/eslint-parser": "^7.12.16", "@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-eslint": "~5.0.0", "@vue/cli-service": "~5.0.0", "eslint": "^7.32.0", "eslint-plugin-vue": "^8.0.3" }, "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/vue3-essential", "eslint:recommended" ], "parserOptions": { "parser": "@babel/eslint-parser" }, "rules": {} },
All I did is import the module:
import InfiniteLoading from "v3-infinite-loading";
import "v3-infinite-loading/lib/style.css"; //required if you're not going to override default slots
const app = createApp(App).mount("#app");
app.component("infinite-loading", InfiniteLoading);`
Error Warning when you run vue-cli-service serve
:
export 'default' (imported as 'V3InfiniteLoading') was not found in 'v3-infinite-loading' (module has no exports)
Error in chrome dev console:
Uncaught TypeError: Cannot read properties of undefined (reading 'pushScopeId')
at S (v3-infinite-loading.umd.js:1:1)
at eval (v3-infinite-loading.umd.js:1:1)
at eval (v3-infinite-loading.umd.js:1:1)
at eval (v3-infinite-loading.umd.js:1:1)
at ./node_modules/v3-infinite-loading/lib/v3-infinite-loading.umd.js (chunk-vendors.js:1868:1)
at __webpack_require__ (app.js:1106:33)
at fn (app.js:1340:21)
at eval (main.js:16:77)
at ./src/main.js (app.js:195:1)
at __webpack_require__ (app.js:1106:33)
Dummy Project Repo: LINK
Version
1.2.1
Vue.js version
3.2
Reproduction Link:
With code-editor: https://codesandbox.io/s/v3-infinite-load-issue-c99j3u?file=/src/App.vue
Fullscreen window: https://c99j3u.csb.app/
Steps to reproduce:
- Open the reproduction link where you can see 6 infinite loading component.
- Now, Scroll down the first card until you see there is "No more result!" message. (While doing this do not scroll down the actual page scroll only the within the card component).
- After you see the "No more result!" then scroll down to the page.
- Now, you can able to see that the last infinite loading card are not loading its data :(
What is Expected?
All the infinite loading component should load its data when it's in the visible area.
What is actually happening?
If any one of the infinite component is completed then it execute the "stopObserver()" function which is "disconnect()" only the last infinite loading component.
The observer doesn't track which one is completed and which one is needed to be observe. Always the last one is getting disconnect().
How to trigger by ref's dom node $state.complete()
Enhancement suggestion: Allow custom spinning wheel by using a template inside the InfiniteLoading element
Hi @oumoussa98 ,
I have an issue regarding my select component, when adding the infinite scroll to the select component, and instantiate this select multiple time in the same page, when I open the first time a select and I scroll the scroll is reset to the top,
It's working correctly if I opened an other select (the scroll is smooth and didn't trigger any reset).
I am using headless ui, but even without it, I still have the reset scroll on the first select opened,
Any idea ?
<ListboxOptions
as="div"
ref="container"
id="container-div"
class="w-full absolute z-10 bg-white shadow-lg rounded-md text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-200"
:class="[minWidthOptionsStyle]"
>
<p v-if="optionsTitle" class="text-xs uppercase text-nilos-gray-light py-1.5 px-3.5">{{ optionsTitle }}</p>
<div v-if="withSearch" class="px-2 py-1.5">
<Input
@keydown.space.stop
class="text-xs"
:placeholder="searchPlaceholder"
v-model="search"
@change="emit('onChangeSearch', search)"
:id="`${label}-search`"
:debounce="debounce"
/>
</div>
<div id="container-scrollable" class="overflow-y-auto h-32">
<ul class="divide-y divide-gray-200">
<SelectOptions :options="options" :displayOptionText="displayOptionText">
<template #prepend="{ option }">
<slot name="prepend" :option="option" />
</template>
<template v-if="!isLessThanDesktopMedium || isAppendInside" #append="{ option }">
<slot name="append" :option="option" />
</template>
</SelectOptions>
<InfiniteLoading @infinite="emit('fetch')" :distance="10" />
</ul>
</div>
<slot name="cta" />
</ListboxOptions>
I got this error on production build website
Sentry stack trace show me that the error is from this package
I don't know why element is null, maybe we have to check
function isVisible(el: Element, view: Element | null): boolean {
if (!el) return false; //<-- maybe we add this to prevent error
const elRect = el.getBoundingClientRect();
if (!view) return elRect.top >= 0 && elRect.bottom <= window.innerHeight;
const viewRect = view.getBoundingClientRect();
return elRect.top >= viewRect.top && elRect.bottom <= viewRect.bottom;
}
Hi 👋🏻 Thanks for your work.
i'm facing an issue since the last update, rolling back to v1.0.6 solved this for me.
I tried to reload the page upon variable change but it doesn't work. I tried with watcher and computed and without it. In Vue2 it worked. What is the exact syntax of an identifier to make it work? I use Vue 3 with Vite + Options API. I have seen your example with Composition API but I don't want to use exclusively Composition API since it doesn't make Vue work faster or more efficient, it only adds to the clutter. As of now I am temporarily refreshing the page with ``location.reload()` upon changing data but triggering identifier it is a more elegant way. So how to do it with Options API, thanks
Hi, I get an error when I try to place a component next to <template #default>
I installed vue3-infinite-loading via npm
npm install --save v3-infinite-loading
After importing module to specific component (MyTable.vue)
import InfiniteLoading from 'v3-infinite-loading';
import "v3-infinite-loading/lib/style.css";
I got error "Cannot resolve definitions for module 'v3-infinite-loading'".
In case of importing globally in main.ts
import {createApp} from 'vue'
import InfiniteLoading from 'v3-infinite-loading';
import "v3-infinite-loading/lib/style.css";
const app = createApp(App)
app.component("infinite-loading", InfiniteLoading)
app.mount('#app')
I got error (on second line): Could not find a declaration file for module 'v3-infinite-loading'. 'MY_PATH/node_modules/v3-infinite-loading/lib/v3-infinite-loading.mjs' implicitly has an 'any' type.
Package version:
- "vue": "^3.2.37"
- "vite": "^3.1.8"
- "v3-infinite-loading": "^1.2.2"
- "typescript": "^4.6.4"
I would be appreciate it for help.
I want to override the text when the complete slot is rendered. However when I add my named slot like so it's still showing the original text.
Also it would be nice to add a css class to this slot then you can opt to hide it with display:none.
Right now as workaround I'm hiding the unwanted text by placing a div over it using some trickery with a div that has negative margin-top.
<InfiniteLoading @infinite="load_more_matches">
<slot name="complete">THIS DOES NOT WORK</slot>
</InfiniteLoading>
<div class="hide-completed-message"/>
Currently, once the complete
event is fired, the list becomes stale and doesn't load more items, even if the list expands. The easy solution would be to either expose the state directly or a function setState(state: string)
to call on the ref.
I get a warning Cannot find base config file "@vue/tsconfig/tsconfig.json"
and an error Cannot read properties of undefined (reading 'sys')
when running the demo project from the dev branch.
Running the demo from the main branch works fine.
Executing task: pnpm run dev
> vu3-infinite-loading-demo@0.0.0 dev C:\...\vue3-infinite-loading\demo
> vite
▲ [WARNING] Cannot find base config file "@vue/tsconfig/tsconfig.json" [tsconfig.json]
../tsconfig.json:2:13:
2 │ "extends": "@vue/tsconfig/tsconfig.json",
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VITE v3.2.7 ready in 599 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Cannot read properties of undefined (reading 'sys')
14.22.51 [vite] Internal server error: Cannot read properties of undefined (reading 'sys')
Plugin: vite:vue
File: C:/.../vue3-infinite-loading/src/components/InfiniteLoading.vue
at resolveFS (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18372:35)
at importSourceToScope (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18397:14)
at resolveTypeFromImport (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18393:23)
at innerResolveTypeReference (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18299:14)
at resolveTypeReference (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18288:36)
at innerResolveTypeElements (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:17945:24)
at resolveTypeElements (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:17902:35)
at resolveRuntimePropsFromType (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19312:20)
at genRuntimePropsFromTypes (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19288:17)
at genRuntimeProps (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19278:18)
14.22.52 [vite] Internal server error: Cannot read properties of undefined (reading 'sys')
Plugin: vite:vue
File: C:/.../vue3-infinite-loading/src/components/InfiniteLoading.vue
at resolveFS (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18372:35)
at importSourceToScope (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18397:14)
at resolveTypeFromImport (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18393:23)
at innerResolveTypeReference (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18299:14)
at resolveTypeReference (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:18288:36)
at innerResolveTypeElements (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:17945:24)
at resolveTypeElements (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:17902:35)
at resolveRuntimePropsFromType (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19312:20)
at genRuntimePropsFromTypes (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19288:17)
at genRuntimeProps (C:\...\vue3-infinite-loading\demo\node_modules\@vue\compiler-sfc\dist\compiler-sfc.cjs.js:19278:18) (x2)
Hi! I was wondering is there any way to customize a spinner? E.g. by implementing bootstrap spinner-border? I tried doing it like this:
<InfiniteLoading :tableData="tableData" @infinite="load">
<div class="text-center pt-5 my-loading">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</InfiniteLoading>
But it isn't working.
When I use this library in ssr mode, it doesn't work. Is there a way to configure it?
isVisible function wasn't implemented properly, And caused those issues #4 and #5
Recommend Projects
-
-
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
An Open Source Machine Learning Framework for Everyone
-
The Web framework for perfectionists with deadlines.
-
A PHP framework for web artisans
-
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
Some thing interesting about web. New door for the world.
-
A server is a program made to process requests and deliver data to clients.
-
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Some thing interesting about visualization, use data art
-
Some thing interesting about game, make everyone happy.
-
Recommend Org
-
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Open source projects and samples from Microsoft.
-
Google ❤️ Open Source for everyone.
-
Alibaba Open Source for everyone
-
Data-Driven Documents codes.
-
China tencent open source team.
-