GithubHelp home page GithubHelp logo

react-native-drax's Introduction

react-native-drax

A drag-and-drop system for React Native

"Not to be confused with react-native-picksaw"

npm version Contributor Covenant

Overview

Drax is a declarative drag-and-drop system for React Native, written in TypeScript. It is designed to be flexible and powerful with the goal of supporting many use cases, while its stock components and default settings should cover the most common scenarios with minimal configuration.

Note: as of version 0.10.0, React Native 0.65 or higher is required. For RN 0.62-0.64 projects, you may be able to use 0.9.3, but it will no longer be supported. For RN 0.61 projects, you may be able to use 0.6.0, but it will no longer be supported.

Personal note from Joe: this project is in need of additional contributors/shepherds. I have not been focused on React Native over the past year, and the state of the library has fallen behind the times. At a minimum, it should be updated to use the latest RNGH and take advantage of any fixes and new features in that and RN. I apologize that I do not have the availability to maintain this project to my own high standards and thank everyone who has been understanding of that.

Contents

Screenshots

Color Drag-and-Drop Reorderable List Knight Moves Knight Moves

(Click images to see larger versions.)

Status

This library adheres to Semantic Versioning (semver) and is in its 0.y.z initial development phase. It has been released so that early adopters (such as the project author) can begin to use it in production and identify gaps in the functionality. The API is subject to potentially significant rework until version 1.0.0 is released, and any minor version increment before then may include breaking changes. Documentation and full examples are still being written.

The author of this library has not had significant availability to work on it for quite a while now, due to higher priority life and work concerns. Newer versions of Drax's major dependencies have been released in that time, and many people have opened issues asking questions about usage and potential features. Relatively small fixes and easy questions are handled reasonably often, but ultimately another round of research, testing, and architecture are what would take this library to the next level of usability. It is not clear when that might happen, but contributors are welcome.

Background

To give an idea of the problem this library is trying to solve, here is some informal background:

In our React Native application we had a screen which showed a FlatList of cards that could be scrolled through or individually tapped to view details. We wanted to add the ability for a user to long-press a card then drag it into a different position in the list; in other words, we needed a reorderable list.

I figured there must already be a library out there that would suit our needs. I tried out a few different packages, which each looked to have pros and cons, but nothing quite worked right how we expected. To complicate things further, our application used react-navigation, which seemed to conflict with some of them.

We also had future features on our roadmap which would necessitate a more generic drag-and-drop solution. I found it a bit odd that, although reorderable lists and drag-and-drop have much functional overlap, there didn't seem to be a package for React Native which did both. It looked like React for the web was a little more mature in this arena, but that didn't help us. I asked some other developers if they knew of a solid React Native library for this, but they agreed that it was a gap in the ecosystem.

I decided to create my own drag-and-drop library, including stock components for common behaviors. The goal, first and foremost, was to fulfill our draggable reorderable list wish. But beyond that, I wanted a robust foundation that could be used to flexibly implement various drag-and-drop-related solutions. I am sure that there are scenarios I have not yet considered, and I am open to input from other people who are working in this space.

Concept

Descriptions of the library's approach, underlying implementation, and drag-and-drop event lifecycle can be found in the Concept Document.

Installation

First you must have a project using react-native version >=0.62, including react-native-gesture-handler version >=1.8.0. For further information on installing the latter, see that library's documentation.

Then simply install Drax with:

yarn add react-native-drax

or

npm install react-native-drax

There is no Cocoapods or native linking step here. You've already covered those needs with react-native-gesture-handler.

Usage

Basic Usage

Import the library components:

import { DraxProvider, DraxView } from 'react-native-drax';

Wrap the area of your app that will use Drax with a DraxProvider, and create a couple DraxViews, one draggable and one receptive:

