reacttraining / react-media Goto Github PK
View Code? Open in Web Editor NEWCSS media queries for React
License: MIT License
CSS media queries for React
License: MIT License
I'm unable to import
the module as shown in the docs & am failing to find any default export
in the source code. I'm trying to pull this into a pretty straightforward app that began using create-react-app
so I don't anticipate any compilation issues - I've been wrong before though :).
import Media from 'react-media'
gives me an error: export 'default' (imported as 'Media') was not found in 'react-media'
If I require
the module in the node cli, I don't see any default
property there either.
> var x = require('react-media')
undefined
> x
{ [Function: Media]
propTypes:
{ defaultMatches: { [Function: bound checkType] isRequired: [Function: bound checkType] },
query: [Function: bound checkType],
render: { [Function: bound checkType] isRequired: [Function: bound checkType] },
children: { [Function: bound checkType] isRequired: [Function: bound checkType] },
targetWindow: { [Function: bound checkType] isRequired: [Function: bound checkType] } },
defaultProps: { defaultMatches: true },
Media: [Circular] }
any ideas where I'm going wrong here?
I use Gatsby JS and was wondering if I need to do any modifications if I need this to work for SSR. Thanks
Part of #110. Opening this to track.
I get a bunch of runtime errors with version 1.9.0
Error: Cannot find module "@babel/runtime/helpers/esm/inheritsLoose"
Module not found: Error: Can't resolve '@babel/runtime/helpers/esm/assertThisInitialized' in ...
Module not found: Error: Can't resolve '@babel/runtime/helpers/esm/defineProperty' in ...
Module not found: Error: Can't resolve '@babel/runtime/helpers/esm/inheritsLoose' in ...
Failed to parse json
npm ERR! Trailing comma in object at 23:3
npm ERR! },
npm ERR! ^
npm ERR! File: /Users/jessierichardson/Desktop/new_proj/package.json
npm ERR! Failed to parse package.json data.
npm ERR! package.json must be actual JSON, not just JavaScript.
npm ERR!
npm ERR! This is not a bug in npm.
npm ERR! Tell the package author to fix their package.json file. JSON.parse
Hey!
Since componentWillMount
is considered unsafe in the latest version of React, i looked into replacing it with componentDidMount
.
I've integrated the component into my project (rewritten it to use Flow types, and removed json2mq
since i didn't need it).
If you'd like, i can update the current module to follow this structure.
The biggest change is that i've added a ssr
prop. If this is false (default), the client will add the matcher in the constructor method. Otherwise, the match will not happen before componentDidMount
. This is to ensure the DOM doesn't change before the first render.
This change will eliminate the DOM doesn't match when rendering serverside.
facebook/react#10591
I don't think this will break existing solutions, since the ssr=false
behavior matches the current implementation.
I've also added support for componentDidUpdate
, so the query can be changed at runtime (hot reload).
// @flow
import * as React from 'react'
type MediaQueryList = {
matches: boolean,
addListener: (handler: Function) => void,
removeListener: (handler: Function) => void,
}
type Props = {
defaultMatches: boolean,
query: string,
render?: Function,
children?: React.Node | Function,
ssr?: boolean,
}
type State = {
matches: boolean,
}
/**
* Conditionally renders based on whether or not a media query matches.
* Adapted from: https://github.com/ReactTraining/react-media
*/
class MediaQuery extends React.Component<Props, State> {
static defaultProps = {
defaultMatches: true,
ssr: false,
}
constructor(props: Props) {
super(props)
this.state = {
matches: this.props.defaultMatches,
}
if (!props.ssr) {
// If not rendering serverside, add the matcher now so state reflects the correct query
this.addMatcher()
}
}
componentDidMount() {
if (!this.mediaQueryList) {
this.addMatcher()
}
}
componentDidUpdate(lastProps: Props) {
if (this.props.query !== lastProps.query) {
this.addMatcher()
}
}
componentWillUnmount() {
if (this.mediaQueryList) {
this.mediaQueryList.removeListener(this.updateMatches)
}
}
mediaQueryList: MediaQueryList
addMatcher() {
if (this.mediaQueryList) {
this.mediaQueryList.removeListener(this.updateMatches)
}
this.mediaQueryList = window.matchMedia(this.props.query)
this.mediaQueryList.addListener(this.updateMatches)
this.updateMatches()
}
updateMatches = () => this.setState({ matches: this.mediaQueryList.matches })
render() {
const { children, render } = this.props
const { matches } = this.state
return render
? matches
? render()
: null
: children
? typeof children === 'function'
? children(matches)
: !Array.isArray(children) || children.length // Preact defaults to empty children array
? matches
? React.Children.only(children)
: null
: null
: null
}
}
export default MediaQuery
This is intended to share some thoughts, and is somewhat related to #13.
My goal is for desktop specific code not to be downloaded/evaluated on mobile devices and vice versa. This is something that I think would present a significant boost to initial load time for many websites.
Now, a combination of this library and react-loadable
would work perfectly fine, if server side rendering is not a requirement. Implementing this combination naively results in both mobile as well as desktop components being rendered serverside, which in turns results in a mismatch on the client. Actually, my current implementation (without this library), involves always rendering both components, and using CSS media queries to hide the irrelevant ones.
I understand that it's fundamentally impossible to perform media queries serverside. However, I think we should be able to do a better job than just rendering everything, always. I'm thinking of using information from the User Agent string as a heuristic to guess which elements to render.
Of course, this approach will inevitably result in mismatches in some cases, for example: User agent signals "mobile", but the device is large enough to show the desktop version according to the media queries. But I think accepting mismatches in these edge cases is worth the speedup in most of the cases.
I didn't dive into implementation details, because I'd like others to chime in, and tell me if they think it's a horrible idea before I'd invest 😛
When I make a change such as <Media query="(min-width: 1120px)">
to <Media query="(min-width: 900px)">
, I need to refresh my browser in order for the change to take effect.
react version: 16.2.0
react-hot-loader version: 4.0.1
react-media version: 1.8.0
webpack-dev-server version: 3.1.1
Per the discussion in #119. Opening this to track.
Hey @mjackson 👋
tl;dr
master
is ready to be published as 1.9.next
?next
, I'll go and polish the docsA bit of an update on the current state of the repo. I've merged most of the outstanding PRs into either master
or next
. I think master
should be publishable as a minor version bump, as we've only added Typescript definitions (#76) and the onChange callback (#95). Docs look good, and I've prepared the CHANGES.md
, you just have to add the release date.
I don't think next
is ready for deployment yet, as I'd like to do a cleanup of the docs. We've accumulated some new features over time, and while they've been added to the docs, I feel the docs now lack cohesion. Moreover, there's an outstanding PR which should improve the state of SSR (mainly preventing nasty edge-case bugs).
After we complete those things on next
, we could release a v2-alpha. What do you think?
This is a feature proposal.
Hey! I really enjoy the declarative approach of react-media
, but I just hit a wall in my use case where having a way of doing some imperative programming would really help.
When the width is enough, my screen is horizontally split in two. To the left, I have component Code
and to the right I have two tabs with components Readme
and Play
. Just one tab can be active at a time, and which one it is is tracked in the component's state
:
Now, when the width is not enough, I don't split the screen and instead convert Code
into another tab:
The problem is that, when the width of the screen changes (because of orientation change, for example), if tab Code
was active and then the tab ceases to exist, I end up with something like this:
I'd like to be able to modify the state upon a media query state change, to be able to change the active tab.
Add an onQueryStateChange
callback as a prop to the <Media>
component, so imperative stuff can be done there. onQueryStateChange
would receive the matches
state as a parameter.
In my use case, that would allow me to do:
class MyComponent extends React.Component {
state = {
activeTab: 'README'; // Active tab defaults to 'README'.
};
handleQueryStateChange = e => { // e is a MediaQueryListEvent instance.
// If 'CODE' was the active tab and it would cease to exist,
// make 'README' the active tab.
if (this.state.activeTab === 'CODE' && !e.matches) {
this.setState({ activeTab: 'README' });
}
};
render() {
return (
<Media
query={...}
onQueryStateChange={this.handleQueryStateChange}
>
...
</Media>
);
}
}
If this is something you would consider adding to react-media
, I'm happy to work on a PR for it. Thanks!
Not mentioned on README.md
.
In Reacts strict mode, react-media is triggering following error when <MediaQuery>
component is used.
Warning: Unsafe lifecycle methods were found within a strict-mode tree:
in Provider (at index-bundle.js:131)
componentWillMount: Please update the following components to use componentDidMount instead: MediaQuery
Would it be possible to comply with the strict mode ?
Thank you
I'm unable to use Media component to do anything without getting an error like this:
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of
Temp
.
I also see this warning in the console:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of
Temp
.
in Temp (created by DetailPane)
in div (created by Panel)
in div (created by Panel)
in Panel (created by DetailPane)
in DetailPane (created by Page)
in div (created by Page)
in Page (created by Root)
in Root
in AppContainer
I based Temp on the example component given in the README:
class Temp extends React.Component<{}, {}> {
public render () {
return (
<div>
<Media query={{ maxWidth: 599 }}>
{(matches) => matches ? (
<p>The document is less than 600px wide.</p>
) : (
<p>The document is at least 600px wide.</p>
)}
</Media>
</div>
);
}
}
I then try using this within another React component:
...
public render () {
return (
<Panel className={`${styles.detailPane}`}>
<h3>msg1FF</h3>
{DetailPane.createPropertyRow('Type', 'Tx', true)}
{DetailPane.createPropertyRow('Template', <FormControl type='text' placeholder='0x FF FF ...'/>)}
{DetailPane.createPropertyRow('Message ID', <FormControl type='text' placeholder='0x FF ...'/>, true)}
{DetailPane.createPropertyRow('Repeat rate', <FormControl type='number'/>, true)}
<hr/>
<Temp/>
<h4>Fields</h4>
<BootstrapTable striped hover data={fields}>
<TableHeaderColumn isKey dataField='name'>Name</TableHeaderColumn>
<TableHeaderColumn dataField='type' width='25%'>Type</TableHeaderColumn>
<TableHeaderColumn dataField='startBit' width='12%'>Start Bit</TableHeaderColumn>
<TableHeaderColumn dataField='size' width='10%'>Size</TableHeaderColumn>
<TableHeaderColumn dataField='endianness' width='15%'>Endianness</TableHeaderColumn>
<TableHeaderColumn dataFormat={DetailPane.optionsFormatter} width='60'/>
</BootstrapTable>
</Panel>
);
}
I've been seeing this error when testing out next
:
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
I've got a repro in a test, so I'll see what I can do to fix and then push a PR.
please close
Sorry for my English,
I tried to test a component that uses Media component using enzyme and jest but I got this error:
<Media targetWindow> does not support `matchMedia`
I use mount from enzyme.
As described in detail in #123, I'm seriously considering publishing the current changes under a minor version bump: 1.10
. The bulk of the preparations for this have already been done in #123.
The next step would be to implement a v2 which uses hooks for the core functionality. I expect a hooks implementation could simplify some of the internals, and would simultaneously allow us to ship a hook as part of the API.
query
prop to queries
(#72)componentDidMount
(solves #81, #91, #109, PR: #96)<Strict>
mode (#115)react-media@next
)react-media/hooks
useMedia
hook<Media>
component, which is compatible with v1.10, but uses said hook internallyI propose exposing Media
as the default export and exporting the hook as a named export:
import Media, { useMedia } from 'react-media';
This would allow people to seamlessly upgrade to v2, without having to change existing code. There's also not really any use in splitting things up, since the Media component will be very small (just a wrapper around the hook), and it will use the hook under the hood. So I don't expect us splitting up the files will result in significant bundle size savings.
Hi, I have a strange behavior. I want render a component in server side mode using user agent, but in client I want use media query, beacuse it is possible that bowser client is resized on a mobile width.
With js disabled it works well, but if it is enabled I have a warning in console
{ userAgent.desktop ?
(
<Media query="(min-width: 768px)" >
{matches =>
matches ? (
<div>Desktop <LmProductDesktop data={data}/></div>
) : (
<div>Mobile <LmProductMobile data={data}/></div>
)
}
</Media>
) :
(
<Media query="(max-width: 767px)" >
{matches =>
matches ? (
<div>Mobile <LmProductMobile data={data}/></div>
) : (
<div>Desktop <LmProductDesktop data={data}/></div>
)
}
</Media>
)
}
Now I am in desktop mode, so I rendered ssr desktop component, in the client with browser resized, I have the warning, in the dom elments I saw the correct css of mobile component, but the desktop component wrapped into media tag, the media mathched is setted to false and if I set true I saw the desktop component not the mobile.
Warning: Text content did not match. Server: "Desktop " Client: "Mobile "
Any ideas?
Not really an issue but something that bothers me (and I think other people as well). When doing a quick search for responsiveness in react react-media and react-responsive (https://github.com/contra/react-responsive) come up. So I checked both github pages out, and from what I can tell both libraries look rather similar in what and how they do it.
So I think it would be worthwhile to include some information on what the differences are and for which use cases react-media is better ....
Hi!
The latest release has not been published yet to npm https://github.com/ReactTraining/react-media/blob/master/package.json#L3.
Thanks!
Love how small the footprint is for this.
Not sure if this makes sense but wondering if this lib could be used to set variables outside of the render method for other uses.
Example I'm messing around with react-virtualized
<VirtualScroll
...
rowHeight={110}
/>
Based on the width of the screen I know what the height of my rows will be.
(max-width: 480px) set the variable to be X else set to Y
This is a follow-up from #38. I removed the commits from #39 in order to ship a 1.x without deprecation warnings, and I'd like to release a 2.x that removes the <Media query>
prop and uses <Media queries>
instead. This is a breaking change.
The API should be:
<Media queries={{ sm: query, lg: query }} children={({ sm, lg }) => (
sm ? (
// The "sm" query matched
) : lg ? (
// The "lg" query matched
) : (
// Neither query matched
)
)}/>
Note that the value of the queries
prop is not itself a media query, but its values are. The children
callback receives an object of the same shape (i.e. has the same keys) whose values are boolean, indicating if that query matches or not. A query
object may be any of the following:
(min-width: 100px) and (max-width: 200px)
{ minWidth: 100, maxWidth: 200 }
=> (min-width: 100px) and (max-width: 200px)
[ { screen: true, minWidth: 100 }, { handheld: true, orientation: 'landscape' } ]
=> screen and (min-width: 100px), handheld and (orientation: landscape)
At this point I'm thinking the render
prop should probably just be removed. We can always add it back later if people find they need it.
Hi,
I set up my app with server-side rendering.
But I got this warning in the browser:
React attempted to reuse markup in a container but the checksum was invalid.
This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting.
React injected new markup to compensate which works but you have lost many of the benefits of server rendering.
Instead, figure out why the markup being generated is different on the client or server
This is because react-media deletes some element from the DOM in the client-side according to media queries, but in the server-side rendering all elements are rendered because matches
prop is true by default.
This approach causes different DOM elements to be rendered in the client and the server.
So, how to fix this warning?
I was thinking about the solution and I found this solution.
For example I have this code:
<Media query='(some query)'>
{matches => (matches ? MatchElement : UnmatchEment)}
</Media>
Result:
<MatchElement /> || <UnmatchElement>
My solution Result is:
<style>
MatchElement {
display: none;
}
UnmatchElement {
display: block;
}
@media (some query) {
MatchElement {
display: block;
}
UnmatchElement {
display: none;
}
}
</style>
<MatchElement />
<UnmatchElement />
I think that this is a correct way to do match server-side rendering with client-side rendering at the first time and it's possible to remove this approach for others rendering in the client-side only.
What do you think?
Thanks.
Hi,
Has anyone had any success with unit testing via Enzyme shallow render?
The only way I could think of was to render twice, something akin to:
shallowCompo = shallow(MyRootComponent)
shallowMatch = shallow(shallowCompo.find(Media).prop('children')(matchesStub));
shallowMatch.find(MyChildComponent).prop('important-prop');
This did lead me to believe perhaps a HoC approach would have made it easier to control, but I know that would have its own drawbacks.
Would love to hear any other ideas/thoughts.
UPDATE:
rendering twice is not necessary, was the result of having nested children. Removing nested children allows for expected interface of
shallowCompo = shallow(MyRootComponent)
compo.find(Media).prop(‘children’)(true).props.somePop;
Hi,
I've been struggling with the onChange
callback. The break point detection works fine but the function I pass to onChange
is never called.
I use the following code:
function logOnChange() {
console.log("changed");
}
function App() {
return (
<Media query={{ maxWidth: 500 }} onChange={logOnChange}>
{matches => (matches ? <p>Small</p> : <p>Large</p>)}
</Media>
);
}
I've created a Codesandbox to illustrate the issue:
https://codesandbox.io/s/5v82oypykl
Am I doing something wrong or is this broken?
Thanks in advance!
<Media queries={{
small: { maxWidth: 991 },
medium: { minWidth: 992, maxWidth: 1199 },
large: { minWidth: 1200 },
}}>
{(small, medium, large) => {
if (small) return S
if (medium) return M
if (large) return L
}}
</Media>
Failed prop type: The prop `query` is marked as required in `Media`, but its value is `undefined`.
Would it be useful for us to provide pre-configured queries for common devices? If so, what would be the best way to expose it?
The folks over at @CSS-Tricks have compiled a nice list of media queries for standard devices that I thought we could start with. Maybe we could provide a bunch of pre-configured <Media>
components that target these devices.
<iPhone6Media>
{matches => matches ? (
<p>You're on an iPhone 6</p>
) : (
<p>You're using something else</p>
)
</iPhone6Media>
@ryanflorence Thoughts?
My app started having issues since #112 when I run it in prod mode. Even if the prop type verifications aren't run, some things rely on the prop types of a component to work properly (such as https://github.com/ngReact/ngReact).
Also, I have a component that wraps the Media component and reuses some of its proptypes like this
MediaQueryPhoneAndTablet.propTypes = {
children: Media.propTypes.children,
render: Media.propTypes.render
};
which I think is a valid use of proptypes.
My thought is while it can save a few bytes, a library should not be removing its proptypes and if an app wants that to be done, it's up to the app to do it.
Given the upcoming release of v16 of React when PropTypes will be removed and not just a warning it would be great if react-media
can start using the standalone one.
Hi,
Currently the React team is preparing for Concurrent Mode (previously known as Async Mode). To prepare my own app for that, I started wrapping my app in <React.StrictMode>
. By doing so I noticed that React Media still implements componentWillMount
, something the team advices to remove as soon as possible to prepare for concurrent mode. See https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
I was wondering if there are any plans in removing this (maybe changing it to componentDidMount
will already be sufficient?
I'm happy to make a PR if you can confirm changing this should work.
Thanks for all the effort!
Just upgraded to v1.3.1, getting this error:
(program):13 Dynamic page loading failed Error: Cannot find module "json2mq"(…)
The error can be reproduced when scaling down this codepen from above 720px to below 720px:
Instead of rendering two different components based on the query, I want to set a variable whose value then I need to pass as an attribute to the component.
Because, the only difference I need for different screen size is this attribute value. It seems this is not feasible with react-media as of now. Is there any solution to this?
Firstly, thanks for this library!
I'm currently trying to use react-media in a project which has SSR and seeing errors when the react tree mounts on the client-side (Warning: Did not expect server HTML to contain a <div> in <div>.
). Doing some experimentation on the side, I confirmed that the state of the Media component after componentWillMount
differs between client and server. if (typeof window !== "object") return
will cause it to skip calling updateMatches
on the server.
As I see it, the solution is to move the logic from componentWillMount
to componentDidMount
. If you agree, then I'd be happy to submit a PR with the change.
Receiving the following message in Travis on build 406:
NPM API key format changed recently. If your deployment fails, check your API key in ~/.npmrc.
... and later on ...
npm ERR! publish Failed PUT 401
npm ERR! code E401
npm ERR! You must be logged in to publish packages. : react-media
@mjackson could you take a look?
If you use a regular React element as children it will be rendered if the query matches. However, you may end up creating a bunch of elements that won't ever actually be rendered to the page (i.e. you'll do a lot of unnecessary createElements on each render). Thus, a children function is the preferred API.
I'm not sure I understand this, the React.createElement
would only be invoked in the case the condition is truthy.
using react 16 portals, we are rendering part of our component tree into an iframe. We ran into the issue where the Media
components in that part of the tree are referencing the parent window when we want it to reference the iframe.
Would you accept a PR to allow specifying the window object to be used (as an optional prop) for the matchMedia
call, in our case sometimes an iframe's contentWindow
?
Thanks for this great library!
I recently had an issue while rehydrating server side rendered markup that contained a react-media component. I'm pretty sure it was because the server side rendered markup was the desktop version and on the client the component immediately rendered the mobile markup when the respective media query matches.
With React 16 it's no longer mandatory to have a 100% matching markup when rehydrating; React will try to patch the DOM as best as it can. In practice this can lead to some problems though if the DOM is really different – resulting in an incosistent DOM that is a mix of the desktop and the mobile markup.
The React docs suggest a two-pass render for such scenarios that will avoid the problem:
If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.
Maybe it could be helpful to move calling this.updateMatches()
from cWM to cDM. This is a disadvantage for clientside-only apps though, as it could add a potentially unnecessary render.
One strategy could be to remove the default for the defaultMatches
prop. As this property is only needed for server side rendering, we could invoke the two-phase render only when this prop is actively provided by the user.
What do you think?
How should I setup a test where a different component is rendered depending on screen size?
This is the component:
<Media query={`(max-width: ${theme.screenSizes.sm.max}px)`}>
{matches => (matches ? this.renderMobileView() : this.renderDesktopView())}
</Media>
It only executes renderDesktopView
but I'd like to also test this.renderMobileView()
.
I've added this to my test global.window.innerWidth = 300;
with no success
Hi,
what's the current solution for multiple MQs? Multiple media components? How should I compose something like that?
A solution like this feels right to me:
<Media
query={{
sm: {
minWidth: theme.sizes.z5,
},
md: {
minWidth: theme.sizes.z10,
},
}}
>
{({ sm, md }) => (
<div>
{ sm && <span>I am small</span> }
{ md && <span> I am medium</span> }
</div>
);
}
</Media>
at small would render as:
<div>
<span>I am small</span>
</div>
and at medium:
<div>
<span>I am small</span>
<span>I am medium</span>
</div>
Thoughts?
Would you accept a PR that converts JSON input to a media query using something like https://github.com/akiran/json2mq#usage ?
Most notable benefit would be that devs could ignore syntax details of media queries:
before:
const min = 100;
const max = 200;
<Media query={`(min-width: ${min}px) and (max-width: ${max}px)`}>
foo
</Media>
after:
const min = 100;
const max = 200;
<Media query={json2mq({minWidth: min, maxWidth: max})}>
foo
</Media>
Not an issue. Just curious why function as child plus render prop. Why not just child elements?
Isn't this easier to write, and easier to separate components base on viewport width?
<Media query="(max-width: 599px)">
<p>The document is less than 600px wide.</p>
</Media>
<Media query="(min-width: 600px)">
<p>The document is at least 600px wide.</p>
</Media>
Just wanted to see if there is any downside of child elements I am not aware of.
Thanks,
Richard
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. 📊📈🎉
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.
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.