Giter Club home page Giter Club logo

tween-one's Introduction

rc-tween-one


React TweenOne Component

NPM version build status Codecov node version npm download

Browser Support

IE Chrome Firefox Opera Safari
IE 10+ ✔ Chrome 31.0+ ✔ Firefox 31.0+ ✔ Opera 30.0+ ✔ Safari 7.0+ ✔

Development

npm install
npm start

Example

http://localhost:8100/examples/

2.x: http://react-component.github.io/tween-one/

3.x: https://tween-one.vercel.app/

install

rc-tween-one

Usage

var TweenOne = require('rc-tween-one');
var React = require('react');
React.render(<TweenOne animation={{x:100}}>
  demo
</TweenOne>, container);

Plugin

var TweenOne = require('rc-tween-one');
var React = require('react');
var SvgDrawPlugin = require('rc-tween-one/lib/plugin/SvgDrawPlugin');
TweenOne.plugins.push(SvgDrawPlugin);
React.render(<svg width="600" height="600">
  <TweenOne 
    animation={{ SVGDraw:'50%'}}
    d="M0,0L100,0"
    style={{ fill: 'none', strokeWidth: 20, stroke: '#00000' }}
    component="path"
  />
</svg>, container);

TweenOneGroup

var TweenOne = require('rc-tween-one');
var React = require('react');
var TweenOneGroup = TweenOne.TweenOneGroup;
React.render(<TweenOneGroup>
  <div key="0">demo</div>
  <div key="1">demo</div>
</TweenOneGroup>, container);

API

中文文档

props

name type default description
animation object / array null animate configure parameters
paused boolean false animate timeline pause
reverse boolean false animate timeline revers
delay number 0 animate timeline delay
repeat number 0 animation all data repeat, To repeat indefinitely, use -1
repeatDelay number 0 animate timeline repeat delay
yoyo boolean false animation all data alternating backward and forward on each repeat.
onChange func null when the animation change called, callback({ moment, targets, index, mode, ratio, vars, index, repeat })
onChangeTimeline func null when the animation change called, callback({ mode, targets, vars, moment, totalTime, repeat })
moment number null set the current frame
regionStartTime number 0 Set the start time of the animation region
regionEndTime number null Set the end time of the animation region
attr boolean false attribute animation is true, when morph SVG must be true.
resetStyle boolean false update animation data, reset init style
component string / React.Element div component tag
componentProps object null component is React.Element, component tag props, not add style

animation = { }

Basic animation param. please view animation terms

name type default description
[key: string] string number array null All variables based on number, such as left, x, color, shadow
type string to play type: to from set
duration number 450 animate duration
delay number 0 animate delay
repeat number 0 animate repeat, To repeat indefinitely, use -1
repeatDelay number 0 repeat start delay
appearTo number null Add to the specified time
yoyo boolean false true: alternating backward and forward on each repeat.
ease string easeInOutQuad animate ease refer or svg path M0,100 C30,60 0,20 50,50 C70,70 60,0 100,0
bezier object null bezier curve animate
onStart func null A function that should be called when the tween begins, callback(e), e: { index, target }
onUpdate func null A function that should be called every time the animate updates, callback(e), e: { index, targets, ratio }
onComplete func null A function that should be called when the animate has completed, callback(e), e: { index, targets }
onRepeat func null A function that should be called each time the animate repeats, callback(e), e: { index, targets }

Cannot be used at the same time reverse and repeat: -1.

animation =[ ] is timeline

<TweenOne animation={[{ x: 100 }, { y: 100 }]} />

Plugins

SvgDrawPlugin

import { Plugins } from 'rc-tween-one';
import SvgDrawPlugin from 'rc-tween-one/es/plugin/SvgDrawPlugin';
Plugins.push(SvgDrawPlugin);

<TweenOne animation={{ SVGDraw: '10%' }} />

SVGDraw = string or number;

{ SVGDraw: 30 } or { SVGDraw: 'start end' } start and end values can be %;

SvgMorphPlugin

import { Plugins } from 'rc-tween-one';
import SvgMorphPlugin from 'rc-tween-one/es/plugin/SvgMorphPlugin';
Plugins.push(SvgMorphPlugin);

<TweenOne animation={{ SVGMorph: { path: '300,10 500,200 120,230 450,220 0,20' }}} />

SvgMorphPlugin API