<DraxProvider>
    <View style={styles.container}>
        <DraxView
            style={styles.draggable}
            onDragStart={() => {
                console.log('start drag');
            }}
            payload="world"
        />
        <DraxView
            style={styles.receiver}
            onReceiveDragEnter={({ dragged: { payload } }) => {
                console.log(`hello ${payload}`);
            }}
            onReceiveDragExit={({ dragged: { payload } }) => {
                console.log(`goodbye ${payload}`);
            }}
            onReceiveDragDrop={({ dragged: { payload } }) => {
                console.log(`received ${payload}`);
            }}
        />
    </View>
</DraxProvider>

The styles are provided here for completeness:

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    draggable: {
        width: 100,
        height: 100,
        backgroundColor: 'blue',
    },
    receiver: {
        width: 100,
        height: 100,
        backgroundColor: 'green',
    },
});

This will give you a blue box which can be dragged around and a green box which it can be dragged into. Watch the console log messages while you drag the blue box around, releasing the drag either in or out of the green box.

API

Full API description coming soon

Caveats

This library has several known issues and limitations, particularly around the Android platform. We hope to address these and improve the library over time. For most use cases, the current functionality is probably fine.

This library currently expects React Native >=0.62 and React Native Gesture Handler >=1.8. Due to complexity, we cannot support the use of the library with older versions.

Examples

A reference application can be found at react-native-drax-example demonstrating several use cases.

If you don't want to download and run the sample application, here are two Snack examples:

Note: these Snack examples will not work in the Web device. You must use an iOS (default) or Android device.

Contributing

Issues, pull request, and discussion are all welcome. See the Contribution Guidelines for details, and please reach out to the author if you would like to participate more significantly.

Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

License

This software library is licensed under the MIT License.

Acknowledgments

The initial version of this library was written by Joe Lafiosca over the course of December 2019. Joe would like to give thanks to Nuclear Pasta co-founder Mark Thomas for being patient with the development process. Joe would also like to give thanks to Lena Raine, Tom Jenkinson, Rollie Pemberton, David Minnick, Tim Smith, and Danny Baranowsky for providing most of the coding background music that inspired this work.

