mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-02-27 16:36:06 +00:00
Adds SPFx react slide swiper sample (#412)
This commit is contained in:
parent
c9a577476f
commit
8680fec4fd
25
samples/react-slide-swiper/.editorconfig
Normal file
25
samples/react-slide-swiper/.editorconfig
Normal file
@ -0,0 +1,25 @@
|
||||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
35
samples/react-slide-swiper/.gitignore
vendored
Normal file
35
samples/react-slide-swiper/.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
||||
|
||||
package-lock.json
|
||||
|
8
samples/react-slide-swiper/.yo-rc.json
Normal file
8
samples/react-slide-swiper/.yo-rc.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.4.0",
|
||||
"libraryName": "react-slide-swiper",
|
||||
"libraryId": "c7fdd51c-469e-432f-bdde-930294d3a133",
|
||||
"environment": "spo"
|
||||
}
|
||||
}
|
62
samples/react-slide-swiper/README.md
Normal file
62
samples/react-slide-swiper/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# SPFx React Slide Swiper #
|
||||
|
||||
## Summary
|
||||
|
||||
This SPFx React web part sample demonstrates mobile touch slide swiper. By default the swiper web part is responsive, has cross device and browser touch support and uses paging, but additional features like navigation, autoplay, loop of the slides and more can be enabled from the web part properties panel. The swiper web part can be used as carousel as well. The slides or cards template can easily be customized. The SPFx React swiper client side solution can easly be extended with more swiper, carousel like features because it is based on a popular feature rich JavaScript library called [Swiper](https://github.com/nolimits4web/swiper).
|
||||
|
||||

|
||||
|
||||
## Solution packaging and bundle optimization considerations
|
||||
|
||||
This sample uses the Swiper JavaScript library thought the npm packages, but just for the purpose of the sample so it can quicky be run without addional setup. It is highly recomended to add the Swiper library as SPFx solution [external reference](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/basics/add-an-external-library) to resize the solution bundle size and improve Site Page load times.
|
||||
|
||||
## Used SharePoint Framework Version
|
||||

|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Office 365 subscription with SharePoint Online.
|
||||
- SharePoint Framework [development environment](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment) already set up.
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-slide-swiper | Velin Georgiev ([@VelinGeorgiev](https://twitter.com/velingeorgiev))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
0.0.1|February 08, 2018 | Initial commit
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
- Clone this repository.
|
||||
- Open the command line, navigate to the web part folder and execute:
|
||||
- `npm i`
|
||||
- `gulp test` (optional)
|
||||
- `gulp serve`
|
||||
|
||||
## Features
|
||||
|
||||
This Web Part illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
- Using React for building SharePoint Framework client-side web parts.
|
||||
- How external css can be included in module.css.
|
||||
- How JavaScript library can be loaded by the help of requirejs in web part.
|
||||
- Mobile Touch capabilities
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-slide-swiper" />
|
||||
|
||||
|
BIN
samples/react-slide-swiper/assets/SPFx-React-Slider-Swiper.gif
Normal file
BIN
samples/react-slide-swiper/assets/SPFx-React-Slider-Swiper.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 MiB |
18
samples/react-slide-swiper/config/config.json
Normal file
18
samples/react-slide-swiper/config/config.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"react-slide-swiper-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/reactSlideSwiper/ReactSlideSwiperWebPart.js",
|
||||
"manifest": "./src/webparts/reactSlideSwiper/ReactSlideSwiperWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"ReactSlideSwiperWebPartStrings": "lib/webparts/reactSlideSwiper/loc/{locale}.js"
|
||||
}
|
||||
}
|
4
samples/react-slide-swiper/config/copy-assets.json
Normal file
4
samples/react-slide-swiper/config/copy-assets.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "react-slide-swiper",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
12
samples/react-slide-swiper/config/package-solution.json
Normal file
12
samples/react-slide-swiper/config/package-solution.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-slide-swiper-client-side-solution",
|
||||
"id": "c7fdd51c-469e-432f-bdde-930294d3a133",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-slide-swiper.sppkg"
|
||||
}
|
||||
}
|
10
samples/react-slide-swiper/config/serve.json
Normal file
10
samples/react-slide-swiper/config/serve.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/core-build/serve.schema.json",
|
||||
"port": 4321,
|
||||
"https": true,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
45
samples/react-slide-swiper/config/tslint.json
Normal file
45
samples/react-slide-swiper/config/tslint.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/core-build/tslint.schema.json",
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
}
|
4
samples/react-slide-swiper/config/write-manifests.json
Normal file
4
samples/react-slide-swiper/config/write-manifests.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
27
samples/react-slide-swiper/gulpfile.js
vendored
Normal file
27
samples/react-slide-swiper/gulpfile.js
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const path = require('path');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
const bundleAnalyzer = require('webpack-bundle-analyzer');
|
||||
|
||||
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||
|
||||
build.configureWebpack.mergeConfig({
|
||||
additionalConfiguration: (generatedConfiguration) => {
|
||||
const lastDirName = path.basename(__dirname);
|
||||
const dropPath = path.join(__dirname, 'temp', 'stats');
|
||||
generatedConfiguration.plugins.push(new bundleAnalyzer.BundleAnalyzerPlugin({
|
||||
openAnalyzer: false,
|
||||
analyzerMode: 'static',
|
||||
reportFilename: path.join(dropPath, `${lastDirName}.stats.html`),
|
||||
generateStatsFile: true,
|
||||
statsFilename: path.join(dropPath, `${lastDirName}.stats.json`),
|
||||
logLevel: 'error'
|
||||
}));
|
||||
|
||||
return generatedConfiguration;
|
||||
}
|
||||
});
|
||||
|
||||
build.initialize(gulp);
|
35
samples/react-slide-swiper/package.json
Normal file
35
samples/react-slide-swiper/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "react-slide-swiper",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "15.6.2",
|
||||
"react-dom": "15.6.2",
|
||||
"@types/react": "15.6.6",
|
||||
"@types/react-dom": "15.5.6",
|
||||
"@microsoft/sp-core-library": "~1.4.0",
|
||||
"@microsoft/sp-webpart-base": "~1.4.0",
|
||||
"@microsoft/sp-lodash-subset": "~1.4.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "~1.4.0",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"swiper": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~1.4.0",
|
||||
"@microsoft/sp-module-interfaces": "~1.4.0",
|
||||
"@microsoft/sp-webpart-workbench": "~1.4.0",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0",
|
||||
"ajv": "~5.2.2",
|
||||
"webpack-bundle-analyzer": "2.9.2"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "6d0ab1aa-db7a-4e80-a2b5-c83fd820f165",
|
||||
"alias": "ReactSlideSwiperWebPart",
|
||||
"componentType": "WebPart",
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
"requiresCustomScript": false,
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "ReactSlideSwiper" },
|
||||
"description": { "default": "Sample that shows swipe slides experience" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "ReactSlideSwiper"
|
||||
}
|
||||
}]
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField,
|
||||
PropertyPaneToggle,
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'ReactSlideSwiperWebPartStrings';
|
||||
import ReactSlideSwiper from './components/ReactSlideSwiper';
|
||||
import { IReactSlideSwiperProps } from './components/IReactSlideSwiperProps';
|
||||
import { IListServce } from './services/IListService';
|
||||
import { ListMock } from './services/ListMock';
|
||||
|
||||
export interface IReactSlideSwiperWebPartProps {
|
||||
enableNavigation: boolean;
|
||||
enablePagination: boolean;
|
||||
enableAutoplay: boolean;
|
||||
delayAutoplay: number;
|
||||
disableAutoplayOnInteraction: boolean;
|
||||
slidesPerView: string;
|
||||
slidesPerGroup: string;
|
||||
spaceBetweenSlides: string;
|
||||
enableGrabCursor: boolean;
|
||||
enableLoop: boolean;
|
||||
}
|
||||
|
||||
export default class ReactSlideSwiperWebPart extends BaseClientSideWebPart<IReactSlideSwiperWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IReactSlideSwiperProps> = React.createElement(
|
||||
ReactSlideSwiper,
|
||||
{
|
||||
listService: new ListMock(),
|
||||
swiperOptions: this.properties
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: 'Swiper Options'
|
||||
},
|
||||
displayGroupsAsAccordion: true,
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.GeneralGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneToggle('enableNavigation', {
|
||||
label: strings.EnableNavigation
|
||||
}),
|
||||
PropertyPaneToggle('enablePagination', {
|
||||
label: strings.EnablePagination,
|
||||
checked: true
|
||||
}),
|
||||
PropertyPaneTextField('slidesPerView', {
|
||||
label: strings.SlidesPerWiew,
|
||||
value: '3'
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
groupName: strings.AutoplayGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneToggle('enableAutoplay', {
|
||||
label: strings.EnableAutoplay
|
||||
}),
|
||||
PropertyPaneTextField('delayAutoplay', {
|
||||
label: strings.DelayAutoplay,
|
||||
description: strings.Miliseconds,
|
||||
value: '2500',
|
||||
disabled: !this.properties.enableAutoplay
|
||||
}),
|
||||
PropertyPaneToggle('disableAutoplayOnInteraction', {
|
||||
label: strings.DisableAutoplayOnInteraction,
|
||||
disabled: !this.properties.enableAutoplay
|
||||
})
|
||||
],
|
||||
isCollapsed: true
|
||||
},
|
||||
{
|
||||
groupName: strings.AdvancedGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('slidesPerGroup', {
|
||||
label: strings.SlidesPerGroup,
|
||||
value: '3'
|
||||
}),
|
||||
PropertyPaneTextField('spaceBetweenSlides', {
|
||||
label: strings.SpaceBetweenSlides,
|
||||
description: strings.InPixels,
|
||||
value: '5'
|
||||
}),
|
||||
PropertyPaneToggle('enableGrabCursor', {
|
||||
label: strings.EnableGrabCursor
|
||||
}),
|
||||
PropertyPaneToggle('enableLoop', {
|
||||
label: strings.EnableLoop
|
||||
})
|
||||
],
|
||||
isCollapsed: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
//@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.card {
|
||||
|
||||
.wrapper{
|
||||
border: 1px solid grey;
|
||||
max-width: 300px;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.url {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.image {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.description {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import * as React from 'react';
|
||||
import { ICardProps } from './ICardProps';
|
||||
import styles from './Card.module.scss';
|
||||
|
||||
export default class Card extends React.Component<ICardProps, {}> {
|
||||
|
||||
public render(): React.ReactElement<ICardProps> {
|
||||
return (
|
||||
<div className={styles.card}>
|
||||
<div className={styles.wrapper}>
|
||||
<img src={this.props.listItem.imageUrl} className={styles.image} />
|
||||
<a href="#" className={styles.url} >
|
||||
<h3 className={styles.title}>{this.props.listItem.title}</h3>
|
||||
</a>
|
||||
<p className={styles.description}>{this.props.listItem.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { ListItem } from "../../services/ListItem";
|
||||
|
||||
export interface ICardProps {
|
||||
key: number;
|
||||
listItem: ListItem;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
import { IListServce } from "../services/IListService";
|
||||
import { IReactSlideSwiperWebPartProps } from "../ReactSlideSwiperWebPart";
|
||||
|
||||
export interface IReactSlideSwiperProps {
|
||||
listService: IListServce;
|
||||
swiperOptions: IReactSlideSwiperWebPartProps;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { ListItem } from "../services/ListItem";
|
||||
|
||||
export interface IReactSlideSwiperState {
|
||||
listItems: Array<ListItem>;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
//@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
@import '~swiper/dist/css/swiper.min.css';
|
||||
|
||||
.reactSlideSwiper {
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.slide {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
background: #fff;
|
||||
/* Center slide text vertically */
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
import * as React from 'react';
|
||||
import styles from './ReactSlideSwiper.module.scss';
|
||||
import { IReactSlideSwiperProps } from './IReactSlideSwiperProps';
|
||||
import { escape } from '@microsoft/sp-lodash-subset';
|
||||
import { IReactSlideSwiperState } from './IReactSlideSwiperState';
|
||||
import { ListItem } from '../services/ListItem';
|
||||
import Card from './Card/Card';
|
||||
|
||||
const Swiper = require('swiper/dist/js/swiper.min');
|
||||
|
||||
export default class ReactSlideSwiper extends React.Component<IReactSlideSwiperProps, IReactSlideSwiperState> {
|
||||
|
||||
constructor(props: IReactSlideSwiperProps) {
|
||||
super(props);
|
||||
this.state = { listItems: [] };
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
|
||||
this.props.listService.getAll().then((result: Array<ListItem>) => {
|
||||
|
||||
// List items returned from the ListMock so we can
|
||||
// change the state and display them.
|
||||
this.setState({ listItems: result });
|
||||
|
||||
// Since we have list items rendered
|
||||
// we can call the swiper and let it
|
||||
// handle the swipe effect for the items.
|
||||
this.setSwiper();
|
||||
});
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<IReactSlideSwiperProps> {
|
||||
return (
|
||||
<div className={styles.reactSlideSwiper}>
|
||||
|
||||
<div className={`swiper-container ${styles.container}`}>
|
||||
<div className='swiper-wrapper'>
|
||||
{this.state.listItems.length &&
|
||||
this.state.listItems.map((listItem, i) => {
|
||||
return <div className={`swiper-slide ${styles.slide}`} key={i}>
|
||||
|
||||
<Card listItem={listItem} key={i} />
|
||||
|
||||
</div>;
|
||||
})}
|
||||
</div>
|
||||
|
||||
{this.props.swiperOptions.enableNavigation &&
|
||||
<div className="swiper-button-next"></div>
|
||||
}
|
||||
{this.props.swiperOptions.enableNavigation &&
|
||||
<div className="swiper-button-prev"></div>
|
||||
}
|
||||
|
||||
{this.props.swiperOptions.enablePagination !== false &&
|
||||
<div className="swiper-pagination"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private setSwiper(): void {
|
||||
const opts = this.props.swiperOptions;
|
||||
|
||||
const options: any = {
|
||||
slidesPerView: parseInt(opts.slidesPerView) || 3,
|
||||
slidesPerGroup: parseInt(opts.slidesPerGroup) || 3,
|
||||
spaceBetween: parseInt(opts.spaceBetweenSlides) || 10,
|
||||
loop: opts.enableLoop || false,
|
||||
grabCursor: opts.enableGrabCursor || false,
|
||||
breakpoints: {
|
||||
1024: {
|
||||
slidesPerView: 3,
|
||||
spaceBetween: 10,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 2,
|
||||
spaceBetween: 10,
|
||||
},
|
||||
640: {
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 5,
|
||||
},
|
||||
320: {
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 5,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (opts.enablePagination !== false) {
|
||||
|
||||
options.pagination = {
|
||||
el: '.swiper-pagination',
|
||||
clickable: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (opts.enableNavigation) {
|
||||
|
||||
options.navigation = {
|
||||
nextEl: '.swiper-button-next',
|
||||
prevEl: '.swiper-button-prev',
|
||||
};
|
||||
}
|
||||
|
||||
if (opts.enableAutoplay) {
|
||||
|
||||
options.autoplay = {
|
||||
delay: opts.delayAutoplay,
|
||||
disableOnInteraction: opts.disableAutoplayOnInteraction,
|
||||
};
|
||||
}
|
||||
|
||||
return new Swiper('.swiper-container', options);
|
||||
}
|
||||
}
|
20
samples/react-slide-swiper/src/webparts/reactSlideSwiper/loc/en-us.js
vendored
Normal file
20
samples/react-slide-swiper/src/webparts/reactSlideSwiper/loc/en-us.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
define([], function() {
|
||||
return {
|
||||
"SwiperOptions": "Swiper Options",
|
||||
"GeneralGroupName": "General",
|
||||
"EnableNavigation":"Enable navigation",
|
||||
"EnablePagination":"Enable pagination",
|
||||
"SlidesPerWiew": "Slides per view",
|
||||
"AutoplayGroupName": "Autoplay",
|
||||
"EnableAutoplay": "Enable autoplay",
|
||||
"DelayAutoplay": "Delay autoplay",
|
||||
"Miliseconds": "Miliseconds",
|
||||
"DisableAutoplayOnInteraction": "Disable autoplay on interaction",
|
||||
"AdvancedGroupName": "Advanced",
|
||||
"SlidesPerGroup": "Slides per group",
|
||||
"SpaceBetweenSlides": "Space between slides",
|
||||
"InPixels": "In pixels",
|
||||
"EnableGrabCursor": "Enable grab cursor",
|
||||
"EnableLoop": "Enable loop",
|
||||
}
|
||||
});
|
23
samples/react-slide-swiper/src/webparts/reactSlideSwiper/loc/mystrings.d.ts
vendored
Normal file
23
samples/react-slide-swiper/src/webparts/reactSlideSwiper/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
declare interface IReactSlideSwiperWebPartStrings {
|
||||
SwiperOptions: string;
|
||||
GeneralGroupName: string;
|
||||
EnableNavigation: string;
|
||||
EnablePagination: string;
|
||||
SlidesPerWiew: string;
|
||||
AutoplayGroupName: string;
|
||||
EnableAutoplay: string;
|
||||
DelayAutoplay: string;
|
||||
Miliseconds: string;
|
||||
DisableAutoplayOnInteraction: string;
|
||||
AdvancedGroupName: string;
|
||||
SlidesPerGroup: string;
|
||||
SpaceBetweenSlides: string;
|
||||
InPixels: string;
|
||||
EnableGrabCursor: string;
|
||||
EnableLoop: string;
|
||||
}
|
||||
|
||||
declare module 'ReactSlideSwiperWebPartStrings' {
|
||||
const strings: IReactSlideSwiperWebPartStrings;
|
||||
export = strings;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { ListItem } from "./ListItem";
|
||||
|
||||
export interface IListServce {
|
||||
getAll(): Promise<Array<ListItem>>;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export class ListItem {
|
||||
|
||||
public title: string;
|
||||
public description:string;
|
||||
public imageUrl: string;
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
import { ListItem } from "./ListItem";
|
||||
import { IListServce } from "./IListService";
|
||||
|
||||
export class ListMock implements IListServce {
|
||||
|
||||
public getAll(): Promise<Array<ListItem>> {
|
||||
return new Promise<Array<ListItem>>((resolve:any) => {
|
||||
|
||||
const fakeData: Array<ListItem> = [
|
||||
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/OFFICE365.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/POWERSHELL.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/PYTHON.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/SP.png'
|
||||
},
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/JAVASCRIPT.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/POWERSHELL.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/PYTHON.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/SP.png'
|
||||
},
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/OFFICE365.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/JAVASCRIPT.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/PYTHON.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/SP.png'
|
||||
},
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/OFFICE365.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/POWERSHELL.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/JAVASCRIPT.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/SP.png'
|
||||
},
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/OFFICE365.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/POWERSHELL.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/PYTHON.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/JAVASCRIPT.png'
|
||||
},
|
||||
{
|
||||
title: 'A convergent value empowers the standard-setters',
|
||||
description: 'The General Head of IT Strategy benchmarks business-for-business agilities',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/OFFICE365.png'
|
||||
},
|
||||
{
|
||||
title: 'The Digital Marketers empower a digitized correlation',
|
||||
description: 'Whereas synchronized brand values promote strategy formulations',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/POWERSHELL.png'
|
||||
},
|
||||
{
|
||||
title: 'The market thinker strategically standardizes a competitive success',
|
||||
description: 'The thinkers/planners benchmark a disciplined growth momentum',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/PYTHON.png'
|
||||
},
|
||||
{
|
||||
title: 'We are going to secure our cross-pollinations',
|
||||
description: 'We are working hard to reintermediate a competitive advantage, while the gatekeeper straightforwardly identifies barriers to success',
|
||||
imageUrl: 'https://blog.velingeorgiev.com/static/images/SP.png'
|
||||
}
|
||||
];
|
||||
|
||||
resolve(fakeData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
25
samples/react-slide-swiper/tsconfig.json
Normal file
25
samples/react-slide-swiper/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
],
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"webpack-env"
|
||||
],
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom",
|
||||
"es2015.collection"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user