name type default description
path string null svg path, ref: M0,0L100,0;
attr string null Svg tag attributes, example: polygon is points, path is d.
maxSegmentLength number 0.5 The lower the value, the smoother the generated animation will be, but at the expense of performance;

PathPlugin

import { Plugins } from 'rc-tween-one';
import PathMotionPlugin from 'rc-tween-one/es/plugin/PathMotionPlugin';
Plugins.push(PathMotionPlugin);

<TweenOne animation={{ PathMotion: { path: '300,10 500,200 120,230 450,220 0,20' }}} />

PathMotion API

name type default description
path string / {x,y}[] null svg path, ref: M0,0L100,0;
pathVars IPathVars null Only valid if path is array [{x, y}, {x, y}]
center number \ string[] ['50%','50%'] center point, ref: [50px, 50px];
x boolean true x follow the path.
y boolean true y follow the path.
rotate boolean true rotate follow the path.
IPathVars
name type default description
type thru \ soft \ cubic thru path type. thru same as the path; soft with the curve of attraction facing them, but not through the point; cubic allows you to define standard Cubic Bezier, example: [start, control, control, end].
curviness 0-2 1 This determines how "curvy" the resulting path is. 0 is lines, 1 is curved path, 2 would make it much more curvy. It can be 1.5.
relative boolean false Increase relative to current value. example: if the target's x starts at 100 and the path is [{x:5}, {x:10}, {x:-2}] , it would first move to 105, then 115, and finally end at 113.

ChildrenPlugin

Children = { value:, floatLength, formatMoney };

name type default description
value number null children number to value.
floatLength number null float precision length
formatMoney true \ { thousand, decimal } null format number to money.

formatMoney = { thousand, decimal }

name type default description
thousand string , no explanation.
decimal string . no explanation.

TweenOneGroup

name type default description
appear boolean true whether support appear anim
enter object / array / func { x: 30, opacity: 0, type: 'from' } enter anim twee-one data. when array is tween-one timeline, func refer to queue-anim
leave object / array / func { x: 30, opacity: 0 } leave anim twee-one data. when array is tween-one timeline, func refer to queue-anim
onEnd func - one animation end callback
animatingClassName array ['tween-one-entering', 'tween-one-leaving'] className to every element of animating
resetStyle boolean true TweenOne resetStyle, reset the initial style when changing animation.
exclusive boolean false Whether to allow a new animate to execute immediately when switching. enter => leave: execute immediately leave
component React.Element/String div component tag
componentProps object - component tag props

tween-one's People

Contributors

afc163 avatar dependabot-preview[bot] avatar dependabot-support avatar evenchange4 avatar jesuistong avatar jljsj33 avatar paranoidjk avatar shmilyyan avatar yeliex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tween-one's Issues

2.0.0

  • 全局 timeline 循环播放,全局有循环播放子级不可循环播
  • 全局 timeline ease 设定; 没什么用处.
  • 全局 timeline 回调事件, 原来的回调不变,增加 timelineMode onChange({ ...e, timelineMode });
  • #18

React does not recognize the `resetStyle` prop on a DOM element

Warning: React does not recognize the `resetStyle` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `resetstylebool` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

[email protected]

            <TweenOneGroup
              className="design-point-wrapper"
              enter={this.getEnter}
              leave={{ x: 0, y: 30, opacity: 0, duration: 300, ease: 'easeInBack' }}
              resetStyle={false}
            >
              {(this.props.isMobile || isHover) && pointChild}
            </TweenOneGroup>

数值变化动画出错

在官网的示例中随机输入一个数字会出现以下错误

index.js:335 Uncaught RangeError: Invalid array length
    at setRatio (index.js:335)
    at index.js:335
    at Array.forEach (<anonymous>)
    at c.f.setRatio (index.js:335)
    at index.js:335
    at Array.forEach (<anonymous>)
    at g.b.setRatio (index.js:335)
    at index.js:335
    at Array.forEach (<anonymous>)
    at g.b.render (index.js:335)

请教下让动画执行后无法被打断该怎么做?

场景: 一个搜索input,一个搜索对应的button。focus input的时候,input变长,button缩放。blur的时候恢复初始状态。

遇到的问题:focus的时候设置input的animation以及button的scala,blur的时候设置reverse。这样是可以工作的。但是如果在动画执行过程中再次快速focus和blur的话,动画就breaking了。

期待的效果:correct.fig