Special thanks go to the folks who have contributed donations toward this project. (If you are a sponsor and would like your name listed here, please let me know! I do not want to make assumptions about people's privacy preferences.)

react-native-drax's People

Contributors

chrisdrackett avatar dependabot[bot] avatar francoisdupayrat avatar jmarnold avatar lafiosca avatar negue avatar rnz269 avatar special-character avatar sturdynut 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

react-native-drax's Issues

Determine compatibility with react-native-safe-area-context v3 and react-navigation v5

Drax needs to be updated to support RN 0.62+ (0.63 at time of writing this) as per #54

I'm in the process of updating my mobile app which uses Drax from RN 0.61 to 0.63, and as part of that effort I'm moving from react-navigation v3 to v5. That library used to provide a custom SafeAreaView, but in v5 they recommend using react-native-safe-area-context (which is on v3 currently).

I need to determine whether Drax is compatible with the latest react-native-safe-area-context and react-navigation, at least for the most common use.

DraxProvider should respect parent padding

Currently DraxProvider uses an absoluteFill to fill its parent view entirely. This means that it does not respect the parent's padding, which can be bad in some cases (e.g., when using certain implementations of SafeAreaView). Let's change it to use flex: 1 instead.

onMonitorDragEnd is only called if drag is cancelled?

It's unclear to me why this block was wrapped in if (cancelled):

if (cancelled) {
response = monitorData.protocol.onMonitorDragEnd?.({
...monitorEventData,
...getRelativePosition(screenPosition, monitorData.absoluteMeasurements),
cancelled,
});
}

Especially because that makes the lines following the block meaningless.

This is the only place onMonitorDragEnd occurs, but it appears with the current logic that it would ONLY be called when a drag is cancelled, never from a drag naturally ending outside of a receiver within the monitor.

itemStyles are somewhat confusing

I'm finding itemStyles on DraxList somewhat confusing, but maybe I'm thinking about them incorrectly. Here is what I'm finding:

  • dragReleasedStyle: the style of the receiving "space" after an element is released.
  • draggingStyle: seems to be the style of the "space" that the picked up item came from, but only shown when being hovered
  • draggingWithoutReceiverStyle: the style of the "space" the element was picked up from if the element isn't over the list anymore.
  • draggingWithReceiverStyle the style of the element in the position the original item came from when not being hovered
  • receivingStyle: the style of the element that the current item will replace when released.

I found the above while trying to find a way to style the space (#37) and also trying to adjust the style of the item being dragged when it leaves the list (for example to reduce its opacity when it isn't over the list anymore.)

Drop is not possible on the visible receiver when width is set dynamically.

The width of the <DraxScrollView /> is set to device width and height will take the autoscroll. When one card is dropped on the <DraxScrollView /> we increased the width dynamically using javascript. We can see width of the <DraxScrollView /> is increased but the visible receiver will not receive the new card dropped. It seems the receiver position is bound with the old width of the <DraxScrollView />.

How can we make the receiver receives even we are giving the width dynamically?

The attachments:
image 1, is the first view, image 3 is with dynamic width added, image 4 the receiver is not receiving the card.

image
image
image
image

Feature Request: Add callback on DraxList for when the dragged item changed hover index

Thanks for the awesome project! It has already been the best drag and drop library that I have seen for react native.

I am using the DraxList to re-order my items and want to provide haptic feedback whenever the item is dragged to a new hover position. i.e. When dragging and item down the list I want to be able to know every step down the list it is dragged before it is released at the final position.

I will take a look at creating a PR for this. I think it should be straightforward given the amount of event hooks that are available.

Explicitly set useNativeDriver for animated views

In RN 0.63, we have this new warning when dragging views:

Animated: `useNativeDriver` was not specified. This is a required option and must be explicitly set to `true` or `false`

Update the library to fix this.

Provide drag translation value in events

In event handlers, it would be nice to know the cumulative drag translation, i.e., the x/y diff from the original absolute grab point to the current absolute drag point. This can let you do things based on how far a view has been dragged.

Please add PropTypes to the Drax components

The library is written in TypeScript, which provides basic compile-time type safety to developers who are using that. PropTypes should be added to the components for run-time type safety and for developers using JavaScript.

DraxScrollView scrollTo function is undefined.

I am trying to make the card center of the DraxScrollView which will have the dynamic width based upon the number of the cards DraxScrollView is acquiring.

I have used <DraxScrollView contentContainerStyle={[styles.receivedZone,]} alwaysBounceVertical={true} maximumZoomScale={10} minimumZoomScale={-2} directionalLockEnabled={false} horizontal={true} ref={(ref) => this.draxScrollViewRef = ref.getNodes()} > <View onLayout={event => this.layout = event.nativeEvent.layout} style={{ position: 'relative', width: 105, height: 105, overflow: 'visible' }} > <Text>Cards content</Text> </View> </DraxScrollView>

The reference is then used on ` componentDidMount = async () => {

	setTimeout(() => {
		this.draxScrollViewRef.getNodes().scrollTo({
			y: this.layout.y,
			x: this.layout.x - GlobalItem.deviceWidth / 2 + 55,
			animated: false
		})
	}, 100);

}`

But the end result is TypeError: _this.draxScrollViewRef.getNodes is not a function. (In '_this.draxScrollViewRef.getNodes()', '_this.draxScrollViewRef.getNodes' is undefined)

What can be done?

Should DraxView longPressDelay default to 0?

Currently, there's a default longPressDelay of 250ms on DraxView:

export const defaultLongPressDelay = 250;

Why? I mean, I know why as the author: the initial use case was to implement a drag-reorderable list, which meant that I needed the delay to prevent the drags from capturing list scroll gestures. But for the standard DraxView use case, might we not want to default to 0, which allows instant grabbing of the view to drag?

One possible counterpoint would be when the draggable views may have standard Touchable buttons embedded in them. The longPressDelay prevents the drag from hijacking those touches. But it can be lowered a little bit for that case as well. The 250ms value came from what "felt right" for reorderable lists.

Only animated values should use Animated.ValueXY

Currently the API returns Animated.ValueXY for several items, such as:

/** The relative offset the drag point in the receiving view */
receiveOffset: Animated.ValueXY;
/** The relative offset/dimensions ratio of the drag point in the receiving view */
receiveOffsetRatio: Animated.ValueXY;

It's actually a hassle to deal with Animated.ValueXY if you're not using it for styling a view. For instance, if you want to read the x value to see if a receiveOffset is in the left/right edges of a receiver, you just want to compare receiveOffset.x to something. A Position value would be more helpful here.

When first building the library, I erred on the side of making more things Animated.ValueXY, but I've realized that there's really no point to using an Animated.ValueXY unless you're going to animate it. Currently only hoverPosition is being animated by the library, so I think we should change these other items into Positions. If/when we need to animate any more of them in the library, we can change them again or add extra fields.

Unify drag/receive event shapes

For consistency, let's consider generally unifying the shapes of the events for onDrag*, onReceive*, onMonitor*. It will make the implementation logic a little bit easier, and it will perhaps be less confusing.

For example, let's always group the dragged view data into a dragged object, rather than having it in dragged for onReceive* and in the root for onDrag*.

We will still need more specific extended shapes for events which have a receiver, events which can be "cancelled", and monitor events.

Drax measurements for dynamic layout items are slightly off after orientation change

Issue #8 addressed the problem with Drax measurements breaking entirely after an orientation change. However it seems there may be a race condition when nesting using Drax with react-native-safe-area-context insets which change from an orientation change. All view measurements seem to become off by a bit diagonally, and even after returning to the original orientation they are broken. Let's see if we can make Drax even more resilient to this type of thing, perhaps by introducing a slight timeout delay for the DraxView remeasurement after orientation change. (Perhaps this delay could be configurable via a DraxProvider parameter, with a sensible default, for greater hacking flexibility.)

Is it possible to pass my own onScroll to DraxList?

I am trying to replace a react-native-draggable-flatlist with this library however they have a onScrollOffsetChange prop that allows me to do a parallax effect while scrolling. If I can pass my own onScroll to the FlatList I should be able to replicate the same effect.

example:

onScroll={({ nativeEvent }) => {
    this.state.scrollY.setValue(nativeEvent.contentOffset.y);
}}

Alternatively is there a way to use values form the useDraxRegistry?

Changing length of DraxList data array causes app to crash

When a DraxList is reused with a new data array of a shorter length, the cached reorder logic causes it to send undefined items to the underlying FlatList, which can crash the app when the keyExtractor or renderItem methods try to access fields of the undefined item.

Why DraxView is not working as it should be with ScrollView?

I am using the inside the when the is pressed it pops out from the original position and works smooth for all those which are visible, once we scroll it horizontally and pressed it, it do not pop out from position where it is pressed but comes out from the position where the is originally placed while loading.
image

image

image

Upgrade react-native devDependency to 0.62.x

There is a security alert for logkitty, but we've inherited that dependency from the React Native CLI v3, which we've inherited from RN 0.61. Upgrading to 0.62 makes sense because it's the latest, and it resolves this security alert. (Note that this security alert probably should not impact our end users since it's only for a devDependency.)

This should be straightforward, but I am not currently set up to verify it by testing the lib after making the change. I'm leaving this issue here to remind me to take care of it for this repo and for react-native-drax-example while I'm at it.

Provide viewState/grabOffset in event data?

The content rendering functions that can be passed to DraxView receive a DraxViewState prop which contains useful information like grabOffset and dragOffset:

/** If being dragged or released, the position in screen coordinates of the drag point */
dragScreenPosition?: Animated.ValueXY;
/** If being dragged or released, the relative offset of the drag point from the view */
dragOffset?: Animated.ValueXY;
/** If being dragged, the relative offset of where the view was grabbed */
grabOffset?: Position;
/** If being dragged, the relative offset/dimensions ratio of where the view was grabbed */
grabOffsetRatio?: Position;

These values are not currently provided in any of the drag event data passed to the drag-drop lifecycle callbacks. Should they be? I think it would be nice in some cases to have that data available.

And this raises a more general question: would adding required fields to the shape of an interface like DraxEventData be considered a breaking change? I think technically it would be. For example, if someone is using that interface to construct objects in their own code, that could break, although the average consumer of this library would presumably only be receiving/handling such objects from the library. The interfaces/types are exposed primarily for flexibility and convenience. Still, it doesn't hurt for us to release additional minor version bumps while in 0.x.

Bug: DraxList doesn't handle dragging out of the list and back in

I noticed that dragging an item outside the DragList and back into the list has odd behavior. Here is a screen cap.

DraxList Exit Bug

In the example, I drag an item over the tab bar which is outside the DraxProvider. I confirmed that pulling the DraxProvider up to the root of the app fixes the issue but I can't do that for my current use case.

It seems that it starts behaving as expected only after I drag it back to it's original position. I am guessing that the onMonitorDragExit is called when it exits but it doesn't call onMonitorDragEnter and set handlers back up accordingly. I will take a crack at making a PR for this!

DraxList doesn't work correctly with numColumns > 1

h/t to Caleb Clarke for asking about this.

The shifting logic in DraxList assumes the underlying FlatList will only have a single column or row. When you increase the numColumns attribute above 1, the shifts don't look right:

multi-column

The existing shift-transform approach might work with some additional logic, but experimentation with Android will be necessary to determine if there is a similar problem to #1.

Note: in FlatList, numColumns only works with horizontal=false and specifically mentions that all items should be the same height. This might simplify some of the assumptions.

support styles on both `DraxList` and its `FlatList`

to have full control over the styles of this component I think it is currently needed to be able to pass styles both to the FlatList and to the DraxList. For example if I want to add padding to inside the FlatList or have effectively flex: 1 it is needed to add styles to both elements.

Android drag offset issues

Now that react-native-drax-example has been updated to the latest react-native, react-navigation, react-native-safe-area-context, and react-native-gesture-handler, I'm experiencing a few functionality problems with drags on the Android build.

On a physical Galaxy S7 Edge, everything seems to work as expected until I rotate the phone into a different orientation. The display automatically rotates, but the drag offsets are wrong, to the point of almost completely breaking the Knight Moves example.

On an emulated Pixel 3a, the drag offsets are wrong when the Color Drag/Drop screen first loads. Specifically, when grabbing a color block, it hovers what appears to be roughly one Android status bar height vertically above where the gesture is touching. The other examples work as expected. Then when I rotate the emulated device, it doesn't automatically reorient the app, but a little software rotation button shows up, as seen in the upper-right corner of this screenshot:

image

When I click this, the app reorients into landscape, and all offsets work fine. Then if I rotate back into portrait and click the button again, everything behaves as it should. This implies to me that during the initialization of the app, Drax is somehow calibrating its base coordinates in the wrong place (perhaps not accounting for status bar), but that when the orientation change handler recalibrates, it's fine. As with all Android issues, I dread trying to determine whether this is specific to only certain devices.

Horizontal DraxList items vanish while shifting on Android

With a DraxList in horizontal mode, on Android the items seem to vanish while they are shifted during a reordering drag. This does not happen on iOS, and it does not happen in vertical mode. It appears that Android may be doing some kind of additional view clipping on each view inside the underlying FlatList to cause this. Without digging into React Native's code, it's unclear why this would only apply to horizontal mode. It's also not obvious to me whether there could be a simple solution or workaround that we can apply within in this library.

Minimal reproduction example here: https://snack.expo.io/@lafiosca/horizontal-draxlist?platform=android

Option to show target placeholder in DraxList reordering

When dragging an item to reorder a DraxList, there is already a feature that shows a semi-transparent item target position placeholder during the snapback after release. It might be nice to have an option to show this placeholder even before the item is released, for the user to visualize where the dragged item will go before releasing it. (This could probably be accomplished using the same shift transformation logic already being used for all of the other items shifting.)

Dragging a DraxList item more than one container length on Android cancels the drag

If you have a DraxList with content extending beyond the length of the list container, dragging one of its list items over one of the ends of the list container will auto-scroll the list contents. If this auto-scrolling takes your item drag more than one full length of the container from the item's initial position, on Android the drag will be cancelled at that point.

DraxList has a logic to mitigate this behavior in regard to list item reordering. Rather than losing the drag progress entirely, it considers the item to have been dragged and dropped to the point of cancellation. Still, it would be preferable if the cancellation didn't happen at all. I'm not sure if there is anything we can do within this library to fix it. The answer likely lies in react-native-gesture-handler, if anywhere.

You can reproduce this behavior in the basic reorderable list example on the Android device: https://snack.expo.io/@lafiosca/react-native-drax---basic-reorderable-list?platform=android

add ability to not have "space" in `DraxList` when hovered item is not over list

Currently if you drag an item outside of a DraxList the empty space shifts back to the spot that the item came from. This leads to some undesirable visual issues with items jumping around. I would like to make the following suggestion:

  1. when an item is dragged outside of its parent list don't show any empty space in that list anymore
  2. if the item is released on another receiver everything is good to go
  3. if the item is released outside of any receiver, while the item is animating back to its place in the list open the space back up.

Basically the space would open if the item comes back over the list based on the items location OR if the item is released and needs to go back to its original location.

Ghost hoverView left behind after slow animation

If you use a slow enough snapback and reposition the dragged DraxView, it's possible to leave a ghost hoverView at the previous position of that DraxView which vanishes the next time it is dragged. This is most easily reproducible in react-native-drax-example's "Knight Moves" tab by setting a snapbackDelay, snapbackDuration, or custom snapbackAnimator with a 5+ second animation.

Change names to no longer refer to "screen"

Originally in Drax development, coordinates were measured absolutely on the screen. At some point, to work around gaps in functionality, we began measuring all views in relation to the DraxProvider root view. This means that the screenPosition values are not actually screen positions. Rather, they are absolute positions in the frame of reference of the DraxProvider. Let's change screen to absolute everywhere for consistency. Then if we decide to expose actual screen positions in the future, we can use that naming convention for those.

Feature Request: Allow specifying custom Animated function for moving/snapping dropped items

It would be great to be able to specify the animation for a dropped item. Right now it is this timing function:

https://github.com/nuclearpasta/react-native-drax/blob/master/src/hooks/useDraxRegistry.ts#L493

I confirmed that I could manually change that to the spring function and it worked as expected. I could probably take a look at doing this. It should be a fairly straightforward option to configure.

Improve reorder behavior when dragging beyond DraxList item content

If you have a short DraxList where the length of the content does not fill the entire list container, the drag-to-reorder behavior may feel a bit unintuitive when dragging an item to the end of the list.

image

Specifically, in the screenshot above, dragging one of the letter items down will cause the list to reorder only as long as the drag is over one of the other letter items. If you drag one down into the grey zone at the bottom of the list, the drag is no longer considered to be internal to the list, and the items all return to their original positions.

It might be nice if dragging over this end zone were considered the same as dragging over the final item in the list. This becomes more apparent when looking at a real life example in which the user could be frustrated that the item snaps back to where it was when dragging past this "invisible" border:

image

Here is the Snack reproduction that the first screenshot comes from: https://snack.expo.io/@lafiosca/short-draxlist?platform=ios

Enhance DraxList onItemDragPositionChange to recognize original position index

The new logic in #42 introduces the DraxList onItemDragPositionChange event handler property. When dragging an item over any other item in the list, that callback receives the position index of the item being dragged over. When dragged anywhere else, including the dragged item's original position, the list header/footer, or outside the list, the callback receives an undefined index. It might be nice for the callback to receive the item's original position index rather than undefined when dragging over the item's own position. This would require additional logic in the DraxList monitoring because the original item can't receive its own drag like the rest of the list items do.

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.