有问题的效果:wrong.gif

目前的解决方案是构造immutable,感觉很麻烦(如下),不知道有没有什么好的方案?

class SearchBox extends React.PureComponent {
  state = {
    inputTweenProps: {}
  }

  handleInputFocus = e => {
    console.log('focus');
    this.setState({
      inputTweenProps: { ...this.state.inputTweenProps, animation: { width: 400 }, reverse: false }
    });

    // 有问题的用法
   /*this.setState({
      inputTweenProps: { animation: { width: 400 }, reverse: false }
    });*/

    this.props.onFocus && this.props.onFocus(e);
  }

  handleInputBlur = e => {
    console.log('blur');
    this.setState({
      inputTweenProps: { ...this.state.inputTweenProps, reverse: true }
    });

   // 有问题的用法
   /*this.setState({
      inputTweenProps: { reverse: true }
    });*/

    this.props.onBlur && this.props.onBlur(e);
  }

  render () {
    const { inputTweenProps } = this.state;
    console.log(JSON.stringify(this.state.inputTweenProps));

    const { className } = this.props;

    return (
      <div styleName="wrap" className={className}>
        <TweenOne
          component=""
          {...inputTweenProps}
        >
          <input type="input" onFocus={this.handleInputFocus} onBlur={this.handleInputBlur} />
        </TweenOne>
      </div>
    );
  }
};

class SearchBar extends React.PureComponent {
  state = {
    searchButtonTweenProps: {}
  }

  handleSearchBoxFocus = () => {
    this.setState({
      searchButtonTweenProps: { ...this.state.searchButtonTweenProps, animation: { scale: 0, duration: 250 }, reverse: false }
    });

    // 有问题的用法
   /*this.setState({
      searchButtonTweenProps: { animation: { scale: 0, duration: 250 } }
    });*/
  }

  handleSearchBoxBlur = () => {
    this.setState({
      searchButtonTweenProps: { ...this.state.searchButtonTweenProps, reverse: true }
    });

   // 有问题的用法
   /*this.setState({
      searchButtonTweenProps: { reverse: true }
    });*/
  }

  render () {
    const { searchButtonTweenProps } = this.state;
    console.log(JSON.stringify(this.state.searchButtonTweenProps));

    const { className } = this.props;

    return (
      <div className={className}>
        <SearchBox onFocus={this.handleSearchBoxFocus} onBlur={this.handleSearchBoxBlur} />

        <TweenOne
          {...searchButtonTweenProps}
          component=""
        >
          <Button>搜索</Button>
        </TweenOne>
      </div>
    );
  }
};

对于负数的处理方式

-1 符合预期,输出:-1.00
-1.11 不符合预期,输出: -1.00
-0.11 不符合预期,输出: 0.00
1.11 符合预期,输出: 1.11
0.11 符合预期,输出:0.11

API 建议(长期补充)

  1. vars 改为 animationkeyframes

  2. type={start|pause|reverse|restart} 不是声明式的语法,可以拆为 paused={true|false} reverse={true|false}。可加入时间轴的参数来控制动画的状态。

    <Tween defaultMoment={0}></Tween>
    onChange(moment) {
      this.setState({ moment });
    }
    ...
    <Tween moment={this.state.moment} onChange={this.onChange}></Tween>

    moment 表示动画当前运行到的总时刻

  3. vars 里的 type 感觉没用。

  4. varsonXxxx 可以都提到 Tween 上面的 onChange,相关信息放在参数里。

onChange(moment, currentKeyframe) {
  // currentKeyframe
  // currentKeyframe.currentDuration => currentDuration
}

height transition is not working

參考 ant-motion

      <Table
        rowKey="id"
        columns={columns}
        dataSource={filterTable}
        components={{
          body: {
            wrapper: useCallback((cprops: any) => {
              return (
                <TweenOneGroup
                  component="tbody"
                  leave={[
                    { duration: 250, opacity: 0 },
                    { height: 0, duration: 200, ease: "easeOutQuad" }
                  ]}
                  appear={false}
                  exclusive
                  {...cprops}
                />
              );
            }, [])
          }
        }}
      />

似乎無法顯示出高度的變化, opacity 可正常顯示,
ps: 仍然有warning
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Issue with storybook shots testing

Got this error

● Storyshots › PageHeader › Details

TypeError: _this.target.getAttribute is not a function

  at node_modules/rc-tween-one/lib/Tween.js:108:51

storyshots.test.ts

import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';

import '@/testUtils';

initStoryshots({
  test: multiSnapshotWithOptions({}),
  // TODO: Layout for now skip testing because issue with ant pro layout component
  storyKindRegex: /^((?!.*?(Theme|Layout|DetailsPage)).)*$/,
});

@testing-library/react pass ok

请教问题

用react来做动画,除了可以封装成组件提高团队的开发效率,还有什么优势么?

不在当前窗口时不进行动画

tween-one/src/ticker.js

Lines 41 to 56 in 58e6dd3

p.tick = function (a) {
ticker.elapsed = getTime() - ticker.lastUpdate;
ticker.lastUpdate += ticker.elapsed;
if (!ticker.frame) {
ticker.frame++;
} else {
ticker.frame += Math.round(ticker.elapsed / ticker.perFrame);
}
ticker.tickFnArray.forEach(func => func(a));
// 如果 object 里没对象了,自动杀掉;
if (!ticker.tickFnArray.length) {
ticker.sleep();
return;
}
ticker.id = requestAnimationFrame(ticker.tick);
};

不在当前窗口时, raf 停止工作,但时间在变动,所以在回到窗口后会有一次跳动,还有相关重复播放的 bug。

解决方案: 在离开窗口时记录当前时间,回到窗口后把当前的时间与记录的时间相减,结下来在 getTime 里减去两值的相差。。

记录一下,没时间整。。

Is there any way to control when the animation begin on scroll?

I found that the animation will start when the object is scrolled to the middle of the screen.
I tried to use playScale and other API to make the animation start when the object reach the bottom of the screen but none of the API is working.

Is there any way to make the animation works when object reach the bottom of the screen??

0.8.0

  • 减少 this.setState, 太卡
  • 倒放时,多个时未归0.

0.2.6

  • cssMatrix 取 transform;
  • 标签上的参数,SVG;
  • Css 230 231 split(' ') 错误, 还原 style={{ transform: 'translate(100px, 200px) rotate(30deg)' }}

babel-runtime 和 core-js 3 冲突

当前项目中 package.json部分包

"@babel/core": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"@babel/preset-react": "^7.10.4",
"@babel/runtime": "^7.11.2",
"@babel/runtime-corejs3": "^7.11.2",
"core-js": "^3.6.5",
"rc-tween-one": "^2.7.3",
"react": "^16.13.1",
"antd": "^4.6.2",

使用 rc-tween-one 报错

image

useLayoutEffect does nothing on the server

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.

null is not an object (evaluating 'this.target.ownerSVGElement')

Hi!

First of all - awesome package. Make apps look really fancy with all those animations!

I've started receiving the following error:

null is not an object (evaluating 'this.target.ownerSVGElement')

Tried to debug it for a long time. It just happens when I load the page that uses this package, but not always (approx. 10 out of 100 cases). Unfortunately that's all that I currently have.

Any ideas why it might be happening and what can I or we do to stop it?

edit
I've seen that it was the case of PR27. What was the reason it was not an acceptable solution?

rc-tween-one 3.x: Table animations

Hi,

I am trying out rc-tween-one 3.x, because I need compatibility with AntD 4.x, but I'm not being able to animate an AntD Table.

I'm following this example: https://motion.ant.design/exhibition/demo/table-enter-leave, by creating a TweenOneGroup in Table.components.body.wrapper.

I'm getting an error from the TweenOne child components: TweenOne domRef is error, and animations are not working. As seen in the React plugin for Chrome:
image

Is there a way to solve this issue? Would you have an example on animating an AntD 4.x table?

样式合并重整。

1。 动画一次后,再变更style..

2。 this.props.style 与 nextProps.style 的问题,在跑马灯里,改变style时, this.props.style 与 nextProps.style 相等了

试着用Ant Motion的Sortlist调用tween-one在动画收尾的时候会err

TweenOne.js:317 Uncaught TypeError: Cannot read property 'totalTime' of null
at TweenOne.frame (TweenOne.js:317)
at Object.raf [as func] (TweenOne.js:367)
at ticker.js:77
at Array.forEach ()
at ./node_modules/rc-tween-one/es/ticker.js.p.tick (ticker.js:76)
frame @ TweenOne.js:317
raf @ TweenOne.js:367
(anonymous) @ ticker.js:77
./node_modules/rc-tween-one/es/ticker.js.p.tick @ ticker.js:76
requestAnimationFrame (async)
./node_modules/raf/index.js.module.exports @ index.js:64
./node_modules/rc-tween-one/es/ticker.js.p.tick @ ticker.js:84
requestAnimationFrame (async)
./node_modules/raf/index.js.module.exports @ index.js:64
./node_modules/rc-tween-one/es/ticker.js.p.tick @ ticker.js:84
requestAnimationFrame (async)
./node_modules/raf/index.js.module.exports @ index.js:64
./node_modules/rc-tween-one/es/ticker.js.p.tick @ ticker.js:84

Compile issue with latest nextjs version (swc, not babel)

Hi,
I use rc-tween-one with latest version of nextjs ("next": "12.0.7",) and get the compile error:

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:988:16)
    at Module._compile (internal/modules/cjs/loader.js:1036:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
    at Module.load (internal/modules/cjs/loader.js:937:32)
    at Function.Module._load (internal/modules/cjs/loader.js:778:12)
    at Module.require (internal/modules/cjs/loader.js:961:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (/path/to/my-proj/node_modules/rc-tween-one/lib/plugin/PathMotionPlugin.js:10:48)
    at Module._compile (internal/modules/cjs/loader.js:1072:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)

error - SyntaxError: Cannot use import statement outside a module 
/path/to/my-proj/node_modules/tween-one/es/plugins/PathMotionPlugin.js:1
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
^^^^^^

FYI, next@12 use swc instead of babel

Reproduction steps

  1. Create new next app
yarn create next-app --typescript
yarn add rc-tween-one
  1. Use rc-tween-one:
    pages/_app.tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'

//  ----> Add this line
import TweenOne from 'rc-tween-one';

function MyApp({ Component, pageProps }: AppProps) {

   // ----> Add this code
  return (
    <TweenOne
      animation={{
        x: 80,
        scale: 0.5,
        rotate: 120,
        yoyo: true, // demo 演示需要
        repeat: -1, // demo 演示需要
        duration: 1000
      }}
      paused={false}
      style={{ transform: 'translateX(-80px)' }}
      className="code-box-shape"
    />
  )
}

export default MyApp

Expected behavior

Can compile and run it

Thanks

请问下 TweenOneGroup 怎么设置第一次不执行动画?

有个列表,代码大概是这样的。第一次获取到数据之后渲染列表,希望不执行动画,后面列表数据有增删的时候再显示动效。

<TweenOneGroup
  component="div"
  enter={enterAnim}
  leave={leaveAnim}
  appear={false}
  exclusive
>
    {data.map((item, idx) => <List.Item key={item.id} />)}
</TweenOneGroup>

Minus start position problem in Safari

If the tween-one component's animation start position is a minus value. Then in the latest Safari (both Mac and iPhone), the animation will start from position 0.

Keep getting Module not found: Can't resolve 'rc-tween-one'

Hi,

I'm trying to start a react project using 'npm start', however it fails to compile and states the following:

./src/component/savedfront.js
Module not found: Can't resolve 'rc-tween-one' in 'E:\reactgame\gameone\gamefront\src\component'

After this, it no longer runs the project but instead gives me this error.

Do let me know how I can fix this,

Appreciated

Start Error

启动后访问页面不成功, 控制台报 Error

image

webpack: bundle build is now finished.
  <-- GET /
  --> GET / 200 12ms 11.04kb
  <-- GET /examples
  --> GET /examples 200 10ms 15.33kb
  <-- GET /examples/childrenUpdate.html
  xxx GET /examples/childrenUpdate.html 500 75s -

  Error: connect ETIMEDOUT 30.129.144.64:8100
      at Object._errnoException (util.js:1022:11)
      at _exceptionWithHostPort (util.js:1044:20)
      at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1198:14)

其中 错误提示 : 【Error: connect ETIMEDOUT 30.129.144.64:8100】
但我的Ip 是: 30.5.54.82

image

one question

Is this based on an open source library React-Tween-State ?

NextJS TweenOne useEffectLayout Warning

I'm getting this warning in the console:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client.

Anyone else having this issue?
Is there a good way to solve this?

0.3.0

  • tweeOneGroup, 子级进出场切换。。。
  • 增加 reverse 开始时延时
  • 所有动画用单时间轴,问题: 两个动画相同时间相同位置,过渡中间错位。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.