代码上传
|
@ -0,0 +1 @@
|
|||
*.svelte linguist-language=HTML
|
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
dist/*
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 2,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
printWidth: 120,
|
||||
semi: false,
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
language: node_js
|
||||
node_js: lts/*
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
# Tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
- /^greenkeeper\//
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- xvfb
|
||||
|
||||
install:
|
||||
- export DISPLAY=':99.0'
|
||||
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||
- npm ci || npm install
|
||||
|
||||
script: skip
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: release
|
||||
node_js: lts/*
|
||||
deploy:
|
||||
provider: script
|
||||
skip_cleanup: true
|
||||
script:
|
||||
- npx semantic-release
|
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Brian Hann; Modified Copyright 2020 Keifer Ju
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
|
||||
|
||||
# svelma-pro
|
||||
|
||||
Based on [svelma](https://github.com/c0bra/svelma) project extension and modification, thanks to the original author components such as c0bra and bulma
|
||||
Based on the original component library, some common components and bug fixes are extended, and the functions of some components are modified.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
[See docs + demos site here](http://www.myllcn.com/svelma-pro/)
|
||||
|
||||
# Quick Start
|
||||
|
||||
### 1. Create a svelte app(or sapper app) from the template
|
||||
|
||||
[https://github.com/sveltejs/template](sveltejs/template) is a template repo for svelte. [degit](https://www.npmjs.com/package/degit) will scaffold the repo for you:
|
||||
|
||||
$ npx degit sveltejs/template my-svelma-project
|
||||
$ cd my-svelma-project
|
||||
$ npm install
|
||||
|
||||
|
||||
### 2. Install svelma and dependencies
|
||||
|
||||
#### bulma and svelma-pro
|
||||
|
||||
$ npm install --save bulma svelma-pro
|
||||
|
||||
#### scss
|
||||
|
||||
$ npm install --save-dev svelte-preprocess autoprefixer node-sass sass
|
||||
|
||||
|
||||
### 3. config
|
||||
Add the scss plugin to your rollup(webpack) config:
|
||||
|
||||
```js
|
||||
// rollup.config.js
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
// ...
|
||||
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
svelte({
|
||||
// ...
|
||||
preprocess: preprocess,
|
||||
})
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
// ...
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
module.export = {
|
||||
// ...
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /.(svelte|html)$/,
|
||||
use: {
|
||||
loader: 'svelte-loader',
|
||||
options: {
|
||||
preprocess,
|
||||
// ...
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Import Bulma's CSS and Svelma components
|
||||
|
||||
```html
|
||||
|
||||
<!-- main.js or client.js(sapper) -->
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
</script>
|
||||
```
|
||||
|
||||
### 5. Include [Font Awesome](https://fontawesome.com/) icons
|
||||
|
||||
From CDN in your HTML page:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"></link>
|
||||
```
|
||||
|
||||
...or as an npm package imported into your root component:
|
||||
|
||||
$ npm install --save @fortawesome/fontawesome-free
|
||||
|
||||
```html
|
||||
<!-- main.js or client.js(sapper) -->
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
import '@fortawesome/fontawesome-free/css/all.css'
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,9 @@
|
|||
var ghpages = require('gh-pages');
|
||||
|
||||
ghpages.publish('docs/__sapper__/export/svelma-pro', {
|
||||
branch: 'gh-pages',
|
||||
repo: 'https://github.com/KeiferJu/svelma-pro.git',
|
||||
message: 'deploy',
|
||||
}, function (err) {
|
||||
console.log(err);
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
yarn-error.log
|
||||
/cypress/screenshots/
|
||||
/__sapper__/
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
|
||||
|
||||
# svelma-pro
|
||||
|
||||
Based on [svelma](https://github.com/c0bra/svelma) project extension and modification, thanks to the original author components such as c0bra and bulma
|
||||
Based on the original component library, some common components and bug fixes are extended, and the functions of some components are modified.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
[See docs + demos site here]()
|
||||
|
||||
# Quick Start
|
||||
|
||||
### 1. Create a svelte app(or sapper app) from the template
|
||||
|
||||
[https://github.com/sveltejs/template](sveltejs/template) is a template repo for svelte. [degit](https://www.npmjs.com/package/degit) will scaffold the repo for you:
|
||||
|
||||
$ npx degit sveltejs/template my-svelma-project
|
||||
$ cd my-svelma-project
|
||||
$ npm install
|
||||
|
||||
|
||||
### 2. Install svelma and dependencies
|
||||
|
||||
#### bulma and svelma-pro
|
||||
|
||||
$ npm install --save bulma svelma-pro
|
||||
|
||||
#### scss
|
||||
|
||||
$ npm install --save-dev svelte-preprocess autoprefixer node-sass sass
|
||||
|
||||
|
||||
### 3. config
|
||||
Add the scss plugin to your rollup(webpack) config:
|
||||
|
||||
```js
|
||||
// rollup.config.js
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
// ...
|
||||
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
svelte({
|
||||
// ...
|
||||
preprocess: preprocess,
|
||||
})
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
// ...
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
module.export = {
|
||||
// ...
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /.(svelte|html)$/,
|
||||
use: {
|
||||
loader: 'svelte-loader',
|
||||
options: {
|
||||
preprocess,
|
||||
// ...
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Import Bulma's CSS and Svelma components
|
||||
|
||||
```html
|
||||
|
||||
<!-- main.js or client.js(sapper) -->
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
</script>
|
||||
```
|
||||
|
||||
### 5. Include [Font Awesome](https://fontawesome.com/) icons
|
||||
|
||||
From CDN in your HTML page:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"></link>
|
||||
```
|
||||
|
||||
...or as an npm package imported into your root component:
|
||||
|
||||
$ npm install --save @fortawesome/fontawesome-free
|
||||
|
||||
```html
|
||||
<!-- main.js or client.js(sapper) -->
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
import '@fortawesome/fontawesome-free/css/all.css'
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,18 @@
|
|||
version: "{build}"
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf false
|
||||
|
||||
build: off
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# node.js
|
||||
- nodejs_version: stable
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- npm install cypress
|
||||
- npm install
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"video": false
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
describe('Sapper template app', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/')
|
||||
});
|
||||
|
||||
it('has the correct <h1>', () => {
|
||||
cy.contains('h1', 'Great success!')
|
||||
});
|
||||
|
||||
it('navigates to /about', () => {
|
||||
cy.get('nav a').contains('about').click();
|
||||
cy.url().should('include', '/about');
|
||||
});
|
||||
|
||||
it('navigates to /blog', () => {
|
||||
cy.get('nav a').contains('blog').click();
|
||||
cy.url().should('include', '/blog');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
|
@ -0,0 +1,20 @@
|
|||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "svelma-site",
|
||||
"description": "Docs and examples for Svelma",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "sapper dev",
|
||||
"build": "sapper build --legacy",
|
||||
"export": "sapper export --legacy",
|
||||
"start": "node __sapper__/build"
|
||||
},
|
||||
"dependencies": {
|
||||
"bulma": "^0.7.5",
|
||||
"clipboard": "^2.0.4",
|
||||
"compression": "^1.7.1",
|
||||
"highlight.js": "^9.15.6",
|
||||
"lodash": "^4.17.15",
|
||||
"polka": "^0.5.0",
|
||||
"sirv": "^0.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"chokidar": "^3.0.1",
|
||||
"codesandbox": "^2.1.6",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^1.0.0",
|
||||
"rollup-plugin-babel": "^4.0.2",
|
||||
"rollup-plugin-commonjs": "^9.1.6",
|
||||
"rollup-plugin-includepaths": "^0.2.3",
|
||||
"rollup-plugin-json": "^4.0.0",
|
||||
"rollup-plugin-node-resolve": "^4.0.0",
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-plugin-scss": "^1.0.1",
|
||||
"rollup-plugin-svelte": "^5.0.1",
|
||||
"rollup-plugin-terser": "^4.0.4",
|
||||
"sapper": "^0.27.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
import path from 'path'
|
||||
import { promisify } from 'util'
|
||||
import { exec as execRaw } from 'child_process'
|
||||
import alias from 'rollup-plugin-alias'
|
||||
import autoPreprocess from 'svelte-preprocess'
|
||||
import babel from 'rollup-plugin-babel'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import json from 'rollup-plugin-json'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import replace from 'rollup-plugin-replace'
|
||||
import svelte from 'rollup-plugin-svelte'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import config from 'sapper/config/rollup.js'
|
||||
import pkg from './package.json'
|
||||
|
||||
const exec = promisify(execRaw)
|
||||
const mode = process.env.NODE_ENV
|
||||
const dev = mode === 'development'
|
||||
const legacy = !!process.env.SAPPER_LEGACY_BUILD
|
||||
|
||||
export default {
|
||||
client: {
|
||||
watch: { chokidar: true },
|
||||
input: config.client.input(),
|
||||
output: config.client.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode),
|
||||
}),
|
||||
alias({
|
||||
resolve: ['.js', '.mjs', '.html', '.svelte'],
|
||||
'~': path.join(__dirname, '../src'),
|
||||
'svelma-pro': '../src/index.js',
|
||||
}),
|
||||
// scss(),
|
||||
svelte({
|
||||
dev,
|
||||
hydratable: true,
|
||||
emitCss: true,
|
||||
preprocess: autoPreprocess({
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')()],
|
||||
},
|
||||
})
|
||||
}),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
json(),
|
||||
|
||||
legacy &&
|
||||
babel({
|
||||
extensions: ['.js', '.mjs', '.html', '.svelte'],
|
||||
runtimeHelpers: true,
|
||||
exclude: ['node_modules/@babel/**'],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: '> 0.25%, not dead',
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
[
|
||||
'@babel/plugin-transform-runtime',
|
||||
{
|
||||
useESModules: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
|
||||
!dev &&
|
||||
terser({
|
||||
module: true,
|
||||
})
|
||||
],
|
||||
},
|
||||
|
||||
server: {
|
||||
watch: { chokidar: true },
|
||||
input: config.server.input(),
|
||||
output: config.server.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': false,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode),
|
||||
}),
|
||||
alias({
|
||||
resolve: ['.js', '.mjs', '.html', '.svelte'],
|
||||
'~': path.join(__dirname, '../src'),
|
||||
'svelma-pro': '../src/index.js',
|
||||
}),
|
||||
// scss(),
|
||||
svelte({
|
||||
generate: 'ssr',
|
||||
dev,
|
||||
preprocess: autoPreprocess({
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')()],
|
||||
},
|
||||
})
|
||||
}),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
json(),
|
||||
],
|
||||
external: Object.keys(pkg.dependencies).concat(
|
||||
require('module').builtinModules || Object.keys(process.binding('natives'))
|
||||
),
|
||||
},
|
||||
|
||||
serviceworker: {
|
||||
watch: { chokidar: true },
|
||||
input: config.serviceworker.input(),
|
||||
output: config.serviceworker.output(),
|
||||
plugins: [
|
||||
resolve(),
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode),
|
||||
}),
|
||||
commonjs(),
|
||||
!dev && terser(),
|
||||
],
|
||||
},
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import * as sapper from '@sapper/app';
|
||||
import hljs from 'highlight.js/lib/highlight';
|
||||
import bash from 'highlight.js/lib/languages/bash';
|
||||
import xml from 'highlight.js/lib/languages/xml';
|
||||
import javascript from 'highlight.js/lib/languages/javascript';
|
||||
|
||||
hljs.registerLanguage('bash', bash);
|
||||
hljs.registerLanguage('xml', xml);
|
||||
hljs.registerLanguage('javascript', javascript);
|
||||
|
||||
sapper.start({
|
||||
target: document.querySelector('#sapper')
|
||||
});
|
|
@ -0,0 +1,110 @@
|
|||
<script>
|
||||
import Clipboard from 'clipboard'
|
||||
import hljs from 'highlight.js/lib/highlight'
|
||||
import { beforeUpdate, tick, onMount, onDestroy } from 'svelte'
|
||||
|
||||
export let lang = 'js'
|
||||
export let code = ''
|
||||
export let showCopy = true
|
||||
let _code = ''
|
||||
let button
|
||||
let codeElm
|
||||
let clip
|
||||
let show = false
|
||||
let compiled
|
||||
let observer
|
||||
|
||||
$: {
|
||||
_code = code || (codeElm && codeElm.innerHTML) || _code
|
||||
updateCode(code)
|
||||
}
|
||||
|
||||
function updateCode(newCode) {
|
||||
if (!newCode) return
|
||||
code = newCode.trim()
|
||||
compiled = hljs.highlightAuto(code, [lang]).value
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (codeElm.innerHTML) code = codeElm.innerHTML
|
||||
|
||||
if (button) {
|
||||
clip = new Clipboard(button, {
|
||||
text: trigger => code,
|
||||
})
|
||||
}
|
||||
|
||||
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
|
||||
observer = new MutationObserver(() => {
|
||||
if (codeElm && codeElm.innerHTML) updateCode(codeElm.innerHTML)
|
||||
})
|
||||
observer.observe(codeElm, {
|
||||
subtree: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
})
|
||||
|
||||
await tick()
|
||||
|
||||
show = true
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
if (clip) clip.destroy()
|
||||
if (observer) observer.disconnect()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.codeview {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.codeview:not(:last-child) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
figure.highlight {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* code {
|
||||
padding: 1.25rem 1.5rem;
|
||||
} */
|
||||
|
||||
pre.hidden {
|
||||
visibility: hidden;
|
||||
height: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
pre.show {
|
||||
/* display: block; */
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="codeview">
|
||||
<figure class="highlight is-expanded">
|
||||
{#if showCopy}
|
||||
<div class="button-container">
|
||||
<button class="button is-text is-small copy-code" bind:this={button}>Copy</button>
|
||||
</div>
|
||||
{/if}
|
||||
<pre class="hidden">
|
||||
<code class={lang} bind:this={codeElm}>
|
||||
<slot />
|
||||
</code>
|
||||
</pre>
|
||||
<pre class:hidden={!show} class:show>
|
||||
<code>
|
||||
{@html compiled}
|
||||
</code>
|
||||
</pre>
|
||||
</figure>
|
||||
</div>
|
|
@ -0,0 +1,113 @@
|
|||
<script>
|
||||
import { getParameters } from 'codesandbox/lib/api/define'
|
||||
|
||||
export let title = 'Svelma Example'
|
||||
export let code
|
||||
|
||||
let form
|
||||
|
||||
function extractTag(code, tag) {
|
||||
let start = code.indexOf(`<${tag}>`)
|
||||
if (start === -1) return
|
||||
|
||||
start = start + tag.length + 2
|
||||
const end = code.lastIndexOf(`<\/${tag}>`)
|
||||
|
||||
const extracted = code.substring(start, end)
|
||||
|
||||
return extracted
|
||||
}
|
||||
|
||||
function extractHTML(code) {
|
||||
code = code.replace(/<script>[\s\S]*<\/script>/im, '')
|
||||
code = code.replace(/<script>[\s\S]*<\/style>/im, '')
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
$: value = getParameters({
|
||||
files: {
|
||||
'sandbox.config.json': {
|
||||
content: {
|
||||
template: 'svelte',
|
||||
},
|
||||
},
|
||||
'index.html': {
|
||||
content: `<html>
|
||||
<body>
|
||||
<link
|
||||
id="external-css"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="https://unpkg.com/bulma/css/bulma.min.css"
|
||||
media="all"
|
||||
/>
|
||||
<link
|
||||
id="external-css2"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"
|
||||
media="all"
|
||||
/>
|
||||
</body>
|
||||
</html>`,
|
||||
},
|
||||
'index.js': {
|
||||
content: `import App from "./App.svelte";
|
||||
|
||||
const app = new App({
|
||||
target: document.body
|
||||
});
|
||||
|
||||
export default app;`,
|
||||
},
|
||||
'App.svelte': { content: code },
|
||||
'package.json': {
|
||||
content: {
|
||||
name: 'svelma-example',
|
||||
version: '1.0.0',
|
||||
devDependencies: {
|
||||
'npm-run-all': '^4.1.5',
|
||||
rollup: '^1.10.1',
|
||||
'rollup-plugin-commonjs': '^9.3.4',
|
||||
'rollup-plugin-node-resolve': '^4.2.3',
|
||||
'rollup-plugin-svelte': '^5.0.3',
|
||||
'rollup-plugin-terser': '^4.0.4',
|
||||
'sirv-cli': '^0.3.1',
|
||||
},
|
||||
dependencies: {
|
||||
svelte: 'latest',
|
||||
svelma: 'latest',
|
||||
'@fortawesome/fontawesome-free': 'latest',
|
||||
bulma: 'latest',
|
||||
},
|
||||
scripts: {
|
||||
build: 'rollup -c',
|
||||
autobuild: 'rollup -c -w',
|
||||
dev: 'run-p start:dev autobuild',
|
||||
start: 'sirv public',
|
||||
'start:dev': 'sirv public --dev',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
function open() {
|
||||
form.submit()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.slot-wrap {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<form action="https://codesandbox.io/api/v1/sandboxes/define" method="POST" target="_blank" bind:this={form}>
|
||||
<input type="hidden" name="parameters" {value} />
|
||||
<div class="slot-wrap" on:click={open}>
|
||||
<slot />
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,18 @@
|
|||
<script>
|
||||
export let title
|
||||
export let subtitle
|
||||
|
||||
$: newTitle = `${title} | Svelma`
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content={newTitle} />
|
||||
<meta property="og:description" content={subtitle} />
|
||||
</svelte:head>
|
||||
|
||||
<!-- Doc for a Svelma Component -->
|
||||
<header class="header">
|
||||
<h1 class="title">{title}</h1>
|
||||
<h2 class="subtitle">{subtitle}</h2>
|
||||
</header>
|
|
@ -0,0 +1,194 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { Button } from 'svelma-pro'
|
||||
import Code from './Code.svelte'
|
||||
import CodepenButton from './CodepenButton.svelte'
|
||||
|
||||
export let lang = 'xml'
|
||||
export let code
|
||||
export let horizontal = false
|
||||
|
||||
let showCode = false
|
||||
|
||||
function show() {
|
||||
showCode = true
|
||||
}
|
||||
|
||||
function hide(e) {
|
||||
e.stopPropagation()
|
||||
showCode = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.snippet {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
border-radius: 6px;
|
||||
border-top-left-radius: 0;
|
||||
border: 2px solid #f5f5f5;
|
||||
flex-direction: row;
|
||||
margin-top: 3em;
|
||||
|
||||
&.horizontal {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1087px) {
|
||||
.snippet {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
min-width: 50%;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
min-width: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
border-radius: 0 6px 6px 0;
|
||||
border-left: 1px solid #f5f5f5;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
/* cursor: pointer;
|
||||
pointer-events: auto; */
|
||||
|
||||
/*
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0.8;
|
||||
background-color: white;
|
||||
content: '<> Show Code';
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
font-size: 0.75rem;
|
||||
}*/
|
||||
|
||||
/*
|
||||
&:hover::before {
|
||||
background-color: #ffdd57;
|
||||
}
|
||||
|
||||
& :global(pre),
|
||||
& :global(pre code) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.show-code {
|
||||
cursor: auto;
|
||||
|
||||
&::before {
|
||||
content: inherit;
|
||||
}
|
||||
|
||||
& :global(figure) {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
||||
& :global(pre) {
|
||||
overflow: auto;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.snippet::before {
|
||||
background: #ffdd57;
|
||||
border-radius: 2px 2px 0 0;
|
||||
bottom: 100%;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
content: 'Example';
|
||||
display: inline-block;
|
||||
font-size: 7px;
|
||||
font-weight: 700;
|
||||
left: -1px;
|
||||
letter-spacing: 1px;
|
||||
margin-left: -1px;
|
||||
padding: 3px 5px;
|
||||
position: absolute;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.snippet::before {
|
||||
content: 'Snippet';
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.codepen-button {
|
||||
position: absolute;
|
||||
display: inline-flex;
|
||||
background: #ffdd57;
|
||||
border-radius: 4px 4px 0 0;
|
||||
bottom: 100%;
|
||||
font-size: 7px;
|
||||
font-weight: 700;
|
||||
right: -1px;
|
||||
padding: 0 0 0 8px;
|
||||
vertical-align: top;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
/*.code {
|
||||
:global(.codeview) {
|
||||
height: 100%;
|
||||
|
||||
:global(figure) {
|
||||
height: 100%;
|
||||
|
||||
:global(pre:not(.hidden)) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
:global(.codeview) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
:global(.btn-show-code) {
|
||||
align-self: center;
|
||||
margin: 2em 0 0.5em;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="snippet" class:horizontal>
|
||||
<CodepenButton {code}>
|
||||
<div class="codepen-button">
|
||||
Codesandbox
|
||||
<i class="icon is-small fas fa-external-link-alt" />
|
||||
</div>
|
||||
</CodepenButton>
|
||||
<div class="preview">
|
||||
<slot name="preview" />
|
||||
</div>
|
||||
<div class="code">
|
||||
<!-- class:show-code={showCode} on:click={show} -->
|
||||
<Code {lang} {code} />
|
||||
|
||||
<!-- {#if showCode}
|
||||
<Button class="btn-show-code is-rounded is-outline has-text-grey-light" on:click|stopPropagation={hide}>
|
||||
Hide Code
|
||||
</Button>
|
||||
{/if} -->
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,93 @@
|
|||
<script>
|
||||
export let jsdoc
|
||||
export let showEvent = false
|
||||
export let showHeader = true
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media screen and (max-width: 1087px) {
|
||||
.table-wrapper {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if jsdoc}
|
||||
{#if showHeader}<hr class="is-medium" />{/if}
|
||||
|
||||
<section>
|
||||
{#if showHeader}<h2 class="title is-4">API</h2>{/if}
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Type</th>
|
||||
<th>Values</th>
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each jsdoc as doc}
|
||||
{#if !doc.isEvent}
|
||||
<tr>
|
||||
<td>
|
||||
<code>{doc.name}</code>
|
||||
</td>
|
||||
<td>
|
||||
{@html doc.description}{#if doc.optional}, optional{/if}
|
||||
</td>
|
||||
<td>{(doc.type || []).join(', ')}</td>
|
||||
<td>
|
||||
{@html doc.values || '—'}
|
||||
</td>
|
||||
<td>
|
||||
{@html ('defaultvalue' in doc && `<code>${doc.defaultvalue}</code>`) || '—'}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
{#if showEvent}
|
||||
{#if showHeader}<hr class="is-medium" />{/if}
|
||||
|
||||
<section>
|
||||
{#if showHeader}<h2 class="title is-4">EVENT</h2>{/if}
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Parameters</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each jsdoc as doc}
|
||||
{#if doc.isEvent}
|
||||
<tr>
|
||||
<td>
|
||||
<code>{doc.name}</code>
|
||||
</td>
|
||||
<td>
|
||||
{@html doc.values || '—'}
|
||||
</td>
|
||||
<td>
|
||||
{@html doc.description}{#if doc.optional}, optional{/if}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
|
@ -0,0 +1,60 @@
|
|||
<script>
|
||||
export let segment
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
img.logo {
|
||||
padding: 0 10px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.brand {
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if false}
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a class={segment === undefined ? 'selected' : ''} href=".">home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class={segment === 'about' ? 'selected' : ''} href="about">about</a>
|
||||
</li>
|
||||
|
||||
<!-- for the blog link, we're using rel=prefetch so that Sapper prefetches
|
||||
the blog data when we hover over the link or tap it on a touchscreen -->
|
||||
<li>
|
||||
<a rel="prefetch" class={segment === 'blog' ? 'selected' : ''} href="blog">blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
<nav id="navbar" class="navbar has-shadow is-spaced">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a href="/" class="navbar-item brand">
|
||||
<!-- <img src="svelma-pro-logo.svg" class="logo" alt="Svelma: Bulma components for Svelte" /> -->
|
||||
svelma-pro
|
||||
</a>
|
||||
<!-- <a class="navbar-item is-hidden-desktop" href={github} target="_blank">
|
||||
<span class="icon" style="color: #333;">
|
||||
<i class="fab fa-github-alt" />
|
||||
</span>
|
||||
</a> -->
|
||||
</div>
|
||||
<!-- <div class="navbar-menu">
|
||||
<div class="navbar-end">
|
||||
<a class="navbar-item is-hidden-touch" href={github} target="_blank">
|
||||
<span class="icon" style="color: #333;">
|
||||
<i class="fab fa-lg fa-github-alt" />
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</nav>
|
|
@ -0,0 +1,111 @@
|
|||
<script context="module">
|
||||
export async function preload({ params, query }) {
|
||||
// const res = await this.fetch('')
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import difference from 'lodash/difference'
|
||||
import { Svelma as Components } from 'svelma-pro'
|
||||
|
||||
const formComponents = ['Input', 'Field', 'Switch'].sort()
|
||||
const omittedComponents = ['Tab']
|
||||
let components = ['Form', ...Object.keys(Components)].sort()
|
||||
components = difference(components, [...formComponents, ...omittedComponents])
|
||||
|
||||
const bulmaElements = ['Media', 'Table', 'Hero', 'Tiles'].sort()
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
width: 16rem;
|
||||
padding: 3rem 1rem;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.sidebar > ul {
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 0;
|
||||
|
||||
ul {
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar li {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sidebar-label {
|
||||
margin-bottom: 0.5em;
|
||||
color: #7a7a7a;
|
||||
font-size: 0.9em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.sidebar-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 50%;
|
||||
background: #f5f5f5;
|
||||
min-height: calc(100vh - 4rem);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1087px) {
|
||||
.sidebar {
|
||||
order: 2;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sidebar-bg" />
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-label">Installation</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="install">Start</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="sidebar-label">Bulma Elements</p>
|
||||
<ul>
|
||||
<li><a href="bulma/intro">Intro</a></li>
|
||||
{#each bulmaElements as c}
|
||||
<li>
|
||||
<a href="bulma/{c.toLowerCase()}">{c}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<p class="sidebar-label">Svelma Components</p>
|
||||
<ul>
|
||||
{#each components as c}
|
||||
<li>
|
||||
{#if c === 'Form'}
|
||||
<p>{c}</p>
|
||||
<ul>
|
||||
{#each formComponents as fc}
|
||||
<li>
|
||||
<a href="components/{fc.toLowerCase()}">{fc}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{:else}
|
||||
<a href="components/{c.toLowerCase()}">{c}</a>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
<!-- <li>
|
||||
<a href="/components/collapse">Collapse</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/components/icon">Icon</a>
|
||||
</li> -->
|
||||
</ul>
|
||||
</aside>
|
|
@ -0,0 +1,40 @@
|
|||
<script>
|
||||
export let status;
|
||||
export let error;
|
||||
|
||||
const dev = process.env.NODE_ENV === 'development';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1, p {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.8em;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>{status}</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{status}</h1>
|
||||
|
||||
<p>{error.message}</p>
|
||||
|
||||
{#if dev && error.stack}
|
||||
<pre>{error.stack}</pre>
|
||||
{/if}
|
|
@ -0,0 +1,78 @@
|
|||
<!-- <script context="module">
|
||||
export async function preload({ path }) {
|
||||
const url = 'https://c0bra.github.io' + `/svelma-pro/${path}`.replace(/\/\//g, '/').replace(/([^\/]$)/, '$1/')
|
||||
|
||||
return { url };
|
||||
}
|
||||
</script> -->
|
||||
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
import 'highlight.js/styles/github.css'
|
||||
|
||||
import { afterUpdate } from 'svelte'
|
||||
import { stores } from '@sapper/app';
|
||||
import Nav from '../components/Nav.svelte'
|
||||
import Sidebar from '../components/Sidebar.svelte'
|
||||
|
||||
const { page } = stores()
|
||||
|
||||
export let segment
|
||||
let url
|
||||
|
||||
// page.subscribe(({ path }) => {
|
||||
// url = 'https://c0bra.github.io' + `/svelma-pro/${path}`.replace(/\/\//g, '/').replace(/([^\/]$)/, '$1/')
|
||||
// })
|
||||
|
||||
// afterUpdate(function() {
|
||||
// console.log('I updated!', this)
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.docs {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.docs-main {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding: 3rem;
|
||||
background-color: white;
|
||||
min-height: calc(100vh - 4rem);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1087px) {
|
||||
.docs {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.docs-main {
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>svelma-pro</title>
|
||||
<meta property="og:site_name" content="Svelma" />
|
||||
<meta property="og:image" content="https://c0bra.github.io/svelma-pro/svelma-pro-logo.png" />
|
||||
<meta property="og:image:width" content="200" />
|
||||
<meta property="og:image:height" content="200" />
|
||||
<meta property="og:url" content={url}>
|
||||
</svelte:head>
|
||||
|
||||
<Nav {segment} />
|
||||
|
||||
<main>
|
||||
<section class="docs">
|
||||
<Sidebar />
|
||||
|
||||
<div class="docs-main">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
|
@ -0,0 +1,7 @@
|
|||
<svelte:head>
|
||||
<title>关于</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>关于页面</h1>
|
||||
|
||||
<p>本文档基于MIT开源项目svelma-pro扩展修改,由Sm@rtMapX团队维护升级</p>
|
|
@ -0,0 +1,28 @@
|
|||
import posts from './_posts.js';
|
||||
|
||||
const lookup = new Map();
|
||||
posts.forEach(post => {
|
||||
lookup.set(post.slug, JSON.stringify(post));
|
||||
});
|
||||
|
||||
export function get(req, res, next) {
|
||||
// the `slug` parameter is available because
|
||||
// this file is called [slug].json.js
|
||||
const { slug } = req.params;
|
||||
|
||||
if (lookup.has(slug)) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
res.end(lookup.get(slug));
|
||||
} else {
|
||||
res.writeHead(404, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
res.end(JSON.stringify({
|
||||
message: `Not found`
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<script context="module">
|
||||
export async function preload({ params, query }) {
|
||||
// the `slug` parameter is available because
|
||||
// this file is called [slug].html
|
||||
const res = await this.fetch(`blog/${params.slug}.json`);
|
||||
const data = await res.json();
|
||||
|
||||
if (res.status === 200) {
|
||||
return { post: data };
|
||||
} else {
|
||||
this.error(res.status, data.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let post;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*
|
||||
By default, CSS is locally scoped to the component,
|
||||
and any unused styles are dead-code-eliminated.
|
||||
In this page, Svelte can't know which elements are
|
||||
going to appear inside the {{{post.html}}} block,
|
||||
so we have to use the :global(...) modifier to target
|
||||
all elements inside .content
|
||||
*/
|
||||
.content :global(h2) {
|
||||
font-size: 1.4em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.content :global(pre) {
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: inset 1px 1px 5px rgba(0,0,0,0.05);
|
||||
padding: 0.5em;
|
||||
border-radius: 2px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.content :global(pre) :global(code) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content :global(ul) {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.content :global(li) {
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>{post.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{post.title}</h1>
|
||||
|
||||
<div class='content'>
|
||||
{@html post.html}
|
||||
</div>
|
|
@ -0,0 +1,92 @@
|
|||
// Ordinarily, you'd generate this data from markdown files in your
|
||||
// repo, or fetch them from a database of some kind. But in order to
|
||||
// avoid unnecessary dependencies in the starter template, and in the
|
||||
// service of obviousness, we're just going to leave it here.
|
||||
|
||||
// This file is called `_posts.js` rather than `posts.js`, because
|
||||
// we don't want to create an `/blog/posts` route — the leading
|
||||
// underscore tells Sapper not to do that.
|
||||
|
||||
const posts = [
|
||||
{
|
||||
title: 'What is Sapper?',
|
||||
slug: 'what-is-sapper',
|
||||
html: `
|
||||
<p>First, you have to know what <a href='https://svelte.dev'>Svelte</a> is. Svelte is a UI framework with a bold new idea: rather than providing a library that you write code with (like React or Vue, for example), it's a compiler that turns your components into highly optimized vanilla JavaScript. If you haven't already read the <a href='https://svelte.dev/blog/frameworks-without-the-framework'>introductory blog post</a>, you should!</p>
|
||||
|
||||
<p>Sapper is a Next.js-style framework (<a href='blog/how-is-sapper-different-from-next'>more on that here</a>) built around Svelte. It makes it embarrassingly easy to create extremely high performance web apps. Out of the box, you get:</p>
|
||||
|
||||
<ul>
|
||||
<li>Code-splitting, dynamic imports and hot module replacement, powered by webpack</li>
|
||||
<li>Server-side rendering (SSR) with client-side hydration</li>
|
||||
<li>Service worker for offline support, and all the PWA bells and whistles</li>
|
||||
<li>The nicest development experience you've ever had, or your money back</li>
|
||||
</ul>
|
||||
|
||||
<p>It's implemented as Express middleware. Everything is set up and waiting for you to get started, but you keep complete control over the server, service worker, webpack config and everything else, so it's as flexible as you need it to be.</p>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: 'How to use Sapper',
|
||||
slug: 'how-to-use-sapper',
|
||||
html: `
|
||||
<h2>Step one</h2>
|
||||
<p>Create a new project, using <a href='https://github.com/Rich-Harris/degit'>degit</a>:</p>
|
||||
|
||||
<pre><code>npx degit sveltejs/sapper-template#rollup my-app
|
||||
cd my-app
|
||||
npm install # or yarn!
|
||||
npm run dev
|
||||
</code></pre>
|
||||
|
||||
<h2>Step two</h2>
|
||||
<p>Go to <a href='http://localhost:3000'>localhost:3000</a>. Open <code>my-app</code> in your editor. Edit the files in the <code>src/routes</code> directory or add new ones.</p>
|
||||
|
||||
<h2>Step three</h2>
|
||||
<p>...</p>
|
||||
|
||||
<h2>Step four</h2>
|
||||
<p>Resist overdone joke formats.</p>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Why the name?',
|
||||
slug: 'why-the-name',
|
||||
html: `
|
||||
<p>In war, the soldiers who build bridges, repair roads, clear minefields and conduct demolitions — all under combat conditions — are known as <em>sappers</em>.</p>
|
||||
|
||||
<p>For web developers, the stakes are generally lower than those for combat engineers. But we face our own hostile environment: underpowered devices, poor network connections, and the complexity inherent in front-end engineering. Sapper, which is short for <strong>S</strong>velte <strong>app</strong> mak<strong>er</strong>, is your courageous and dutiful ally.</p>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: 'How is Sapper different from Next.js?',
|
||||
slug: 'how-is-sapper-different-from-next',
|
||||
html: `
|
||||
<p><a href='https://github.com/zeit/next.js'>Next.js</a> is a React framework from <a href='https://zeit.co'>Zeit</a>, and is the inspiration for Sapper. There are a few notable differences, however:</p>
|
||||
|
||||
<ul>
|
||||
<li>It's powered by <a href='https://svelte.dev'>Svelte</a> instead of React, so it's faster and your apps are smaller</li>
|
||||
<li>Instead of route masking, we encode route parameters in filenames. For example, the page you're looking at right now is <code>src/routes/blog/[slug].html</code></li>
|
||||
<li>As well as pages (Svelte components, which render on server or client), you can create <em>server routes</em> in your <code>routes</code> directory. These are just <code>.js</code> files that export functions corresponding to HTTP methods, and receive Express <code>request</code> and <code>response</code> objects as arguments. This makes it very easy to, for example, add a JSON API such as the one <a href='blog/how-is-sapper-different-from-next.json'>powering this very page</a></li>
|
||||
<li>Links are just <code><a></code> elements, rather than framework-specific <code><Link></code> components. That means, for example, that <a href='blog/how-can-i-get-involved'>this link right here</a>, despite being inside a blob of HTML, works with the router as you'd expect.</li>
|
||||
</ul>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: 'How can I get involved?',
|
||||
slug: 'how-can-i-get-involved',
|
||||
html: `
|
||||
<p>We're so glad you asked! Come on over to the <a href='https://github.com/sveltejs/svelte'>Svelte</a> and <a href='https://github.com/sveltejs/sapper'>Sapper</a> repos, and join us in the <a href='https://svelte.dev/chat'>Discord chatroom</a>. Everyone is welcome, especially you!</p>
|
||||
`
|
||||
}
|
||||
];
|
||||
|
||||
posts.forEach(post => {
|
||||
post.html = post.html.replace(/^\t{3}/gm, '');
|
||||
});
|
||||
|
||||
export default posts;
|
|
@ -0,0 +1,16 @@
|
|||
import posts from './_posts.js';
|
||||
|
||||
const contents = JSON.stringify(posts.map(post => {
|
||||
return {
|
||||
title: post.title,
|
||||
slug: post.slug
|
||||
};
|
||||
}));
|
||||
|
||||
export function get(req, res) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
res.end(contents);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<script context="module">
|
||||
export function preload({ params, query }) {
|
||||
return this.fetch(`blog.json`).then(r => r.json()).then(posts => {
|
||||
return { posts };
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let posts;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
margin: 0 0 1em 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>Blog</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Recent posts</h1>
|
||||
|
||||
<ul>
|
||||
{#each posts as post}
|
||||
<!-- we're using the non-standard `rel=prefetch` attribute to
|
||||
tell Sapper to load the data for the page as soon as
|
||||
the user hovers over the link or taps it, instead of
|
||||
waiting for the 'click' event -->
|
||||
<li><a rel='prefetch' href='blog/{post.slug}'>{post.title}</a></li>
|
||||
{/each}
|
||||
</ul>
|
|
@ -0,0 +1,77 @@
|
|||
<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { slide } from 'svelte/transition'
|
||||
import Codepreview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
const types = ['is-primary', 'is-success', 'is-danger', 'is-warning', 'is-info', 'is-link']
|
||||
let type = 'is-primary'
|
||||
|
||||
async function update() {
|
||||
type = ''
|
||||
|
||||
setTimeout(() => {
|
||||
type = types[Math.floor(Math.random() * types.length)];
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<DocHeader title="Hero" subtitle="Hero headers" />
|
||||
|
||||
<Example horizontal={true} code={`<script>
|
||||
import { slide } from 'svelte/transition'
|
||||
|
||||
const types = ['is-primary', 'is-success', 'is-danger', 'is-warning', 'is-info', 'is-link']
|
||||
let type = 'is-primary'
|
||||
|
||||
async function update() {
|
||||
type = ''
|
||||
|
||||
setTimeout(() => {
|
||||
type = types[Math.floor(Math.random() * types.length)];
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<button class="button is-primary" on:click={update}>Update Hero</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{#if type}
|
||||
<section class="hero {type}" transition:slide>
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
Title
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
Subtitle
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/if}`}>
|
||||
<div slot="preview">
|
||||
<button class="button is-primary" on:click={update}>Update Hero</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{#if type}
|
||||
<section class="hero {type}" transition:slide>
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
Title
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
Subtitle
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,9 @@
|
|||
<script>
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
</script>
|
||||
|
||||
<DocHeader title="Bulma Elements" subtitle="在Svelte中使用常规Bulma元素" />
|
||||
|
||||
<p class="content">
|
||||
许多Bulma组件很容易与常规的Svelte代码一起使用,而不需要额外的Svelma组件层。本节的文档将讨论如何在Svelte中使用这些元素。
|
||||
</p>
|
|
@ -0,0 +1,141 @@
|
|||
<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { fade, slide } from 'svelte/transition'
|
||||
import Codepreview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
let timer
|
||||
let user
|
||||
|
||||
const titleize = s => s.replace(/^([a-z])/, (_, r) => r.toUpperCase())
|
||||
|
||||
async function updateUser() {
|
||||
user = null
|
||||
user = (await (await fetch('https://randomuser.me/api/')).json()).results[0]
|
||||
}
|
||||
|
||||
onMount(() => updateUser())
|
||||
</script>
|
||||
|
||||
<DocHeader title="Media" subtitle="Social media UI element" />
|
||||
|
||||
<Example horizontal={true} code={`<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { fade } from 'svelte/transition'
|
||||
|
||||
let user
|
||||
|
||||
const titleize = s => s.replace(/^([a-z])/, (_, r) => r.toUpperCase())
|
||||
|
||||
async function updateUser() {
|
||||
user = null
|
||||
user = (await (await fetch('https://randomuser.me/api/')).json()).results[0]
|
||||
}
|
||||
</script>
|
||||
|
||||
<button class="button is-primary" on:click={updateUser}>Fetch New User</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div class="box">
|
||||
<article class="media">
|
||||
<div class="media-left">
|
||||
<figure class="image is-64x64">
|
||||
{#if user}
|
||||
<img transition:fade class="is-rounded" src={user.picture.medium} alt="Profile picture" />
|
||||
{/if}
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<div class="content">
|
||||
{#if user}
|
||||
<p transition:fade>
|
||||
<strong>{titleize(user.name.first)} {titleize(user.name.last)}</strong>
|
||||
<small>@{user.login.username}</small>
|
||||
<small />
|
||||
<br />
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean efficitur sit amet massa fringilla
|
||||
egestas. Nullam condimentum luctus turpis.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if user}
|
||||
<nav class="level is-mobile" transition:fade>
|
||||
<div class="level-left">
|
||||
<a href class="level-item" aria-label="reply">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-reply" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
<a href class="level-item" aria-label="retweet">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-retweet" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
<a href class="level-item" aria-label="like">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-heart" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<button class="button is-primary" on:click={updateUser}>Fetch New User</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div class="box">
|
||||
<article class="media">
|
||||
<div class="media-left">
|
||||
<figure class="image is-64x64">
|
||||
{#if user}
|
||||
<img transition:fade class="is-rounded" src={user.picture.medium} alt="Profile picture" />
|
||||
{/if}
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<div class="content">
|
||||
{#if user}
|
||||
<p transition:fade>
|
||||
<strong>{titleize(user.name.first)} {titleize(user.name.last)}</strong>
|
||||
<small>@{user.login.username}</small>
|
||||
<small />
|
||||
<br />
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean efficitur sit amet massa fringilla
|
||||
egestas. Nullam condimentum luctus turpis.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if user}
|
||||
<nav class="level is-mobile" transition:fade>
|
||||
<div class="level-left">
|
||||
<a href class="level-item" aria-label="reply">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-reply" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
<a href class="level-item" aria-label="retweet">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-retweet" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
<a href class="level-item" aria-label="like">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-heart" aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,128 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import Codepreview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
let loading = false
|
||||
let users = []
|
||||
|
||||
const titleize = s => s.replace(/^([a-z])/, (_, r) => r.toUpperCase())
|
||||
|
||||
async function update() {
|
||||
loading = true
|
||||
|
||||
users = []
|
||||
users = (await (await fetch('https://randomuser.me/api/?results=10')).json()).results
|
||||
|
||||
loading = false
|
||||
}
|
||||
|
||||
onMount(() => update())
|
||||
</script>
|
||||
|
||||
<DocHeader title="Tables" subtitle="Pretty HTML tables" />
|
||||
|
||||
<Example code={`<script>
|
||||
let loading = false
|
||||
let users = []
|
||||
|
||||
const titleize = s => s.replace(/^([a-z])/, (_, r) => r.toUpperCase())
|
||||
|
||||
async function update() {
|
||||
loading = true
|
||||
|
||||
users = []
|
||||
users = (await (await fetch('https://randomuser.me/api/?results=10')).json()).results
|
||||
|
||||
loading = false
|
||||
}
|
||||
|
||||
onMount(() => update())
|
||||
</script>
|
||||
|
||||
<button class="button is-primary" on:click={update}>Update</button>
|
||||
<button class="button is-primary" on:click={() => users = []}>No Data</button>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>City</th>
|
||||
<th>State</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each users as user}
|
||||
<tr>
|
||||
<td><figure class="image"><img class="is-rounded" src="{user.picture.thumbnail}" alt=""></figure></td>
|
||||
<td>{titleize(user.name.first)}</td>
|
||||
<td>{titleize(user.name.last)}</td>
|
||||
<td>{titleize(user.location.city)}</td>
|
||||
<td>{titleize(user.location.state)}</td>
|
||||
</tr>
|
||||
{:else}
|
||||
{#if !loading}
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<section class="section">
|
||||
<div class="content has-text-grey has-text-centered">
|
||||
<p><i class="far fa-3x fa-frown"></i></p>
|
||||
<p>No data</p>
|
||||
</div>
|
||||
</section>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>`}>
|
||||
<div slot="preview">
|
||||
<button class="button is-primary" on:click={update}>Update</button>
|
||||
<button class="button is-primary" on:click={() => users = []}>No Data</button>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>City</th>
|
||||
<th>State</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each users as user}
|
||||
<tr>
|
||||
<td><figure class="image"><img class="is-rounded" src="{user.picture.thumbnail}" alt=""></figure></td>
|
||||
<td>{titleize(user.name.first)}</td>
|
||||
<td>{titleize(user.name.last)}</td>
|
||||
<td>{titleize(user.location.city)}</td>
|
||||
<td>{titleize(user.location.state)}</td>
|
||||
</tr>
|
||||
{:else}
|
||||
{#if !loading}
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<section class="section">
|
||||
<div class="content has-text-grey has-text-centered">
|
||||
<p><i class="far fa-3x fa-frown"></i></p>
|
||||
<p>No data</p>
|
||||
</div>
|
||||
</section>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,179 @@
|
|||
<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
async function waitForDraggabilly() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const interval = setInterval(() => {
|
||||
if (Draggabilly) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
const draggables = document.querySelectorAll('.tile.is-child');
|
||||
|
||||
await waitForDraggabilly();
|
||||
|
||||
for (const elm of draggables) {
|
||||
let drag = new Draggabilly(elm, { // .tile:not(.is-ancestor)
|
||||
containment: '.tile.is-ancestor',
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tile:not(.is-ancestor) {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:global(.is-dragging) {
|
||||
transform: rotate(25deg);
|
||||
cursor: move;
|
||||
}
|
||||
</style>
|
||||
|
||||
<DocHeader title="Tiles" subtitle="2D grids with flexbox" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
waitForDraggabilly() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const interval = setInterval({
|
||||
if (Draggabilly) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
const draggables = document.querySelectorAll('.tile.is-child');
|
||||
|
||||
await waitForDraggabilly();
|
||||
|
||||
for (const elm of draggables) {
|
||||
let drag = new Draggabilly(elm, {
|
||||
containment: '.tile.is-ancestor',
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tile:not(.is-ancestor) {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:global(.is-dragging) {
|
||||
transform: rotate(25deg);
|
||||
cursor: move;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://unpkg.com/draggabilly@2/dist/draggabilly.pkgd.min.js"></script>
|
||||
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-vertical is-8">
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-vertical">
|
||||
<article class="tile is-child notification is-primary">
|
||||
<p class="title">Vertical...</p>
|
||||
<p class="subtitle">Top tile</p>
|
||||
</article>
|
||||
<article class="tile is-child notification is-warning">
|
||||
<p class="title">...tiles</p>
|
||||
<p class="subtitle">Bottom tile</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-info">
|
||||
<p class="title">Middle tile</p>
|
||||
<p class="subtitle">With an image</p>
|
||||
<figure class="image is-4by3">
|
||||
<img src="https://bulma.io/images/placeholders/640x480.png" />
|
||||
</figure>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-danger">
|
||||
<p class="title">Wide tile</p>
|
||||
<p class="subtitle">Aligned with the right tile</p>
|
||||
<div class="content">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-success">
|
||||
<div class="content">
|
||||
<p class="title">Tall tile</p>
|
||||
<p class="subtitle">With even more content</p>
|
||||
<div class="content">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<script src="https://unpkg.com/draggabilly@2/dist/draggabilly.pkgd.min.js"></script>
|
||||
|
||||
<h5 class="title">Click to drag tiles</h5>
|
||||
|
||||
<div class="tile is-ancestor">
|
||||
<div class="tile is-vertical is-8">
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-vertical">
|
||||
<article class="tile is-child notification is-primary">
|
||||
<p class="title">Vertical...</p>
|
||||
<p class="subtitle">Top tile</p>
|
||||
</article>
|
||||
<article class="tile is-child notification is-warning">
|
||||
<p class="title">...tiles</p>
|
||||
<p class="subtitle">Bottom tile</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-info">
|
||||
<p class="title">Middle tile</p>
|
||||
<p class="subtitle">With an image</p>
|
||||
<figure class="image is-4by3">
|
||||
<img src="https://bulma.io/images/placeholders/640x480.png" alt="profile" />
|
||||
</figure>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-danger">
|
||||
<p class="title">Wide tile</p>
|
||||
<p class="subtitle">Aligned with the right tile</p>
|
||||
<div class="content">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-success">
|
||||
<div class="content">
|
||||
<p class="title">Tall tile</p>
|
||||
<p class="subtitle">With even more content</p>
|
||||
<div class="content">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,14 @@
|
|||
import jsdocs from './jsdocs.json'
|
||||
|
||||
const titleize = s => s.replace(/^([a-z])/, (_, r) => r.toUpperCase())
|
||||
|
||||
export async function get(req, res, next) {
|
||||
const { slug } = req.params;
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(
|
||||
JSON.stringify(
|
||||
jsdocs[titleize(slug)]
|
||||
)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const res = await this.fetch(`components/button.json`)
|
||||
const jsdoc = await res.json()
|
||||
|
||||
return { jsdoc }
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { Button, Icon } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
let counter = 0
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<DocHeader title="Buttons" subtitle="可点击按钮" />
|
||||
|
||||
<Example
|
||||
code={`<Button type="is-primary" on:click={() => counter++}>
|
||||
Click!: {counter}
|
||||
</Button>`}>
|
||||
<div slot="preview">
|
||||
<Button type="is-primary" on:click={() => counter++}>Click!: {counter}</Button>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">状态,样式和类型</p>
|
||||
|
||||
<Example
|
||||
code={`<div class="buttons">
|
||||
<Button type="is-primary">Primary</Button>
|
||||
<Button type="is-success">Success</Button>
|
||||
<Button type="is-danger">Danger</Button>
|
||||
<Button type="is-warning">Warning</Button>
|
||||
<Button type="is-info">Info</Button>
|
||||
<Button type="is-link">Link</Button>
|
||||
<Button type="is-light">Light</Button>
|
||||
<Button type="is-dark">Dark</Button>
|
||||
<Button type="is-text">Text</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button disabled>Disabled</Button>
|
||||
<Button type="is-primary" loading>Loading</Button>
|
||||
<Button type="is-success" rounded>Rounded</Button>
|
||||
<Button type="is-info" outline>Outlined</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="notification is-primary">
|
||||
<Button type="is-primary" inverted>Inverted</Button>
|
||||
<Button type="is-primary" inverted outlined>Invert Outlined</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button type="is-primary" nativeType="submit">Submit</Button>
|
||||
<Button type="is-primary" nativeType="reset">Reset</Button>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<div class="buttons">
|
||||
<Button type="is-primary">Primary</Button>
|
||||
<Button type="is-success">Success</Button>
|
||||
<Button type="is-danger">Danger</Button>
|
||||
<Button type="is-warning">Warning</Button>
|
||||
<Button type="is-info">Info</Button>
|
||||
<Button type="is-link">Link</Button>
|
||||
<Button type="is-light">Light</Button>
|
||||
<Button type="is-dark">Dark</Button>
|
||||
<Button type="is-text">Text</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button disabled>Disabled</Button>
|
||||
<Button type="is-primary" loading>Loading</Button>
|
||||
<Button type="is-success" rounded>Rounded</Button>
|
||||
<Button type="is-info" outline>Outlined</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="notification is-primary">
|
||||
<Button type="is-primary" inverted>Inverted</Button>
|
||||
<Button type="is-primary" inverted outlined>Invert Outlined</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button type="is-primary" nativeType="submit">Submit</Button>
|
||||
<Button type="is-primary" nativeType="reset">Reset</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Sizes</p>
|
||||
|
||||
<Example
|
||||
code={`<div class="buttons">
|
||||
<Button size="is-small">Small</Button>
|
||||
<Button>Default</Button>
|
||||
<Button size="is-medium">Medium</Button>
|
||||
<Button size="is-large">Large</Button>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<div class="buttons">
|
||||
<Button size="is-small">Small</Button>
|
||||
<Button>Default</Button>
|
||||
<Button size="is-medium">Medium</Button>
|
||||
<Button size="is-large">Large</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Icons</p>
|
||||
|
||||
<Example
|
||||
code={`<div class="buttons">
|
||||
<Button>
|
||||
<Icon icon="bold" />
|
||||
</Button>
|
||||
<Button>
|
||||
<Icon icon="underline" />
|
||||
</Button>
|
||||
<Button>
|
||||
<Icon icon="italic" />
|
||||
</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button type="is-primary" iconPack="fab" iconLeft="twitter">Twitter</Button>
|
||||
<Button type="is-success" iconPack="fa" iconLeft="check">Save</Button>
|
||||
<Button type="is-danger" outline iconPack="fa" iconRight="times">Delete</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button size="is-small" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button iconLeft="github" iconPack="fab">GitHub</Button>
|
||||
<Button size="is-medium" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button size="is-large" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<div class="buttons">
|
||||
<Button>
|
||||
<Icon icon="bold" />
|
||||
</Button>
|
||||
<Button>
|
||||
<Icon icon="underline" />
|
||||
</Button>
|
||||
<Button>
|
||||
<Icon icon="italic" />
|
||||
</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button type="is-primary" iconPack="fab" iconLeft="twitter">Twitter</Button>
|
||||
<Button type="is-success" iconPack="fa" iconLeft="check">Save</Button>
|
||||
<Button type="is-danger" outline iconPack="fa" iconRight="times">Delete</Button>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Button size="is-small" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button iconLeft="github" iconPack="fab">GitHub</Button>
|
||||
<Button size="is-medium" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
<Button size="is-large" iconPack="fab" iconLeft="github">GitHub</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,49 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/collapse.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Collapse } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
</script>
|
||||
|
||||
<DocHeader title="Collapse" subtitle="可折叠元素" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Collapse } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Collapse>
|
||||
<button class="button is-primary" slot="trigger">
|
||||
Click Me!
|
||||
</button>
|
||||
<div class="notification">
|
||||
<div class="content">
|
||||
<h3>Subtitle</h3>
|
||||
<p>Lorem ipsum dolor...</p>
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>`}>
|
||||
<div slot="preview">
|
||||
<Collapse>
|
||||
<button class="button is-primary" slot="trigger">Click Me!</button>
|
||||
<div class="notification">
|
||||
<div class="content">
|
||||
<h3>Subtitle</h3>
|
||||
<p>Lorem ipsum dolor...</p>
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc}></JSDoc>
|
|
@ -0,0 +1,77 @@
|
|||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const res = await this.fetch(`components/datepicker.json`)
|
||||
const jsdoc = await res.json()
|
||||
|
||||
return { jsdoc }
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
import { Datepicker } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
let result = 1584517629215;
|
||||
|
||||
function click(e){
|
||||
alert(e.detail.time)
|
||||
}
|
||||
</script>
|
||||
|
||||
<DocHeader title="Datepicker" subtitle="日期选择器" />
|
||||
|
||||
<p class="title is-4">默认与暗黑主题</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import {Datepicker} from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Datepicker/>
|
||||
<Datepicker theme="dark"/>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Datepicker/>
|
||||
<Datepicker theme="dark"/>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">范围选择与自由选择</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import {Datepicker} from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Datepicker pickerRule="freeChoice"/>
|
||||
<Datepicker pickerRule="rangeChoice"/>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Datepicker pickerRule="freeChoice"/>
|
||||
<Datepicker pickerRule="rangeChoice"/>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">获取结果</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import Datepicker from 'svelma-pro'
|
||||
|
||||
function click(e){
|
||||
alert(e.detail.timeStamp)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Datepicker on:dateChecked={click}/>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Datepicker on:dateChecked={click}/>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} showEvent="true"/>
|
|
@ -0,0 +1,129 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/dialog.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Button, Dialog, Toast } from 'svelma-pro'
|
||||
import Codepreview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
function alert() {
|
||||
Dialog.alert('Alles ist gut')
|
||||
}
|
||||
|
||||
const thenHandler = result => Toast.create(`You ${result ? 'confirmed' : 'canceled'}`)
|
||||
|
||||
function confirm(type) {
|
||||
switch(type) {
|
||||
case 'custom':
|
||||
return Dialog.confirm({
|
||||
message: 'This is a custom confirmation message',
|
||||
title: "I'm a title!",
|
||||
type: 'is-danger',
|
||||
icon: 'times-circle'
|
||||
})
|
||||
.then(thenHandler)
|
||||
default:
|
||||
Dialog.confirm('Shall we dance?')
|
||||
.then(thenHandler)
|
||||
}
|
||||
}
|
||||
|
||||
function prompt(opts) {
|
||||
Dialog.prompt({
|
||||
message: "What is your quest?",
|
||||
...opts
|
||||
})
|
||||
.then(prompt => Toast.create(`Your answer was: '${prompt}'`))
|
||||
}
|
||||
</script>
|
||||
|
||||
<DocHeader title="Dialog" subtitle="用户警报,提示和确认对话框" />
|
||||
|
||||
<p class="title is-4">Alert and Dialog</p>
|
||||
|
||||
<p class="content">Use <code>Dialog.alert()</code> and <code>Dialog.confirm()</code> to create these kinds of dialogs.
|
||||
The methods return a promise that is resolved when the user cancels or confirms the alert. If the use closes/cancels the
|
||||
value will be <code>false</code>. If the user clicks the confirm button the value will be <code>true</code>.
|
||||
|
||||
The first argument can either be an object of options or a string to use as the message.</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Dialog, Toast } from 'svelma-pro'
|
||||
|
||||
function alert() {
|
||||
Dialog.alert('Alles ist gut')
|
||||
}
|
||||
|
||||
const thenHandler = result => Toast.create(\`You \${result ? 'confirmed' : 'canceled'}\`)
|
||||
|
||||
function confirm(type) {
|
||||
switch(type) {
|
||||
case 'custom':
|
||||
return Dialog.confirm({
|
||||
message: 'This is a custom confirmation message',
|
||||
title: "I'm a title!",
|
||||
type: 'is-danger',
|
||||
icon: 'times-circle'
|
||||
})
|
||||
.then(thenHandler)
|
||||
default:
|
||||
Dialog.confirm('Shall we dance?')
|
||||
.then(thenHandler)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button type="is-primary" on:click={() => alert()}>Dialog</Button>
|
||||
<Button type="is-info" on:click={() => confirm()}>Confirm</Button>
|
||||
<Button type="is-danger" on:click={() => confirm('custom')}>Confirm (custom)</Button>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Button type="is-primary" on:click={() => alert()}>Dialog</Button>
|
||||
<Button type="is-info" on:click={() => confirm()}>Confirm</Button>
|
||||
<Button type="is-danger" on:click={() => confirm('custom')}>Confirm (custom)</Button>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Prompt</p>
|
||||
|
||||
<p class="content">Use <code>Dialog.prompt()</code> to programmatically create prompts for user input. By default the
|
||||
dialog will be created with a required text input. You can control the props (attributes) on the prompt with the
|
||||
<code>inputProps</code> prop.
|
||||
|
||||
<code>prompt()</code> returns a promise that will be resolved with the prompt input value if the user confirms, or null
|
||||
if they cancel/close.</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Dialog, Toast } from 'svelma-pro'
|
||||
|
||||
function prompt(opts) {
|
||||
Dialog.prompt({
|
||||
message: "What is your quest?",
|
||||
...opts
|
||||
})
|
||||
.then(prompt => Toast.create(\`Your answer was: '\${prompt}'\`))
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button type="is-primary" on:click={() => prompt()}>Prompt</Button>
|
||||
<Button type="is-link" on:click={() => prompt({ message: 'Which date?', inputProps: { type: 'date' }})}>Date Prompt</Button>`
|
||||
}>
|
||||
<div slot="preview">
|
||||
<Button type="is-primary" on:click={() => prompt()}>Prompt</Button>
|
||||
<Button type="is-link" on:click={() => prompt({ message: 'Which date?', inputProps: { type: 'date' }})}>Date Prompt</Button>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,269 @@
|
|||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const res = await this.fetch(`components/field.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Button, Field, Icon, Input } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
let name = 'Moby Dick'
|
||||
|
||||
export let jsdoc
|
||||
</script>
|
||||
|
||||
<DocHeader title="Field" subtitle="添加功能和样式表单元素/输入" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field label="Name">
|
||||
<Input value="Rich Harris" />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" type="is-danger" message="Email is invalid">
|
||||
<Input value="john@" />
|
||||
</Field>
|
||||
|
||||
<Field label="Username" type="is-success" message="Username is available">
|
||||
<Input value="joey55" />
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field label="Name">
|
||||
<Input value="Rich Harris" />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" type="is-danger" message="Email is invalid">
|
||||
<Input value="john@" />
|
||||
</Field>
|
||||
|
||||
<Field label="Username" type="is-success" message="Username is available">
|
||||
<Input value="joey55" />
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Addons</p>
|
||||
|
||||
Multiple controls in a field get attached. Use <code>expanded</code> property on the control to fill up space on the line.
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Field, Icon, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field>
|
||||
<Input type="search" placeholder="Search" icon="search" />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input type="search" placeholder="This is expanded" expanded />
|
||||
<p class="control">
|
||||
<Button type="is-static">@gmail.com</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<hr>
|
||||
|
||||
<Field>
|
||||
<div class="control"><Button><Icon icon="bold"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="italic"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="underline"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-left"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-center"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-right"></Icon></Button></div>
|
||||
<Input expanded icon="comment" placeholder="Text here" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
<div class="control"><Button type="is-primary"><Icon icon="search" /></Button></div>
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field>
|
||||
<Input type="search" placeholder="Search" icon="search" />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input type="search" placeholder="This is expanded" expanded />
|
||||
<p class="control">
|
||||
<Button type="is-static">@gmail.com</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<hr>
|
||||
|
||||
<Field>
|
||||
<div class="control"><Button><Icon icon="bold"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="italic"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="underline"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-left"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-center"></Icon></Button></div>
|
||||
<div class="control"><Button><Icon icon="align-right"></Icon></Button></div>
|
||||
<Input expanded icon="comment" placeholder="Text here" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
<div class="control"><Button type="is-primary"><Icon icon="search" /></Button></div>
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Groups</p>
|
||||
|
||||
Use the <code>grouped</code> property to group controls together. Use the <code>expanded</code> property to make a control take up remaining space.
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field grouped>
|
||||
<Input type="search" placeholder="Search" icon="search" />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<Field grouped>
|
||||
<Input type="search" placeholder="Search" icon="search" expanded />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field grouped>
|
||||
<Input type="search" placeholder="Search" icon="search" />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>
|
||||
|
||||
<Field grouped>
|
||||
<Input type="search" placeholder="Search" icon="search" expanded />
|
||||
<p class="control">
|
||||
<Button type="is-primary">Search</Button>
|
||||
</p>
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Nested Groups</p>
|
||||
|
||||
You can nest fields inside fields. You have to use the <code>expanded</code> property on the <strong>Field</strong> to fill up the remaining space.
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field grouped>
|
||||
<Field label="Button">
|
||||
<Button type="is-primary">Button</Button>
|
||||
</Field>
|
||||
|
||||
<Field label="Name" expanded>
|
||||
<Input />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" expanded>
|
||||
<Input />
|
||||
</Field>
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field grouped>
|
||||
<Field label="Button">
|
||||
<Button type="is-primary">Button</Button>
|
||||
</Field>
|
||||
|
||||
<Field label="Name" expanded>
|
||||
<Input />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" expanded>
|
||||
<Input />
|
||||
</Field>
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Responsive Groups</p>
|
||||
|
||||
Add <code>groupMultiline</code> property to allow controls to fill up multiple lines.
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field grouped groupMultiline>
|
||||
<Input />
|
||||
{#each Array(30).fill().map((x, i) => i+1) as num}
|
||||
<div class="control">
|
||||
<Button>{num}</Button>
|
||||
</div>
|
||||
{/each}
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field grouped groupMultiline>
|
||||
<Input />
|
||||
{#each Array(30).fill().map((x, i) => i+1) as num}
|
||||
<div class="control">
|
||||
<Button>{num}</Button>
|
||||
</div>
|
||||
{/each}
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Positions</p>
|
||||
|
||||
Use <code>position</code> property to align Field horizontally.
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field position="is-centered">
|
||||
<Input />
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
</Field>
|
||||
|
||||
<Field grouped position="is-right">
|
||||
<Input />
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field position="is-centered">
|
||||
<Input />
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
</Field>
|
||||
|
||||
<Field grouped position="is-right">
|
||||
<Input />
|
||||
<div class="control"><Button type="is-primary">Button</Button></div>
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc}></JSDoc>
|
|
@ -0,0 +1,33 @@
|
|||
<script>
|
||||
import { Icon } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
</script>
|
||||
|
||||
<DocHeader title="Icon" subtitle="浮标" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Icon } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Icon pack="fab" size="is-large" icon="github" />
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Icon pack="fab" size="is-large" icon="github"/>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">添加角标</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Icon } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Icon pack="fab" size="is-large" icon="github" num="99"/>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Icon pack="fab" size="is-large" icon="github" num="99"/>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,213 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/input.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Field, Input } from 'svelma-pro'
|
||||
import Codeview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
let bound = {
|
||||
name: 'Rich Harris',
|
||||
email: 'rich@',
|
||||
username: 'richie55',
|
||||
password: 'secret123',
|
||||
}
|
||||
</script>
|
||||
|
||||
<DocHeader title="Input" subtitle="用户输入控件" />
|
||||
|
||||
<p class="content">
|
||||
Mostly just wraps <code>{`<input>`}</code> and <code>{`<textarea>`}</code> so additional Bulma features can be bound easily.
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Input type="text" placeholder="Text input" />
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Input type="text" placeholder="Text input" />
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<br>
|
||||
|
||||
<p class="title is-4">Types and colors</p>
|
||||
|
||||
<p class="content">Wrap with <a href="components/field"><strong>Field</strong></a> for additional features</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Field, Input } from 'svelma-pro'
|
||||
|
||||
let bound = {
|
||||
name: 'Rich Harris',
|
||||
email: 'rich@',
|
||||
username: 'richie55',
|
||||
password: 'secret123',
|
||||
}
|
||||
</script>
|
||||
|
||||
<Field label="Name">
|
||||
<Input type="text" bind:value={bound.name} placeholder="Text input" />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" type="is-danger" message="Invalid email">
|
||||
<Input type="email" bind:value={bound.email} maxlength="30" />
|
||||
</Field>
|
||||
|
||||
<Field label="Username" type="is-success" message="Username available">
|
||||
<Input type="email" bind:value={bound.username} />
|
||||
</Field>
|
||||
|
||||
<Field label="Password">
|
||||
<Input type="password" bind:value={bound.password} passwordReveal={true} />
|
||||
</Field>
|
||||
|
||||
<Field label="Textarea">
|
||||
<Input type="textarea" maxlength="200" />
|
||||
</Field>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Codeview lang="js" showCopy={false}>
|
||||
// Bound values
|
||||
{JSON.stringify(bound, null, 2)}
|
||||
</Codeview>
|
||||
|
||||
<br>
|
||||
|
||||
<Field label="Name">
|
||||
<Input type="text" bind:value={bound.name} placeholder="Text input" />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" type="is-danger" message="Invalid email">
|
||||
<Input type="email" bind:value={bound.email} maxlength="30" />
|
||||
</Field>
|
||||
|
||||
<Field label="Username" type="is-success" message="Username available">
|
||||
<Input type="email" bind:value={bound.username} />
|
||||
</Field>
|
||||
|
||||
<Field label="Password">
|
||||
<Input type="password" bind:value={bound.password} passwordReveal={true} />
|
||||
</Field>
|
||||
|
||||
<Field label="Textarea">
|
||||
<Input type="textarea" maxlength="200" />
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">States, plus more styles</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="No label" />
|
||||
</Field>
|
||||
|
||||
<Field label="Rounded">
|
||||
<Input class="is-rounded" placeholder="Rounded" />
|
||||
</Field>
|
||||
|
||||
<Field label="Info" type="is-info">
|
||||
<Input placeholder="Info" />
|
||||
</Field>
|
||||
|
||||
<Field label="Warning" type="is-warning">
|
||||
<Input placeholder="Warning" />
|
||||
</Field>
|
||||
|
||||
<Field label="Disabled">
|
||||
<Input placeholder="Disabled" disabled />
|
||||
</Field>
|
||||
|
||||
<Field label="Loading">
|
||||
<Input placeholder="Loading" loading />
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field>
|
||||
<Input placeholder="No label" />
|
||||
</Field>
|
||||
|
||||
<Field label="Rounded">
|
||||
<Input class="is-rounded" placeholder="Rounded" />
|
||||
</Field>
|
||||
|
||||
<Field label="Info" type="is-info">
|
||||
<Input placeholder="Info" />
|
||||
</Field>
|
||||
|
||||
<Field label="Warning" type="is-warning">
|
||||
<Input placeholder="Warning" />
|
||||
</Field>
|
||||
|
||||
<Field label="Disabled">
|
||||
<Input placeholder="Disabled" disabled />
|
||||
</Field>
|
||||
|
||||
<Field label="Loading">
|
||||
<Input placeholder="Loading" loading />
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Sizes</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Field, Input } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Small" size="is-small" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Default" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Medium" size="is-medium" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Large" size="is-large" />
|
||||
</Field>`}>
|
||||
<div slot="preview">
|
||||
<Field>
|
||||
<Input placeholder="Small" size="is-small" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Default" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Medium" size="is-medium" />
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<Input placeholder="Large" size="is-large" />
|
||||
</Field>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc}></JSDoc>
|
|
@ -0,0 +1,55 @@
|
|||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const res = await this.fetch(`components/layout.json`)
|
||||
const jsdoc = await res.json()
|
||||
|
||||
return { jsdoc }
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
import { Layout, Children } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
</script>
|
||||
|
||||
<DocHeader title="Layout" subtitle="布局" />
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import { Layout, Children } from 'svelma-pro';
|
||||
</script>
|
||||
|
||||
<Layout>
|
||||
<Children.Sider width="100px">
|
||||
侧边栏
|
||||
</Children.Sider>
|
||||
<Layout>
|
||||
<Children.Header>
|
||||
头部
|
||||
</Children.Header>
|
||||
<Children.Content height="300px">
|
||||
内容
|
||||
</Children.Content>
|
||||
<Children.Footer>
|
||||
脚部
|
||||
</Children.Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Layout>
|
||||
<Children.Sider width="100px">侧边栏</Children.Sider>
|
||||
<Layout>
|
||||
<Children.Header>头部</Children.Header>
|
||||
<Children.Content height="300px">内容</Children.Content>
|
||||
<Children.Footer>脚部</Children.Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,34 @@
|
|||
<script>
|
||||
import { Button, Message } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
|
||||
let open
|
||||
</script>
|
||||
|
||||
<DocHeader title="Message" subtitle="传递信息的消息块" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Message } from 'svelma-pro'
|
||||
|
||||
let open
|
||||
</script>
|
||||
|
||||
<Button class="block" on:click={() => open = !open}>Toggle</Button>
|
||||
<Message active={!open} title="Default"
|
||||
on:close={active => open = active}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Message>`}>
|
||||
<div slot="preview">
|
||||
<Button class="block" on:click={() => open = !open}>Toggle</Button>
|
||||
<Message active={!open} title="Default"
|
||||
on:close={active => open = active}
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Message>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,45 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/modal.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
import { Button, Modal } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
|
||||
let active = false
|
||||
</script>
|
||||
|
||||
<DocHeader title="Modal" subtitle="模态框" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Modal } from 'svelma-pro'
|
||||
|
||||
let active = false
|
||||
</script>
|
||||
|
||||
<Button class="block" on:click={() => active = !active}>Toggle</Button>
|
||||
<Modal bind:active={active}>
|
||||
<p class="image is-4by3">
|
||||
<img alt="Test image" src="https://via.placeholder.com/1280x920"/>
|
||||
</p>
|
||||
</Modal>`}>
|
||||
<div slot="preview">
|
||||
<Button class="block" on:click={() => active = !active}>Toggle</Button>
|
||||
<Modal bind:active={active}>
|
||||
<p class="image is-4by3">
|
||||
<img alt="Test image" src="https://via.placeholder.com/1280x920"/>
|
||||
</p>
|
||||
</Modal>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc}/>
|
|
@ -0,0 +1,236 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/notification.json`)
|
||||
const jsdoc = await res.json()
|
||||
|
||||
return { jsdoc }
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Button, Notification } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
let isOpen = true
|
||||
let autoIsOpen = false
|
||||
|
||||
function open(props) {
|
||||
Notification.create({ message: 'I am a notification message', ...props })
|
||||
}
|
||||
|
||||
function showNotification(props) {
|
||||
Notification.create({
|
||||
message: 'You opened this programmatically!',
|
||||
...props
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<DocHeader title="Notification" subtitle="提醒用户的通知" />
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import { Button, Notification } from 'svelma-pro';
|
||||
|
||||
let isOpen = true
|
||||
</script>
|
||||
|
||||
<Button class="block" on:click={() => (isOpen = !isOpen)}>Toggle</Button>
|
||||
<Notification bind:active={isOpen}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>`}>
|
||||
<div slot="preview">
|
||||
<Button class="block" on:click={() => (isOpen = !isOpen)}>Toggle</Button>
|
||||
<Notification bind:active={isOpen}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Types</p>
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import { Notification } from 'svelma-pro';
|
||||
</script>
|
||||
|
||||
<Notification>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-info">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-success">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-warning">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-danger">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>`}>
|
||||
<div slot="preview">
|
||||
<Notification>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-info">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-success">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-warning">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-danger">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Icons</p>
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import { Notification } from 'svelma-pro';
|
||||
</script>
|
||||
|
||||
<Notification icon="question-circle">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-info" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-success" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-warning" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-danger" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>`}>
|
||||
<div slot="preview">
|
||||
<Notification icon="question-circle">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-info" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-success" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-warning" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
|
||||
<Notification type="is-danger" icon={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Auto-close</p>
|
||||
|
||||
<p>
|
||||
Notification will close automatically after
|
||||
<code>duration</code>
|
||||
.
|
||||
</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Notification } from 'svelma-pro';
|
||||
|
||||
let autoIsOpen = false
|
||||
</script>
|
||||
|
||||
<Button class="block" on:click={() => (autoIsOpen = true)}>Show</Button>
|
||||
<Notification bind:active={autoIsOpen} autoClose={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>`}>
|
||||
<div slot="preview">
|
||||
<Button class="block" on:click={() => (autoIsOpen = true)}>Show</Button>
|
||||
<Notification bind:active={autoIsOpen} autoClose={true}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id fermentum quam. Proin sagittis, nibh id
|
||||
hendrerit imperdiet, elit sapien laoreet elit
|
||||
</Notification>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<p class="title is-4">Opening with code</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Notification } from 'svelma-pro';
|
||||
|
||||
function showNotification(props) {
|
||||
Notification.create({
|
||||
message: 'You opened this programmatically!',
|
||||
...props
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button class="block" on:click={() => showNotification()}>Show Notification</Button>
|
||||
<Button class="block" type="is-success" on:click={() => showNotification({ type: 'is-success' })}>Show Notification (success)</Button>
|
||||
<Button class="block" type="is-danger" on:click={() => showNotification({ type: 'is-danger', position: 'is-bottom-right', icon: true })}>Show Notification (danger)</Button>`}>
|
||||
<div slot="preview">
|
||||
<Button class="block" on:click={() => showNotification()}>Show Notification</Button>
|
||||
<Button class="block" type="is-success" on:click={() => showNotification({ type: 'is-success' })}>Show Notification (success)</Button>
|
||||
<Button class="block" type="is-danger" on:click={() => showNotification({ type: 'is-danger', position: 'is-bottom-right', icon: true })}>Show Notification (danger)</Button>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,19 @@
|
|||
<script>
|
||||
import {Pagination} from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
</script>
|
||||
|
||||
<DocHeader title="Pagination" subtitle="分页" />
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import {Pagination} from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Pagination current="1" total="10" show="5" align="centered" />
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Pagination current="1" total="10" show="5" align="centered" />
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,72 @@
|
|||
<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import Codepreview from '../../components/Code.svelte'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import { Progress } from 'svelma-pro'
|
||||
|
||||
const types = ['is-primary', 'is-success', 'is-danger', 'is-warning', 'is-info', 'is-link']
|
||||
const progresses = Array(6).fill(0)
|
||||
|
||||
function update() {
|
||||
types.forEach((type, i) => {
|
||||
progresses[i] = Math.floor(Math.random() * 100)
|
||||
})
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
update()
|
||||
})
|
||||
</script>
|
||||
|
||||
<DocHeader title="Progress" subtitle="进度条" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { Progress } from 'svelma-pro'
|
||||
|
||||
const types = ['is-primary', 'is-success', 'is-danger', 'is-warning', 'is-info', 'is-link']
|
||||
const progresses = Array(6).fill(0)
|
||||
|
||||
function update() {
|
||||
types.forEach((type, i) => {
|
||||
progresses[i] = Math.floor(Math.random() * 100)
|
||||
})
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
update()
|
||||
})
|
||||
</script>
|
||||
|
||||
<button class="button is-primary" on:click={update}>Update</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{#each types as type, i}
|
||||
<Progress {type} value={progresses[i]} duration={i * 200} max="100"></Progress>
|
||||
{/each}
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<p class="title is-5">Indeterminate (no value)</p>
|
||||
<Progress max="100"></Progress>`}>
|
||||
<div slot="preview">
|
||||
<button class="button is-primary" on:click={update}>Update</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{#each types as type, i}
|
||||
<Progress {type} value={progresses[i]} duration={i * 200} max="100"></Progress>
|
||||
{/each}
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<p class="title is-5">Indeterminate (no value)</p>
|
||||
<Progress max="100"></Progress>
|
||||
</div>
|
||||
</Example>
|
|
@ -0,0 +1,58 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/snackbar.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Button, Snackbar } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
function open(props) {
|
||||
Snackbar.create({ message: 'I am a snackbar message', ...props })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<DocHeader title="Snackbar" subtitle="比提示轻量,比吐司重要的提醒框" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Snackbar } from 'svelma-pro'
|
||||
|
||||
function open(props) {
|
||||
Snackbar.create({ message: 'I am a snackbar message', ...props })
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="buttons">
|
||||
<Button on:click={() => open()}>Default Snackbar</Button>
|
||||
<Button type="is-success" on:click={() => open({ type: 'is-success' })}>Success</Button>
|
||||
<Button type="is-danger" on:click={() => open({ type: 'is-danger', actionText: 'retry', position: 'is-top-right' })}>Top Right</Button>
|
||||
<Button type="is-primary" on:click={() => open({ background: 'has-background-grey-lighter' })}>Custom Background</Button>
|
||||
</div>`}>
|
||||
<div slot="preview">
|
||||
<div class="buttons">
|
||||
<Button on:click={() => open()}>Default Snackbar</Button>
|
||||
<Button type="is-success" on:click={() => open({ type: 'is-success' })}>Success</Button>
|
||||
<Button type="is-danger" on:click={() => open({ type: 'is-danger', actionText: 'retry', position: 'is-top-right' })}>Top Right</Button>
|
||||
<Button type="is-primary" on:click={() => open({ background: 'has-background-grey-lighter' })}>Custom Background</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,134 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/switch.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Switch } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
let val
|
||||
</script>
|
||||
|
||||
<DocHeader title="Switch" subtitle="开关" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Switch } from 'svelma-pro'
|
||||
|
||||
let val
|
||||
</script>
|
||||
|
||||
<div class="field">
|
||||
<Switch bind:checked={val}>Foo</Switch>
|
||||
<br>
|
||||
<code>value = {JSON.stringify(val)}</code>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch disabled>Disabled</Switch>
|
||||
</div>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<div class="field">
|
||||
<Switch bind:checked={val}>Foo</Switch>
|
||||
<br>
|
||||
<code>value = {JSON.stringify(val)}</code>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch disabled>Disabled</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
<p class="title is-4">Types</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Switch } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-primary">Primary</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-danger">Danger</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-warning">Warning</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-info">Info</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-link">Link</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-dark">Dark</Switch>
|
||||
</div>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-primary">Primary</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-danger">Danger</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-warning">Warning</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-info">Info</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-link">Link</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch checked="true" type="is-dark">Dark</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
<p class="title is-4">Sizes</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Switch } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<div class="field">
|
||||
<Switch size="is-small">Small</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch>Default</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch size="is-medium">Medium</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch size="is-large">Large</Switch>
|
||||
</div>
|
||||
</div>
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<div class="field">
|
||||
<Switch size="is-small">Small</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch>Default</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch size="is-medium">Medium</Switch>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Switch size="is-large">Large</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc}></JSDoc>
|
|
@ -0,0 +1,210 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const tabsRes = await this.fetch(`components/tabs.json`);
|
||||
const tabRes = await this.fetch(`components/tab.json`);
|
||||
const jsdocTabs = await tabsRes.json();
|
||||
const jsdocTab = await tabRes.json();
|
||||
|
||||
return { jsdocTabs, jsdocTab };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Tabs, Tab } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdocTabs
|
||||
export let jsdocTab
|
||||
</script>
|
||||
|
||||
<DocHeader title="Tabs" subtitle="横向导航选项卡" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Tabs, Tab } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Tabs>
|
||||
<Tab label="Svelte">
|
||||
Is cool
|
||||
</Tab>
|
||||
<Tab label="Vue">
|
||||
Is good
|
||||
</Tab>
|
||||
<Tab label="Angular">
|
||||
lol no
|
||||
</Tab>
|
||||
</Tabs>`}>
|
||||
<div slot="preview">
|
||||
<Tabs>
|
||||
<Tab label="Svelte">
|
||||
Is cool
|
||||
</Tab>
|
||||
<Tab label="Vue">
|
||||
Is good
|
||||
</Tab>
|
||||
<Tab label="Angular">
|
||||
lol no
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Icons and Sizes</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Tabs, Tab } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Tabs>
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs size="is-medium">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs size="is-large">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>`}>
|
||||
<div slot="preview">
|
||||
<Tabs>
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs size="is-medium">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs size="is-large">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Position</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Tabs, Tab } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Tabs position="is-centered">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs position="is-right">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>`}>
|
||||
<div slot="preview">
|
||||
<Tabs position="is-centered">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs position="is-right">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<p class="title is-4">Style</p>
|
||||
|
||||
<p class="content">
|
||||
Use <code>is-boxed</code>, <code>is-toggle</code>, <code>is-toggle</code> and <code>is-toggle-rounded</code>, or
|
||||
<code>is-fullwidth</code> to alter to style of your tabs.
|
||||
</p>
|
||||
|
||||
<Example code={`<script>
|
||||
import { Tabs, Tab } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Tabs style="is-boxed">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-toggle">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-toggle is-toggle-rounded">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-fullwidth">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>`}>
|
||||
<div slot="preview">
|
||||
<Tabs style="is-boxed">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-toggle">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-toggle is-toggle-rounded">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
|
||||
<Tabs style="is-fullwidth">
|
||||
<Tab label="People" icon="users"></Tab>
|
||||
<Tab label="Places" icon="map-marker-alt"></Tab>
|
||||
<Tab label="Things" icon="ellipsis-h"></Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<hr class="is-medium" />
|
||||
|
||||
<h2 class="title is-4 is-spaced">API</h2>
|
||||
|
||||
<h3 class="subtitle">Tabs</h3>
|
||||
|
||||
<JSDoc jsdoc={jsdocTabs} showHeader={false}></JSDoc>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<h3 class="subtitle is-spaced">Tab</h3>
|
||||
|
||||
<JSDoc jsdoc={jsdocTab} showHeader={false}></JSDoc>
|
|
@ -0,0 +1,39 @@
|
|||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const res = await this.fetch(`components/timepicker.json`)
|
||||
const jsdoc = await res.json()
|
||||
|
||||
return { jsdoc }
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
import {Timepicker} from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
let time = new Date();
|
||||
|
||||
function test(e){
|
||||
// debugger;
|
||||
console.log(e)
|
||||
}
|
||||
</script>
|
||||
|
||||
<DocHeader title="Timepicker" subtitle="时间选择器" />
|
||||
|
||||
<Example
|
||||
code={`<script>
|
||||
import {Timepicker} from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Timepicker bind:time />
|
||||
`}>
|
||||
<div slot="preview">
|
||||
<Timepicker bind:time on:change={test}/>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} showEvent="true"/>
|
|
@ -0,0 +1,55 @@
|
|||
<script context="module">
|
||||
export async function preload() {
|
||||
const res = await this.fetch(`components/toast.json`);
|
||||
const jsdoc = await res.json();
|
||||
|
||||
return { jsdoc };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Button, Toast } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Example from '../../components/Example.svelte'
|
||||
import JSDoc from '../../components/JSDoc.svelte'
|
||||
|
||||
export let jsdoc
|
||||
|
||||
function open(type, position, background) {
|
||||
Toast.create({ message: 'I am a toast', type, position, background })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<DocHeader title="Toast" subtitle="吐司" />
|
||||
|
||||
<Example code={`<script>
|
||||
import { Button, Toast } from 'svelma-pro'
|
||||
|
||||
function open(type, position) {
|
||||
Toast.create({ message: 'I am a toast', type, position })
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button on:click={() => open()}>Toast</Button>
|
||||
<Button type="is-success" on:click={() => open('is-success')}>Success</Button>
|
||||
<Button type="is-danger" on:click={() => open('is-danger', 'is-bottom-right')}>Bottom Right</Button>
|
||||
<Button type="is-primary" on:click={() => open('is-primary', 'is-top', 'has-background-grey-lighter')}>Custom Background</Button>`}>
|
||||
<div slot="preview">
|
||||
<div class="buttons">
|
||||
<Button on:click={() => open()}>Toast</Button>
|
||||
<Button type="is-success" on:click={() => open('is-success')}>Success</Button>
|
||||
<Button type="is-danger" on:click={() => open('is-danger', 'is-bottom-right')}>Bottom Right</Button>
|
||||
<Button type="is-primary" on:click={() => open('is-primary', 'is-top', 'has-background-grey-lighter')}>Custom Background</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<JSDoc {jsdoc} />
|
|
@ -0,0 +1,72 @@
|
|||
<script>
|
||||
import { Message } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1,
|
||||
/* figure, */
|
||||
p {
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.8em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
/* figure {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin: 0 0 1em 0;
|
||||
} */
|
||||
|
||||
p {
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
display: inline-flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>svelma-pro</title>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Svelma" />
|
||||
<meta property="og:description" content="Bulma components for Svelte" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="hero is-full-height">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
<h1 class="title">svelma-pro</h1>
|
||||
<h2 class="subtitle">基于开源svelma-pro项目扩展而来的组件库,扩展原有功能,新增一些常用组件.</h2>
|
||||
|
||||
<pre>
|
||||
<code>$ npm install svelma-pro</code>
|
||||
</pre>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<p>
|
||||
<Message title="Note!" type="is-primary" showClose={false}>
|
||||
为了针对svelte市面成熟组件库缺少及组件分散的情况,团队在svelma-pro开源库的基础上定制及扩展团队私有组件库,可以避免大量的引入分散组件导致的模块管理混乱及市面组件无法自定义扩展,升级等问题.
|
||||
</Message>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,154 @@
|
|||
<script>
|
||||
import { Message } from 'svelma-pro'
|
||||
import DocHeader from '../../components/DocHeader.svelte'
|
||||
import Codeview from '../../components/Code.svelte'
|
||||
</script>
|
||||
|
||||
<DocHeader title="Start" subtitle="如何使用" />
|
||||
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<p class="title">1</p>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title">NPM</p>
|
||||
<p class="subtitle is-spaced">此组件库适用于基于rollup或者webpack搭建的svelte及sapper项目</p>
|
||||
<p class="title is-4">下载安装</p>
|
||||
|
||||
<div class="content">下载bluma与组件库.</div>
|
||||
|
||||
<Codeview lang="bash">npm install --save bulma svelma-pro</Codeview>
|
||||
|
||||
<div class="content">集成scss模板语法支持(因为组件库采用了类似vue的scss模板写法,所以需要也集成进去).</div>
|
||||
|
||||
<Codeview lang="bash">npm install --save-dev svelte-preprocess autoprefixer node-sass sass</Codeview>
|
||||
|
||||
<div class="content">
|
||||
添加
|
||||
<code>scss编译</code>
|
||||
到你的
|
||||
<code>rollup.config.js</code>
|
||||
配置文件中(或者webpack.config.js).
|
||||
</div>
|
||||
|
||||
<Codeview
|
||||
lang="js"
|
||||
code={`import sveltePreprocess from 'svelte-preprocess';
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
svelte({
|
||||
// ...
|
||||
preprocess: preprocess,
|
||||
})
|
||||
]
|
||||
}`} />
|
||||
|
||||
<div class="content">
|
||||
如果使用webpack,在
|
||||
<code>webpack.config.js</code>
|
||||
配置文件中.
|
||||
</div>
|
||||
<Codeview
|
||||
lang="js"
|
||||
code={`import sveltePreprocess from 'svelte-preprocess';
|
||||
const preprocess = sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ['src'],
|
||||
},
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')],
|
||||
},
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
module.export = {
|
||||
// ...
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(svelte|html)$/,
|
||||
use: {
|
||||
loader: 'svelte-loader',
|
||||
options: {
|
||||
preprocess,
|
||||
// ...
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}`} />
|
||||
|
||||
<p class="title is-4">使用</p>
|
||||
<div class="content">引入bluma样式到您的项目</div>
|
||||
<Codeview lang="html" code={`
|
||||
<!-- main.js或者client.js全局引入 -->
|
||||
<script>
|
||||
import 'bulma/css/bulma.css'
|
||||
</script>
|
||||
`}>
|
||||
</Codeview>
|
||||
|
||||
<div class="content">
|
||||
svelma-pro组件可以一次导入一个,就像这样
|
||||
</div>
|
||||
<Codeview lang="html" code={`
|
||||
<script>
|
||||
import { Button } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Button>I am a Button</Button>
|
||||
`}>
|
||||
</Codeview>
|
||||
|
||||
<div class="content">
|
||||
或导入完整的Svelma软件包。
|
||||
</div>
|
||||
<Codeview lang="html" code={`
|
||||
<script>
|
||||
import { Svelma } from 'svelma-pro'
|
||||
</script>
|
||||
|
||||
<Svelma.Button>I am a Button</Svelma.Button>
|
||||
`}>
|
||||
</Codeview>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="is-medium">
|
||||
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<p class="title">2</p>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title is-spaced">使用 [Font Awesome] 图标</p>
|
||||
|
||||
添加 CDN 在你的 HTML 页面:
|
||||
<Codeview lang="bash" code={`
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"></link>
|
||||
`}/>
|
||||
...或者使用npm包:
|
||||
<Codeview lang="bash" code={`npm install --save @fortawesome/fontawesome-free`}/>
|
||||
<Codeview lang="bash" code={`<!-- main.js or client.js(sapper) -->
|
||||
<script>
|
||||
import '@fortawesome/fontawesome-free/css/all.css'
|
||||
</script>`}/>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,18 @@
|
|||
import sirv from 'sirv';
|
||||
import polka from 'polka';
|
||||
import compression from 'compression';
|
||||
import * as sapper from '@sapper/server';
|
||||
|
||||
const { PORT, NODE_ENV } = process.env;
|
||||
const dev = NODE_ENV === 'development';
|
||||
|
||||
polka() // You can also use Express
|
||||
.use(...[
|
||||
process.env.SAPPER_EXPORT && '/svelma-pro' || undefined,
|
||||
compression({ threshold: 0 }),
|
||||
sirv('static', { dev }),
|
||||
sapper.middleware()
|
||||
].filter(x => !!x))
|
||||
.listen(PORT, err => {
|
||||
if (err) console.log('error', err);
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
import { timestamp, files, shell, routes } from '@sapper/service-worker';
|
||||
|
||||
const ASSETS = `cache${timestamp}`;
|
||||
|
||||
// `shell` is an array of all the files generated by the bundler,
|
||||
// `files` is an array of everything in the `static` directory
|
||||
const to_cache = shell.concat(files);
|
||||
const cached = new Set(to_cache);
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches
|
||||
.open(ASSETS)
|
||||
.then(cache => cache.addAll(to_cache))
|
||||
.then(() => {
|
||||
self.skipWaiting();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(async keys => {
|
||||
// delete old caches
|
||||
for (const key of keys) {
|
||||
if (key !== ASSETS) await caches.delete(key);
|
||||
}
|
||||
|
||||
self.clients.claim();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
if (event.request.method !== 'GET' || event.request.headers.has('range')) return;
|
||||
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// don't try to handle e.g. data: URIs
|
||||
if (!url.protocol.startsWith('http')) return;
|
||||
|
||||
// ignore dev server requests
|
||||
if (url.hostname === self.location.hostname && url.port !== self.location.port) return;
|
||||
|
||||
// always serve static files and bundler-generated assets from cache
|
||||
if (url.host === self.location.host && cached.has(url.pathname)) {
|
||||
event.respondWith(caches.match(event.request));
|
||||
return;
|
||||
}
|
||||
|
||||
// for pages, you might want to serve a shell `service-worker-index.html` file,
|
||||
// which Sapper has generated for you. It's not right for every
|
||||
// app, but if it's right for yours then uncomment this section
|
||||
/*
|
||||
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
|
||||
event.respondWith(caches.match('/service-worker-index.html'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if (event.request.cache === 'only-if-cached') return;
|
||||
|
||||
// for everything else, try the network first, falling back to
|
||||
// cache if the user is offline. (If the pages never change, you
|
||||
// might prefer a cache-first approach to a network-first one.)
|
||||
event.respondWith(
|
||||
caches
|
||||
.open(`offline${timestamp}`)
|
||||
.then(async cache => {
|
||||
try {
|
||||
const response = await fetch(event.request);
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
} catch(err) {
|
||||
const response = await cache.match(event.request);
|
||||
if (response) return response;
|
||||
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#333333" />
|
||||
|
||||
%sapper.base%
|
||||
|
||||
<link rel="stylesheet" href="global.css" />
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
<link rel="icon" type="image/png" href="favicon.ico" />
|
||||
|
||||
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" /> -->
|
||||
<!-- <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script> -->
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"></link>
|
||||
|
||||
<!-- Sapper generates a <style> tag containing critical CSS
|
||||
for the current page. CSS for the rest of the app is
|
||||
lazily loaded when it precaches secondary pages -->
|
||||
%sapper.styles%
|
||||
|
||||
<!-- This contains the contents of the <svelte:head> component, if
|
||||
the current page has one -->
|
||||
%sapper.head%
|
||||
</head>
|
||||
<body>
|
||||
<!-- The application will be rendered inside this element,
|
||||
because `app/client.js` references it -->
|
||||
<div id="sapper">%sapper.html%</div>
|
||||
|
||||
<!-- Sapper creates a <script> tag containing `app/client.js`
|
||||
and anything else it needs to hydrate the app and
|
||||
initialise the router -->
|
||||
%sapper.scripts%
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,61 @@
|
|||
/* body {
|
||||
margin: 0;
|
||||
font-family: Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans,
|
||||
Helvetica Neue, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 0 0 0.5em 0;
|
||||
font-weight: 400;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: menlo, inconsolata, monospace;
|
||||
font-size: calc(1em - 2px);
|
||||
color: #555;
|
||||
background-color: #f0f0f0;
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
body {
|
||||
font-size: 16px;
|
||||
}
|
||||
} */
|
||||
|
||||
header.header {
|
||||
border-bottom: 2px solid #f5f5f5;
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
header.header .subtitle {
|
||||
color: #7a7a7a;
|
||||
}
|
||||
|
||||
hr.is-medium {
|
||||
margin: 3rem 0
|
||||
}
|
||||
|
||||
.control .icon.is-clickable, .control.has-icons-left .icon.is-clickable, .control.has-icons-right .icon.is-clickable {
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
}
|
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"background_color": "#ffffff",
|
||||
"theme_color": "#333333",
|
||||
"name": "Svelma",
|
||||
"short_name": "Svelma",
|
||||
"display": "minimal-ui",
|
||||
"start_url": "/",
|
||||
"icons": [
|
||||
{
|
||||
"src": "logo-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "logo-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 6.1 KiB |
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Gravit.io -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
style="isolation:isolate"
|
||||
viewBox="0 0 93.19593 126.78137"
|
||||
width="93.19593"
|
||||
height="126.78137"
|
||||
version="1.1"
|
||||
id="svg13"
|
||||
sodipodi:docname="svelte-logo(1).svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
|
||||
<metadata
|
||||
id="metadata17">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1107"
|
||||
inkscape:window-height="721"
|
||||
id="namedview15"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0300053"
|
||||
inkscape:cx="254.27558"
|
||||
inkscape:cy="73.807952"
|
||||
inkscape:window-x="189"
|
||||
inkscape:window-y="87"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg13"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<defs
|
||||
id="defs5">
|
||||
<clipPath
|
||||
id="_clipPath_tx9IWIff9jpFhn3EvaPjyIq3XXdSNcS0">
|
||||
<rect
|
||||
width="519"
|
||||
height="139"
|
||||
id="rect2"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g
|
||||
clip-path="url(#_clipPath_tx9IWIff9jpFhn3EvaPjyIq3XXdSNcS0)"
|
||||
id="g11"
|
||||
inkscape:export-xdpi="95.919998"
|
||||
inkscape:export-ydpi="95.919998"
|
||||
transform="translate(-22.975806,-7.0562131)">
|
||||
<path
|
||||
d="M 110.23,28.39 C 99.83,13.51 97.139206,0.86190476 82.289206,10.321905 L 38.36,35.18 c -7.117,4.47 -12.025,11.729 -13.52,20 -1.247,6.904 -0.156,14.026 3.1,20.24 -2.232,3.386 -3.752,7.189 -4.47,11.18 -1.505,8.446 0.46,17.142 5.45,24.12 10.4,14.88 13.090794,29.58762 27.940794,20.12762 L 100.79,104 c 7.109,-4.479 12.013,-11.734 13.52,-20 1.243,-6.902 0.148,-14.02 -3.11,-20.23 2.231,-3.387 3.754,-7.19 4.48,-11.18 1.5,-8.446 -0.464,-17.14 -5.45,-24.12"
|
||||
id="path7"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#00c4a7"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
d="m 61.89,112.135 c -8.41,2.183 -17.288,-1.111 -22.24,-8.25 -2.999,-4.195 -4.178,-9.423 -3.27,-14.5 0.147,-0.817 0.355,-1.623 0.62,-2.41 l 0.49,-1.5 1.34,1 c 3.08,2.249 6.519,3.96 10.17,5.06 l 1,0.29 -0.09,1 c -0.096,1.371 0.289,2.733 1.09,3.85 1.494,2.148 4.168,3.137 6.7,2.48 0.565,-0.152 1.105,-0.388 1.6,-0.7 l 26.04,-16.62 c 1.293,-0.813 2.183,-2.135 2.45,-3.64 0.269,-1.532 -0.091,-3.107 -1,-4.37 -1.494,-2.147 -4.168,-3.137 -6.7,-2.48 -0.566,0.15 -1.106,0.386 -1.6,0.7 l -10,6.35 c -1.636,1.037 -3.419,1.82 -5.29,2.32 -8.395,2.169 -17.253,-1.118 -22.2,-8.24 -2.99,-4.199 -4.162,-9.426 -3.25,-14.5 0.893,-4.984 3.844,-9.362 8.13,-12.06 L 72,29.295 c 1.626,-1.035 3.399,-1.817 5.26,-2.32 8.407,-2.183 17.283,1.111 22.23,8.25 3.002,4.194 4.185,9.422 3.28,14.5 -0.156,0.822 -0.363,1.634 -0.62,2.43 l -0.5,1.5 -1.33,-1 c -3.087,-2.265 -6.536,-3.99 -10.2,-5.1 l -1,-0.29 0.09,-1 c 0.115,-1.378 -0.26,-2.752 -1.06,-3.88 -1.503,-2.11 -4.155,-3.069 -6.66,-2.41 -0.566,0.15 -1.106,0.386 -1.6,0.7 L 53.8,57.265 c -1.288,0.815 -2.177,2.131 -2.45,3.63 -0.264,1.535 0.096,3.112 1,4.38 1.487,2.127 4.133,3.115 6.65,2.48 0.564,-0.154 1.103,-0.39 1.6,-0.7 l 10,-6.34 c 1.634,-1.048 3.422,-1.834 5.3,-2.33 8.405,-2.189 17.282,1.102 22.23,8.24 3,4.195 4.183,9.423 3.28,14.5 -0.893,4.985 -3.844,9.363 -8.13,12.06 l -26.09,16.62 c -1.639,1.041 -3.426,1.826 -5.3,2.33"
|
||||
id="path9"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"name": "svelma-pro",
|
||||
"svelte": "src/index.js",
|
||||
"description": "Based on svelma project extension and modification",
|
||||
"version": "1.0.0",
|
||||
"author": "KeiferJu",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"svelte",
|
||||
"svelte.js",
|
||||
"svelma",
|
||||
"bulma",
|
||||
"component",
|
||||
"components"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/KeiferJu/svelma-pro"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/KeiferJu/svelma-pro/issues"
|
||||
},
|
||||
"module": "dist/module.js",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"bulma": "^0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.6.0",
|
||||
"bulma": "^0.8.0",
|
||||
"conventional-changelog-cli": "^2.0.21",
|
||||
"get-port-cli": "^2.0.0",
|
||||
"gh-pages": "^2.2.0",
|
||||
"node-sass": "^4.12.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^7.0.17",
|
||||
"prettier": "^1.17.1",
|
||||
"prettier-plugin-svelte": "^0.5.1",
|
||||
"rollup": "^1.2.2",
|
||||
"rollup-plugin-alias": "^1.5.1",
|
||||
"rollup-plugin-analyzer": "^3.0.1",
|
||||
"rollup-plugin-bundle-size": "^1.0.3",
|
||||
"rollup-plugin-commonjs": "^9.2.0",
|
||||
"rollup-plugin-copy": "^2.0.1",
|
||||
"rollup-plugin-livereload": "^1.0.4",
|
||||
"rollup-plugin-node-resolve": "^4.0.1",
|
||||
"rollup-plugin-scss": "^1.0.1",
|
||||
"rollup-plugin-svelte": "^5.0.3",
|
||||
"rollup-plugin-terser": "^4.0.4",
|
||||
"semantic-release": "^15.13.24",
|
||||
"sirv-cli": "^0.3.1",
|
||||
"standard-version": "^6.0.1",
|
||||
"svelte": "^3.9.2",
|
||||
"svelte-preprocess": "^2.12.0",
|
||||
"wait-for-localhost-cli": "^1.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"autobuild": "rollup -c -w",
|
||||
"autodocs": "(cd docs; npx sapper dev --basepath svelma-pro)",
|
||||
"dev": "run-p autobuild autodocs",
|
||||
"docs": "(cd docs; npx sapper export --basepath svelma-pro)",
|
||||
"clean": "rm -rf node_modules/gh-pages/.cache",
|
||||
"deploy": "npm run clean && npm run docs && node ./deploy.js",
|
||||
"pkg": "npm run build && npm publish"
|
||||
},
|
||||
"browserslist": "last 2 versions"
|
||||
}
|
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,65 @@
|
|||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
hr.is-medium {
|
||||
margin: 3rem 0
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf8'>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='stylesheet' href='global.css'>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src='index.js'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,55 @@
|
|||
import analyze from 'rollup-plugin-analyzer'
|
||||
import autoPreprocess from 'svelte-preprocess'
|
||||
import bundleSize from 'rollup-plugin-bundle-size'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import svelte from 'rollup-plugin-svelte'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import pkg from './package.json'
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH
|
||||
|
||||
const { name } = pkg
|
||||
|
||||
export default {
|
||||
input: 'src/index.js',
|
||||
output: [
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'es',
|
||||
sourcemap: true,
|
||||
name,
|
||||
},
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'umd',
|
||||
sourcemap: true,
|
||||
name,
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// generate: production ? 'dom' : 'ssr',
|
||||
hydratable: true,
|
||||
|
||||
preprocess: autoPreprocess({
|
||||
postcss: {
|
||||
plugins: [require('autoprefixer')()],
|
||||
},
|
||||
})
|
||||
}),
|
||||
|
||||
resolve(),
|
||||
commonjs(),
|
||||
|
||||
production && terser(),
|
||||
|
||||
// production && analyze(),
|
||||
production && bundleSize(),
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import Icon from './Icon.svelte'
|
||||
import { omit } from '../utils'
|
||||
|
||||
/** HTML tag to use for button (either 'a' or 'button')
|
||||
* @svelte-prop {String} tag=button
|
||||
* @values <code>button</code>, <code>a</code>
|
||||
* */
|
||||
export let tag = 'button'
|
||||
|
||||
/** Type (color of control)
|
||||
* @svelte-prop {String} [type] - Type (color of control)
|
||||
* @values $$colors$$
|
||||
* */
|
||||
export let type = ''
|
||||
|
||||
/** Size of button
|
||||
* @svelte-prop {String} [size]
|
||||
* @values $$sizes$$
|
||||
* */
|
||||
export let size = ''
|
||||
|
||||
/** Href to use when <code>tag</code> is 'a'
|
||||
* @svelte-prop {String} [href]
|
||||
* */
|
||||
export let href = ''
|
||||
|
||||
/** Native button type
|
||||
* @svelte-prop {String} [nativeType]=button
|
||||
* @values Any native button type (button, submit, reset)
|
||||
* */
|
||||
export let nativeType = 'button'
|
||||
|
||||
export let loading = false
|
||||
export let inverted = false
|
||||
export let outlined = false
|
||||
export let rounded = false
|
||||
|
||||
export let iconLeft = null
|
||||
export let iconRight = null
|
||||
export let iconPack = null
|
||||
|
||||
let iconSize = ''
|
||||
|
||||
onMount(() => {
|
||||
if (!['button', 'a'].includes(tag)) throw new Error(`'${tag}' cannot be used as a tag for a Bulma button`)
|
||||
})
|
||||
|
||||
$: props = {
|
||||
...omit($$props, 'loading', 'inverted', 'nativeType', 'outlined', 'rounded', 'type'),
|
||||
class: `button ${type} ${size} ${$$props.class || ''}`,
|
||||
}
|
||||
|
||||
$: {
|
||||
if (!size || size === 'is-medium') {
|
||||
iconSize = 'is-small'
|
||||
} else if (size === 'is-large') {
|
||||
iconSize = 'is-medium'
|
||||
} else {
|
||||
iconSize = size
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if tag === 'button'}
|
||||
<button
|
||||
{...props}
|
||||
type={nativeType}
|
||||
class:is-inverted={inverted}
|
||||
class:is-loading={loading}
|
||||
class:is-outlined={outlined}
|
||||
class:is-rounded={rounded}
|
||||
on:click>
|
||||
{#if iconLeft}
|
||||
<Icon pack={iconPack} icon={iconLeft} size={iconSize} />
|
||||
{/if}
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
{#if iconRight}
|
||||
<Icon pack={iconPack} icon={iconRight} size={iconSize} />
|
||||
{/if}
|
||||
</button>
|
||||
{:else if tag === 'a'}
|
||||
<a
|
||||
{href}
|
||||
{...props}
|
||||
class:is-inverted={inverted}
|
||||
class:is-loading={loading}
|
||||
class:is-outlined={outlined}
|
||||
class:is-rounded={rounded}
|
||||
on:click>
|
||||
{#if iconLeft}
|
||||
<Icon pack={iconPack} icon={iconLeft} size={iconSize} />
|
||||
{/if}
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
{#if iconRight}
|
||||
<Icon pack={iconPack} icon={iconRight} size={iconSize} />
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
|
@ -0,0 +1,32 @@
|
|||
<script>
|
||||
import * as transitions from 'svelte/transition'
|
||||
|
||||
/** Whether the Collapse is open or not
|
||||
* @svelte-prop {boolean} open=true
|
||||
* */
|
||||
export let open = true
|
||||
|
||||
/** Animation to use when opening/closing
|
||||
* @svelte-prop {String} animation=slide
|
||||
* @values Any animation that ships with Svelte
|
||||
* */
|
||||
export let animation = 'slide'
|
||||
|
||||
let _animation = transitions[animation]
|
||||
$: _animation = typeof animation === 'function' ? animation : transitions[animation]
|
||||
|
||||
function toggle() {
|
||||
open = !open
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="collapse">
|
||||
<div class="collapse-trigger" on:click={toggle}>
|
||||
<slot name="trigger" />
|
||||
</div>
|
||||
{#if open}
|
||||
<div class="collapse-content" transition:_animation|local>
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
|
@ -0,0 +1,242 @@
|
|||
<script>
|
||||
import { setContext, getContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
import MonthView from './View/MonthView.svelte'
|
||||
import YearView from './View/YearView.svelte'
|
||||
import DecadeYearView from './View/DecadeYearView.svelte'
|
||||
import Selector from './Selector/Selector.svelte'
|
||||
|
||||
import { obtainWeeks } from './main.js'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let width = '100%'
|
||||
export let nowDate = new Date()
|
||||
export let i18n = 'ZH'
|
||||
|
||||
export let markDate = []
|
||||
|
||||
export let disableDate = []
|
||||
|
||||
export let disableDateRule = 'piecemeal'
|
||||
|
||||
export let date = nowDate.getTime()
|
||||
|
||||
export let pickerRule = 'singleChoice'
|
||||
|
||||
export let align = "left";
|
||||
let left;
|
||||
$: {
|
||||
if(align === 'center'){
|
||||
left = 'calc(50% - 150px)';
|
||||
}else if(align === 'right'){
|
||||
left = 'calc(100% - 300px)'
|
||||
}else{
|
||||
left = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let pickerResult = []
|
||||
|
||||
if (pickerRule === 'singleChoice') {
|
||||
const dt = new Date(Number(date))
|
||||
pickerResult = dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate()
|
||||
}
|
||||
if (pickerRule === 'freeChoice') {
|
||||
const dts = []
|
||||
if (typeof date === 'number' || typeof date === 'string') {
|
||||
date = [date]
|
||||
}
|
||||
for (let v of date) {
|
||||
const dt = new Date(Number(v))
|
||||
const pr = dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate()
|
||||
dts.push(pr)
|
||||
}
|
||||
pickerResult = dts
|
||||
}
|
||||
if (pickerRule === 'rangeChoice') {
|
||||
if (typeof date === 'number' || typeof date === 'string') {
|
||||
date = [{ start: date }, { end: date }]
|
||||
}
|
||||
const sdt = new Date(Number(date[0].start))
|
||||
const edt = new Date(Number(date[1].end))
|
||||
const spr = sdt.getFullYear() + '-' + (sdt.getMonth() + 1) + '-' + sdt.getDate()
|
||||
const epr = edt.getFullYear() + '-' + (edt.getMonth() + 1) + '-' + edt.getDate()
|
||||
|
||||
pickerResult = [{ start: spr }, { end: epr }]
|
||||
}
|
||||
|
||||
//主题
|
||||
export let theme = 'light'
|
||||
|
||||
export let calendar = false
|
||||
let visible = calendar ? true : false
|
||||
|
||||
if (theme !== 'light' && theme !== 'dark') {
|
||||
throw new RangeError(`Unexpected value.[ErrorPlace]:Datepicker.porps.theme.`)
|
||||
}
|
||||
if (i18n !== 'EN' && i18n !== 'ZH') {
|
||||
throw new RangeError(`Unexpected value.[ErrorPlace]:Datepicker.porps.i18n.`)
|
||||
}
|
||||
if (disableDateRule !== 'piecemeal' && disableDateRule !== 'range') {
|
||||
throw new RangeError(`Unexpected value.[ErrorPlace]:Datepicker.porps.disableDateRule.`)
|
||||
}
|
||||
if (pickerRule !== 'singleChoice' && pickerRule !== 'freeChoice' && pickerRule !== 'rangeChoice') {
|
||||
throw new RangeError(`Unexpected value.[ErrorPlace]:Datepicker.porps.pickerRule.`)
|
||||
}
|
||||
//Initialize to the store
|
||||
const viewDate = writable(1)
|
||||
const viewMonth = writable(1)
|
||||
const viewYear = writable(1920)
|
||||
const thisView = writable('m') //This month:'m' ,this year:'y',ten years:'d'
|
||||
|
||||
//Bind to context
|
||||
setContext('theme', theme)
|
||||
setContext('nowDate', nowDate)
|
||||
setContext('i18n', i18n)
|
||||
setContext('viewMonth', nowDate.getMonth() + 1)
|
||||
setContext('thisView', thisView)
|
||||
setContext('viewYear', viewYear)
|
||||
setContext('viewMonth', viewMonth)
|
||||
setContext('viewDate', viewDate)
|
||||
setContext('markDate', markDate)
|
||||
setContext('disableDate', disableDate)
|
||||
setContext('disableDateRule', disableDateRule)
|
||||
setContext('pickerRule', pickerRule)
|
||||
|
||||
//Reacquire
|
||||
let view = getContext('thisView')
|
||||
let _year = getContext('viewYear')
|
||||
let _month = getContext('viewMonth')
|
||||
let _date = getContext('viewDate')
|
||||
|
||||
//Reassign
|
||||
$_year = nowDate.getFullYear()
|
||||
$_month = nowDate.getMonth() + 1
|
||||
$_date = nowDate.getDate()
|
||||
|
||||
//Obtain weeks
|
||||
$: theFirstWeek = obtainWeeks($_year, $_month, $_date).theFirstWeek
|
||||
$: theSecondWeek = obtainWeeks($_year, $_month, $_date).theSecondWeek
|
||||
$: theThirdWeek = obtainWeeks($_year, $_month, $_date).theThirdWeek
|
||||
$: theFourthWeek = obtainWeeks($_year, $_month, $_date).theFourthWeek
|
||||
$: fifthWeek = obtainWeeks($_year, $_month, $_date).fifthWeek
|
||||
$: sixthWeek = obtainWeeks($_year, $_month, $_date).sixthWeek
|
||||
|
||||
function checked(e) {
|
||||
date = e.detail.timeStamp
|
||||
dispatch('dateChecked', e.detail)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.calendar_light,
|
||||
.calendar_dark {
|
||||
background-color: #ffffff;
|
||||
/* width: 100%; */
|
||||
height: 245px;
|
||||
/* padding: 8px 6px 8px 6px; */
|
||||
/* margin: 5px; */
|
||||
border: 1px solid #ededf0;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 1px #ededf0;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.calendar_dark {
|
||||
background-color: #141416;
|
||||
border: 1px solid #0f1126;
|
||||
box-shadow: 0px 1px #0f1126;
|
||||
}
|
||||
|
||||
.dp-input {
|
||||
margin: 5px 0 0 0;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.date-icon {
|
||||
height: 40px;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 10px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.range-input {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.range-input.left,
|
||||
.range-input.left:focus,
|
||||
.range-input.left:active {
|
||||
border-right: 0;
|
||||
box-shadow: none !important;
|
||||
/* float: left; */
|
||||
}
|
||||
|
||||
.range-input.right,
|
||||
.range-input.right:focus,
|
||||
.range-input.right:active {
|
||||
border-left: 0;
|
||||
box-shadow: none !important;
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="width: {width};position: relative">
|
||||
{#if !calendar}
|
||||
{#if pickerRule === 'rangeChoice'}
|
||||
<div
|
||||
style="position: relative;"
|
||||
on:click={() => {
|
||||
visible = !visible
|
||||
}}>
|
||||
<input class="dp-input input is-primary range-input left" type="text" value={pickerResult[0].start} readonly />
|
||||
<span class="fa fa-calendar date-icon" />
|
||||
<input class="dp-input input is-primary range-input right" type="text" value={pickerResult[1].end} readonly />
|
||||
<span class="fa fa-chevron-right date-icon" style="left: calc(50% - 5px);" />
|
||||
</div>
|
||||
{:else}
|
||||
<div style="position: relative;">
|
||||
<input
|
||||
class="dp-input input is-primary"
|
||||
type="text"
|
||||
value={pickerResult}
|
||||
readonly
|
||||
on:click={() => {
|
||||
visible = !visible
|
||||
}} />
|
||||
<span class="fa fa-calendar date-icon" />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if visible || calendar}
|
||||
<div class={'calendar_' + theme} style="left: {left}">
|
||||
<Selector />
|
||||
{#if $view === 'y'}
|
||||
<YearView />
|
||||
{:else if $view === 'm'}
|
||||
<MonthView
|
||||
{theFirstWeek}
|
||||
{theSecondWeek}
|
||||
{theThirdWeek}
|
||||
{theFourthWeek}
|
||||
{fifthWeek}
|
||||
{sixthWeek}
|
||||
on:checked={checked}
|
||||
bind:result={pickerResult} />
|
||||
{:else if $view === 'd'}
|
||||
<DecadeYearView />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
|
@ -0,0 +1,232 @@
|
|||
<script>
|
||||
import { getContext, beforeUpdate } from "svelte";
|
||||
|
||||
export let date;
|
||||
export let result;
|
||||
export let isChosen;
|
||||
|
||||
let chosen;
|
||||
let getDate = getContext("nowDate");
|
||||
let pickerRule = getContext("pickerRule");
|
||||
let theme = getContext("theme");
|
||||
|
||||
$: nowMonth = getDate.getMonth() + 1;
|
||||
$: nowYear = getDate.getFullYear();
|
||||
$: nowDay = getDate.getDate();
|
||||
|
||||
function hasChosen(date) {
|
||||
let _date = date.year + "-" + date.month + "-" + date.day;
|
||||
if (pickerRule === "singleChoice") {
|
||||
return result == _date ? (chosen = "isChosen_" + theme) : (chosen = "");
|
||||
} else if (pickerRule === "freeChoice") {
|
||||
let r = new Set(result);
|
||||
return r.has(_date) ? (chosen = "isFreeChosen_" + theme) : (chosen = "");
|
||||
} else if (pickerRule === "rangeChoice") {
|
||||
isStartOrEnd(_date);
|
||||
}
|
||||
}
|
||||
|
||||
let start = "";
|
||||
let end = "";
|
||||
function isStartOrEnd(arr) {
|
||||
if (result.length === 0) {
|
||||
return;
|
||||
}
|
||||
switch (+parseDate(arr)) {
|
||||
case result[0].start:
|
||||
start = "startChosen_" + theme;
|
||||
break;
|
||||
case result[1].end:
|
||||
end = "endChosen_" + theme;
|
||||
break;
|
||||
default:
|
||||
start = "";
|
||||
end = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
function parseDate(str) {
|
||||
var mdy = str.split("-");
|
||||
return new Date(mdy[0], mdy[1] - 1, mdy[2]);
|
||||
}
|
||||
|
||||
function datediff(first, second) {
|
||||
return Math.round((second - first) / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
beforeUpdate(() => {
|
||||
hasChosen(date);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div
|
||||
class="{date.day == nowDay && date.month == nowMonth && date.year == nowYear ? 'today' : ''}
|
||||
{chosen}
|
||||
{isChosen}
|
||||
{start}
|
||||
{end}
|
||||
">
|
||||
{date.day}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
td, .endChosen_dark, .endChosen_light,.startChosen_dark, .startChosen_light, .selected_dark, .selected_light, .isFreeChosen_dark,.isFreeChosen_light, .isChosen_dark, .isChosen_light,.th_dark, .th_light {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: #b1b1b3;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.endChosen_dark:hover, .endChosen_light:hover, .startChosen_dark:hover, .startChosen_light:hover, .selected_dark:hover, .selected_light:hover, .isFreeChosen_dark:hover, .isFreeChosen_light:hover, .isChosen_dark:hover, .isChosen_light:hover, .th_dark:hover, .th_light:hover {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dark{
|
||||
color: #737373;
|
||||
}
|
||||
.dark:hover{
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.today {
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
position: relative;
|
||||
}
|
||||
.today::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0;
|
||||
width: 39px;
|
||||
border: 1.6px solid #0060df;
|
||||
border-radius: 0.8px;
|
||||
}
|
||||
|
||||
.markDate_light, .markDate_dark {
|
||||
position: relative;
|
||||
}
|
||||
.markDate_light::before, .markDate_dark::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 3.2px;
|
||||
left: 47%;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 1.5px;
|
||||
background-color: #0060df;
|
||||
}
|
||||
|
||||
.markDate_dark::before {
|
||||
background-color: #45a1ff;
|
||||
}
|
||||
|
||||
.isChosen_light {
|
||||
background-color: #002275;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.isChosen_light:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isChosen_dark {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.isChosen_dark:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isFreeChosen_light {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
.isFreeChosen_light:hover {
|
||||
background-color: #45a1ff;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isFreeChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
.isFreeChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.selected_light {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
.selected_light:hover {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
|
||||
.selected_dark {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #f9f9fa;
|
||||
}
|
||||
.selected_dark:hover {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.startChosen_light {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.startChosen_light:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.startChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.startChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.endChosen_light {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
.endChosen_light:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.endChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
.endChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,76 @@
|
|||
<script>
|
||||
import { getContext } from "svelte";
|
||||
//i18N
|
||||
let i18n = getContext("i18n");
|
||||
let theme = getContext("theme");
|
||||
|
||||
const WEEK_NAME = {
|
||||
EN: [
|
||||
{ id: 1, name: "MON" },
|
||||
{ id: 2, name: "TUE" },
|
||||
{ id: 3, name: "WED" },
|
||||
{ id: 4, name: "THU" },
|
||||
{ id: 5, name: "FRI" },
|
||||
{ id: 6, name: "SAT" },
|
||||
{ id: 7, name: "SUN" }
|
||||
],
|
||||
ZH: [
|
||||
{ id: 1, name: "一" },
|
||||
{ id: 2, name: "二" },
|
||||
{ id: 3, name: "三" },
|
||||
{ id: 4, name: "四" },
|
||||
{ id: 5, name: "五" },
|
||||
{ id: 6, name: "六" },
|
||||
{ id: 7, name: "日" }
|
||||
]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
thead {
|
||||
padding: 0;
|
||||
width: 301px;
|
||||
}
|
||||
tr {
|
||||
padding: 0;
|
||||
}
|
||||
.th_dark,
|
||||
.th_light {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: #1d8ef1;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
th {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.th_light:hover {
|
||||
background: none;
|
||||
color: #0c0c0d;
|
||||
}
|
||||
|
||||
.th_dark {
|
||||
color: #4a4a4f;
|
||||
}
|
||||
.th_dark:hover {
|
||||
background: none;
|
||||
color: rgb(207, 207, 207);
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
{#each WEEK_NAME[i18n] as item}
|
||||
<th class={'th_' + theme}>{item.name}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
<script>
|
||||
import {getContext} from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
|
||||
const MONTH_NAME = {
|
||||
EN:[{id:1,name:"January"},{id:2,name:"February"},{id:3,name:"March"},
|
||||
{id:4,name:"April"},{id:5,name:"May"},{id:6,name:"June"},
|
||||
{id:7,name:"July"},{id:8,name:"August"},{id:9,name:"September"},
|
||||
{id:10,name:"October"},{id:11,name:"November"},{id:12,name:"December"}],
|
||||
ZH:[{id:1,name:"一月"},{id:2,name:"二月"},{id:3,name:"三月"},
|
||||
{id:4,name:"四月"},{id:5,name:"五月"},{id:6,name:"六月"},
|
||||
{id:7,name:"七月"},{id:8,name:"八月"},{id:9,name:"九月"},
|
||||
{id:10,name:"十月"},{id:11,name:"十一月"},{id:12,name:"十二月"}]
|
||||
}
|
||||
|
||||
let i18n = getContext('i18n');
|
||||
|
||||
let viewMonth = getContext('viewMonth')
|
||||
let viewYear = getContext('viewYear')
|
||||
let thisView = getContext('thisView')
|
||||
let theme = getContext('theme')
|
||||
|
||||
$:monthName=i18n==='ZH'? $viewYear+"年 "+MONTH_NAME[i18n][$viewMonth-1].name: MONTH_NAME[i18n][$viewMonth-1].name+" "+$viewYear;
|
||||
|
||||
//切换视图
|
||||
function switchView (){
|
||||
if($thisView==='m'){
|
||||
$thisView='y'
|
||||
}else if($thisView==='y'){
|
||||
$thisView='d'
|
||||
}else if($thisView==='d'){
|
||||
$thisView='m'
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<div class="{'monthTitle_'+theme}" on:click={switchView} >
|
||||
<div class="titleBox">
|
||||
{#if $thisView==='m'}
|
||||
<div class="monthTitle" transition:fly="{{ y: -20, opacity: 0.2,duration: 200 ,easing: quintOut }}">
|
||||
{monthName}
|
||||
</div>
|
||||
{:else if $thisView==='y'}
|
||||
<div class="monthTitle" transition:fly="{{ y: 20, opacity: 0.2,duration: 200 ,easing: quintOut}}">
|
||||
{$viewYear}
|
||||
</div>
|
||||
{:else if $thisView==='d'}
|
||||
<div class="monthTitle" transition:fly="{{ y: -20, opacity: 0.2,duration: 200 ,easing: quintOut}}">
|
||||
{$viewYear}-{$viewYear+11}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
|
||||
.monthTitle_light, .monthTitle_dark {
|
||||
width: 60%;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
color: #0c0c0d;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
}
|
||||
.monthTitle_light:hover, .monthTitle_dark:hover {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.monthTitle_dark {
|
||||
color: #d7d7db;
|
||||
}
|
||||
.monthTitle_dark:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.titleBox {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monthTitle {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
let view = getContext("thisView");
|
||||
let viewYear = getContext("viewYear");
|
||||
let viewMonth = getContext("viewMonth");
|
||||
let theme = getContext("theme");
|
||||
|
||||
function nextClick() {
|
||||
switch ($view) {
|
||||
case "m":
|
||||
if ($viewMonth === 12) {
|
||||
$viewMonth = 1;
|
||||
$viewYear = $viewYear + 1;
|
||||
} else {
|
||||
$viewMonth = $viewMonth + 1;
|
||||
}
|
||||
break;
|
||||
case "y":
|
||||
$viewYear = $viewYear + 1;
|
||||
break;
|
||||
case "d":
|
||||
$viewYear = $viewYear + 11;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.next_light, .next_dark {
|
||||
width: 20%;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
stroke: #b1b1b3;
|
||||
cursor: pointer;
|
||||
}
|
||||
.next_light:hover{
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
stroke: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.next_dark {
|
||||
stroke: #4a4a4f;
|
||||
}
|
||||
.next_dark:hover {
|
||||
background-color: #003eaa;
|
||||
stroke: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class={'next_' + theme} on:click={nextClick}>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' width='20' height='30' viewBox='0 0 512 512' style="display: inline-block;"><polyline points='184 112 328 256 184 400' style='fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:48px'/></svg>
|
||||
</div>
|
|
@ -0,0 +1,53 @@
|
|||
<script>
|
||||
import {getContext} from 'svelte'
|
||||
|
||||
let viewYear = getContext('viewYear')
|
||||
let viewMonth = getContext('viewMonth')
|
||||
|
||||
let view = getContext('thisView')
|
||||
let theme = getContext('theme')
|
||||
function prevClick(){
|
||||
if($view==='m'){
|
||||
if($viewMonth===1){
|
||||
$viewMonth=12
|
||||
$viewYear=$viewYear-1
|
||||
}else{
|
||||
$viewMonth= $viewMonth-1
|
||||
}
|
||||
}else if($view === 'y'){
|
||||
$viewYear = $viewYear-1
|
||||
}else if($view === 'd'){
|
||||
$viewYear = $viewYear-11
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="{'prev_'+theme}"
|
||||
on:click={prevClick}>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' width='20' height='30' viewBox='0 0 512 512' style="display: inline-block;"><polyline points='328 112 184 256 328 400' style='fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:48px'/></svg>
|
||||
</div>
|
||||
|
||||
<style >
|
||||
.prev_light, .prev_dark{
|
||||
width: 20%;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
stroke: #b1b1b3;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.prev_light:hover, .prev_dark:hover {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
stroke: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.prev_dark{
|
||||
stroke: #4a4a4f;
|
||||
}
|
||||
.prev_dark:hover {
|
||||
background-color: #003eaa;
|
||||
stroke: #f9f9fa;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
<script>
|
||||
import MonthTitle from './MonthTitle.svelte';
|
||||
import Prev from './Prev.svelte';
|
||||
import Next from './Next.svelte';
|
||||
</script>
|
||||
|
||||
<div class="header">
|
||||
<Prev />
|
||||
<MonthTitle />
|
||||
<Next/>
|
||||
</div>
|
||||
|
||||
<style >
|
||||
.header {
|
||||
display: flex;
|
||||
width: 301px;
|
||||
height: 30px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<script>
|
||||
import { getContext } from "svelte";
|
||||
import { scale } from "svelte/transition";
|
||||
import { quintOut } from "svelte/easing";
|
||||
|
||||
let viewYear = getContext("viewYear");
|
||||
let thisView = getContext("thisView");
|
||||
let theme = getContext("theme");
|
||||
|
||||
function updateYear(e) {
|
||||
$viewYear = +e.target.innerText;
|
||||
$thisView = "y";
|
||||
}
|
||||
</script>
|
||||
|
||||
<table
|
||||
transition:scale={{ duration: 100, delay: 100, opacity: 0.1, start: 0.5, easing: quintOut }}>
|
||||
<tbody>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td on:click={updateYear}>{$viewYear}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 1}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 2}</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td on:click={updateYear}>{$viewYear + 3}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 4}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 5}</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td on:click={updateYear}>{$viewYear + 6}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 7}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 8}</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td on:click={updateYear}>{$viewYear + 9}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 10}</td>
|
||||
<td on:click={updateYear}>{$viewYear + 11}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style >
|
||||
|
||||
table {
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
position: absolute;
|
||||
width: 301px;
|
||||
}
|
||||
|
||||
|
||||
tbody {
|
||||
padding: 0;
|
||||
width: 301px;
|
||||
}
|
||||
|
||||
tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td, .YearView_light td, .YearView_dark td, .YearView_light .th_light, .YearView_light .th_dark, .th_dark, .th_light {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: #b1b1b3;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
td:hover{
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dark{
|
||||
color: #737373;
|
||||
}
|
||||
.dark:hover{
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.YearView_light, .YearView_dark {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
.YearView_light td, .YearView_dark td, .YearView_dark .endChosen_dark, .YearView_dark .endChosen_light, .YearView_dark .startChosen_dark, .YearView_dark .startChosen_light, .YearView_dark .selected_dark, .YearView_dark .selected_light, .YearView_dark .isFreeChosen_dark, .YearView_dark .isFreeChosen_light, .YearView_dark .isChosen_dark, .YearView_dark .isChosen_light, .YearView_light .th_light, .YearView_dark .th_light, .YearView_light .th_dark, .YearView_dark .th_dark {
|
||||
color: #0c0c0d;
|
||||
width: 32%;
|
||||
height: 52.5px;
|
||||
line-height: 52.5px;
|
||||
}
|
||||
|
||||
.YearView_dark td, .YearView_dark .endChosen_dark, .YearView_dark .endChosen_light, .YearView_dark .startChosen_dark, .YearView_dark .startChosen_light, .YearView_dark .selected_dark, .YearView_dark .selected_light, .YearView_dark .isFreeChosen_dark, .YearView_dark .isFreeChosen_light, .YearView_dark .isChosen_dark, .YearView_dark .isChosen_light, .YearView_dark .th_light, .YearView_dark .th_dark {
|
||||
color: #ededf0;
|
||||
}
|
||||
.YearView_dark td:hover, .YearView_dark .endChosen_dark:hover, .YearView_dark .endChosen_light:hover, .YearView_dark .startChosen_dark:hover, .YearView_dark .startChosen_light:hover, .YearView_dark .selected_dark:hover, .YearView_dark .selected_light:hover, .YearView_dark .isFreeChosen_dark:hover, .YearView_dark .isFreeChosen_light:hover, .YearView_dark .isChosen_dark:hover, .YearView_dark .isChosen_light:hover, .YearView_dark .th_light:hover, .YearView_dark .th_dark:hover {
|
||||
background-color: #003eaa;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,420 @@
|
|||
<script>
|
||||
import { getContext } from 'svelte'
|
||||
import { scale } from 'svelte/transition'
|
||||
import { quintOut } from 'svelte/easing'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
import WeekTitle from '../Month/WeekTitle.svelte'
|
||||
import Day from '../Month/Day.svelte'
|
||||
|
||||
export let theFirstWeek
|
||||
export let theSecondWeek
|
||||
export let theThirdWeek
|
||||
export let theFourthWeek
|
||||
export let fifthWeek
|
||||
export let sixthWeek
|
||||
export let result
|
||||
|
||||
let array = []
|
||||
$: {
|
||||
array[0] = theFirstWeek
|
||||
array[1] = theSecondWeek
|
||||
array[2] = theThirdWeek
|
||||
array[3] = theFourthWeek
|
||||
array[4] = fifthWeek
|
||||
array[5] = sixthWeek
|
||||
}
|
||||
|
||||
const TODAY_NAME = {
|
||||
EN: 'today',
|
||||
ZH: '今天',
|
||||
}
|
||||
|
||||
//判断周末
|
||||
function isSatOrSun(arr) {
|
||||
let _date = arr.year + '-' + arr.month + '-' + arr.day
|
||||
let d = new Date(Date.parse(_date.replace(/\-/g, '/'))).getDay()
|
||||
return d === 6 || d === 0 ? true : false
|
||||
}
|
||||
|
||||
//是否被标记
|
||||
function isMark(arr) {
|
||||
let _date = arr.year + '-' + arr.month + '-' + arr.day
|
||||
let markDate = new Set(primaevalMarkDate)
|
||||
return markDate.has(_date)
|
||||
}
|
||||
|
||||
//是否被禁用
|
||||
function isDisableDate(arr) {
|
||||
if (disableDateRule === 'piecemeal') {
|
||||
let _date = arr.year + '-' + arr.month + '-' + arr.day
|
||||
let _disableDate = new Set(disableDate)
|
||||
return _disableDate.has(_date)
|
||||
} else if (disableDateRule === 'range') {
|
||||
let _date = arr.year + '-' + arr.month + '-' + arr.day
|
||||
let dateNum = datediff(parseDate(disableDate[0].start), parseDate(disableDate[1].end))
|
||||
let startDateNum = datediff(parseDate(_date), parseDate(disableDate[0].start))
|
||||
let endDateNum = datediff(parseDate(_date), parseDate(disableDate[1].end))
|
||||
if (startDateNum > 0 || endDateNum < 0) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseDate(str) {
|
||||
var mdy = str.split('-')
|
||||
return new Date(mdy[0], mdy[1] - 1, mdy[2])
|
||||
}
|
||||
|
||||
function datediff(first, second) {
|
||||
return Math.round((second - first) / (1000 * 60 * 60 * 24))
|
||||
}
|
||||
|
||||
let i18n = getContext('i18n')
|
||||
let theme = getContext('theme')
|
||||
let pickerRule = getContext('pickerRule')
|
||||
|
||||
let viewMonth = getContext('viewMonth')
|
||||
let primaevalMarkDate = getContext('markDate')
|
||||
let disableDate = getContext('disableDate')
|
||||
let disableDateRule = getContext('disableDateRule')
|
||||
let getDate = getContext('nowDate')
|
||||
let thisView = getContext('thisView')
|
||||
|
||||
$: nowMonth = getDate.getMonth() + 1
|
||||
$: nowYear = getDate.getFullYear()
|
||||
$: nowDay = getDate.getDate()
|
||||
|
||||
function handleClick(date) {
|
||||
let _date = date.year + '-' + date.month + '-' + date.day
|
||||
let times = []
|
||||
switch (pickerRule) {
|
||||
case 'freeChoice':
|
||||
let r = new Set(result)
|
||||
if (r.has(_date)) {
|
||||
r.delete(_date)
|
||||
result = [...new Set(r)]
|
||||
} else {
|
||||
result = [...result, _date]
|
||||
}
|
||||
for (let v of result) {
|
||||
times.push(+parseDate(v))
|
||||
}
|
||||
// dispatch('dateChecked', {
|
||||
// time: result,
|
||||
// timeStamp: times
|
||||
// })
|
||||
break
|
||||
case 'rangeChoice':
|
||||
if (result.length === 0) {
|
||||
result = [{ start: 0 }, { end: 0 }]
|
||||
result[0].start = _date
|
||||
result[1].end = _date
|
||||
} else if (+parseDate(_date) > +parseDate(result[1].end)) {
|
||||
result[1].end = _date
|
||||
} else if (+parseDate(_date) === +parseDate(result[0].start)) {
|
||||
result[1].end = _date
|
||||
} else if (+parseDate(_date) < +parseDate(result[1].end)) {
|
||||
result[0].start = _date
|
||||
}
|
||||
|
||||
times.push({ start: +parseDate(result[0].start) })
|
||||
times.push({ end: +parseDate(result[1].end) })
|
||||
// dispatch('dateChecked', {
|
||||
// time: result,
|
||||
// timeStamp: times
|
||||
// })
|
||||
break
|
||||
default:
|
||||
if (result !== _date) {
|
||||
result = _date
|
||||
times = +parseDate(_date)
|
||||
} else if (result === _date) {
|
||||
result = []
|
||||
}
|
||||
}
|
||||
|
||||
if ((result.length !== 0)) {
|
||||
dispatch('checked', { time: result, timeStamp: times })
|
||||
|
||||
} else {
|
||||
dispatch('checked', '')
|
||||
}
|
||||
|
||||
array = array
|
||||
}
|
||||
|
||||
function isChosen(arr) {
|
||||
let _date = arr.year + '-' + arr.month + '-' + arr.day
|
||||
if (pickerRule === 'rangeChoice') {
|
||||
if (result.length === 0) {
|
||||
return
|
||||
}
|
||||
let dateNum = datediff(new Date(result[0].start), new Date(result[1].end))
|
||||
let startDateNum = datediff(parseDate(_date), new Date(result[0].start))
|
||||
let endDateNum = datediff(parseDate(_date), new Date(result[1].end))
|
||||
|
||||
if (startDateNum > 0 || endDateNum < 0 || result[0].start === 0) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
table {
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
/* position: absolute; */
|
||||
width: 300px;
|
||||
left: -1px;
|
||||
}
|
||||
tbody {
|
||||
padding: 0;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
.endChosen_dark,
|
||||
.YearView_light .endChosen_dark,
|
||||
.endChosen_light,
|
||||
.YearView_light .endChosen_light,
|
||||
.startChosen_dark,
|
||||
.YearView_light .startChosen_dark,
|
||||
.startChosen_light,
|
||||
.YearView_light .startChosen_light,
|
||||
.selected_dark,
|
||||
.YearView_light .selected_dark,
|
||||
.selected_light,
|
||||
.YearView_light .selected_light,
|
||||
.isFreeChosen_dark,
|
||||
.YearView_light .isFreeChosen_dark,
|
||||
.isFreeChosen_light,
|
||||
.YearView_light .isFreeChosen_light,
|
||||
.isChosen_dark,
|
||||
.YearView_light .isChosen_dark,
|
||||
.isChosen_light,
|
||||
.YearView_light .isChosen_light,
|
||||
.YearView_light td,
|
||||
.YearView_dark td,
|
||||
.YearView_light .th_light,
|
||||
.YearView_light .th_dark,
|
||||
.th_dark,
|
||||
.th_light {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: #b1b1b3;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
td:hover,
|
||||
.endChosen_dark:hover,
|
||||
.endChosen_light:hover,
|
||||
.startChosen_dark:hover,
|
||||
.startChosen_light:hover,
|
||||
.selected_dark:hover,
|
||||
.selected_light:hover,
|
||||
.isFreeChosen_dark:hover,
|
||||
.isFreeChosen_light:hover,
|
||||
.isChosen_dark:hover,
|
||||
.isChosen_light:hover,
|
||||
.th_dark:hover,
|
||||
.th_light:hover {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dark,
|
||||
.th_dark {
|
||||
color: #737373;
|
||||
}
|
||||
.dark:hover,
|
||||
.th_dark:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.isSatOrSun_light {
|
||||
background-color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isSatOrSun_dark {
|
||||
background-color: #0c0c0d;
|
||||
}
|
||||
|
||||
.thisMonth_light {
|
||||
color: #0c0c0d;
|
||||
}
|
||||
|
||||
.thisMonth_dark {
|
||||
color: #d7d7db;
|
||||
}
|
||||
|
||||
.disableDate_light {
|
||||
color: #d7d7db;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.disableDate_dark {
|
||||
color: #38383d;
|
||||
pointer-events: none;
|
||||
}
|
||||
.markDate_light,
|
||||
.markDate_dark {
|
||||
position: relative;
|
||||
}
|
||||
.markDate_light::before,
|
||||
.markDate_dark::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 3.2px;
|
||||
left: 47%;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 1.5px;
|
||||
background-color: #0060df;
|
||||
}
|
||||
|
||||
.markDate_dark::before {
|
||||
background-color: #45a1ff;
|
||||
}
|
||||
|
||||
.isChosen_light {
|
||||
background-color: #002275;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.isChosen_light:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isChosen_dark {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.isChosen_dark:hover {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isFreeChosen_light {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
.isFreeChosen_light:hover {
|
||||
background-color: #45a1ff;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.isFreeChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
.isFreeChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.selected_light {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
.selected_light:hover {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #0c0c0d;
|
||||
}
|
||||
|
||||
.selected_dark {
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #f9f9fa;
|
||||
}
|
||||
.selected_dark:hover {
|
||||
background-color: rgba(10, 132, 255, 0.3);
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.startChosen_light {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.startChosen_light:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.startChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.startChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.endChosen_light {
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
.endChosen_light:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
|
||||
.endChosen_dark {
|
||||
background-color: #0a84ff;
|
||||
color: #f9f9fa;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
.endChosen_dark:hover {
|
||||
background-color: #0060df;
|
||||
color: #f9f9fa;
|
||||
}
|
||||
</style>
|
||||
|
||||
<table transition:scale={{ duration: 100, delay: 100, opacity: 0.1, start: 0.5, easing: quintOut }}>
|
||||
<WeekTitle />
|
||||
<tbody>
|
||||
{#each array as Weeks}
|
||||
<tr>
|
||||
{#each Weeks as item, i}
|
||||
<td
|
||||
title={item.day == nowDay && item.month == nowMonth && item.year == nowYear ? TODAY_NAME[i18n] : ''}
|
||||
class="{theme}
|
||||
{(item.month === $viewMonth ? 'thisMonth_' : '') + theme}
|
||||
{(isSatOrSun(item) ? 'isSatOrSun_' : '') + theme}
|
||||
{(isMark(item) ? 'markDate_' : '') + theme}
|
||||
{(isDisableDate(item) ? 'disableDate_' : '') + theme}
|
||||
{isChosen(item) ? 'selected_' + theme : ''}
|
||||
"
|
||||
on:click={()=> handleClick(item)}>
|
||||
<Day date={item} {result} isChosen={isChosen(item) ? 'selected_' + theme : ''} />
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
|
@ -0,0 +1,158 @@
|
|||
<script>
|
||||
import { getContext } from "svelte";
|
||||
import { scale } from "svelte/transition";
|
||||
import { quintOut } from "svelte/easing";
|
||||
const MONTH_NAME = {
|
||||
EN: [
|
||||
{ id: 1, name: "January" },
|
||||
{ id: 2, name: "February" },
|
||||
{ id: 3, name: "March" },
|
||||
{ id: 4, name: "April" },
|
||||
{ id: 5, name: "May" },
|
||||
{ id: 6, name: "June" },
|
||||
{ id: 7, name: "July" },
|
||||
{ id: 8, name: "August" },
|
||||
{ id: 9, name: "September" },
|
||||
{ id: 10, name: "October" },
|
||||
{ id: 11, name: "November" },
|
||||
{ id: 12, name: "December" }
|
||||
],
|
||||
ZH: [
|
||||
{ id: 1, name: "一月" },
|
||||
{ id: 2, name: "二月" },
|
||||
{ id: 3, name: "三月" },
|
||||
{ id: 4, name: "四月" },
|
||||
{ id: 5, name: "五月" },
|
||||
{ id: 6, name: "六月" },
|
||||
{ id: 7, name: "七月" },
|
||||
{ id: 8, name: "八月" },
|
||||
{ id: 9, name: "九月" },
|
||||
{ id: 10, name: "十月" },
|
||||
{ id: 11, name: "十一月" },
|
||||
{ id: 12, name: "十二月" }
|
||||
]
|
||||
};
|
||||
|
||||
let i18n = getContext("i18n");
|
||||
let viewMonth = getContext("viewMonth");
|
||||
let thisView = getContext("thisView");
|
||||
let theme = getContext("theme");
|
||||
|
||||
function changeMonth(e) {
|
||||
$viewMonth = +e.target.id;
|
||||
$thisView = "m";
|
||||
}
|
||||
</script>
|
||||
<table
|
||||
transition:scale={{ duration: 100, delay: 100, opacity: 0.1, start: 0.5, easing: quintOut }}>
|
||||
<tbody>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td id={MONTH_NAME[i18n][0].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][0].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][1].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][1].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][2].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][2].name}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td id={MONTH_NAME[i18n][3].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][3].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][4].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][4].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][5].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][5].name}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td id={MONTH_NAME[i18n][6].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][6].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][7].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][7].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][8].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][8].name}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class={'YearView_' + theme}>
|
||||
<td id={MONTH_NAME[i18n][9].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][9].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][10].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][10].name}
|
||||
</td>
|
||||
<td id={MONTH_NAME[i18n][11].id} on:click={changeMonth}>
|
||||
{MONTH_NAME[i18n][11].name}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style >
|
||||
|
||||
table {
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
position: absolute;
|
||||
width: 301px;
|
||||
}
|
||||
|
||||
|
||||
tbody {
|
||||
padding: 0;
|
||||
width: 301px;
|
||||
}
|
||||
|
||||
tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td, .YearView_light td, .YearView_dark td, .YearView_light .th_light, .YearView_light .th_dark, .th_dark, .th_light {
|
||||
display: inline-flex;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
width: 42.8px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: #b1b1b3;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
td:hover{
|
||||
background-color: rgba(10, 132, 255, 0.1);
|
||||
color: #0c0c0d;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dark{
|
||||
color: #737373;
|
||||
}
|
||||
.dark:hover{
|
||||
background-color: #003eaa;
|
||||
color: #f9f9fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.YearView_light, .YearView_dark {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
.YearView_light td, .YearView_dark td, .YearView_dark .endChosen_dark, .YearView_dark .endChosen_light, .YearView_dark .startChosen_dark, .YearView_dark .startChosen_light, .YearView_dark .selected_dark, .YearView_dark .selected_light, .YearView_dark .isFreeChosen_dark, .YearView_dark .isFreeChosen_light, .YearView_dark .isChosen_dark, .YearView_dark .isChosen_light, .YearView_light .th_light, .YearView_dark .th_light, .YearView_light .th_dark, .YearView_dark .th_dark {
|
||||
color: #0c0c0d;
|
||||
width: 32%;
|
||||
height: 52.5px;
|
||||
line-height: 52.5px;
|
||||
}
|
||||
|
||||
.YearView_dark td, .YearView_dark .endChosen_dark, .YearView_dark .endChosen_light, .YearView_dark .startChosen_dark, .YearView_dark .startChosen_light, .YearView_dark .selected_dark, .YearView_dark .selected_light, .YearView_dark .isFreeChosen_dark, .YearView_dark .isFreeChosen_light, .YearView_dark .isChosen_dark, .YearView_dark .isChosen_light, .YearView_dark .th_light, .YearView_dark .th_dark {
|
||||
color: #ededf0;
|
||||
}
|
||||
.YearView_dark td:hover, .YearView_dark .endChosen_dark:hover, .YearView_dark .endChosen_light:hover, .YearView_dark .startChosen_dark:hover, .YearView_dark .startChosen_light:hover, .YearView_dark .selected_dark:hover, .YearView_dark .selected_light:hover, .YearView_dark .isFreeChosen_dark:hover, .YearView_dark .isFreeChosen_light:hover, .YearView_dark .isChosen_dark:hover, .YearView_dark .isChosen_light:hover, .YearView_dark .th_light:hover, .YearView_dark .th_dark:hover {
|
||||
background-color: #003eaa;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,206 @@
|
|||
//Is there a sixth week of the month
|
||||
let thisMonthHasSixthWeek = false;
|
||||
|
||||
//Solar month
|
||||
const SOLAR_MONTH = [1, 3, 5, 7, 8, 10, 12];
|
||||
|
||||
let thisDate;
|
||||
let thisMonthDays;
|
||||
let lastMonthOfYear;
|
||||
let lastMonth;
|
||||
let lastMonthDays;
|
||||
let monthFirstDayDay;
|
||||
let monthLastDayDay;
|
||||
let nextMonthOfYear;
|
||||
let nextMonth;
|
||||
|
||||
let theFirstWeek;
|
||||
let theSecondWeek;
|
||||
let theThirdWeek;
|
||||
let theFourthWeek;
|
||||
let fifthWeek;
|
||||
let sixthWeek;
|
||||
|
||||
let thisYear;
|
||||
let thisDay;
|
||||
let thisMonth;
|
||||
|
||||
export const obtainWeeks = function (y, m, d) {
|
||||
thisDay = d;
|
||||
thisYear = y;
|
||||
thisMonth = m;
|
||||
//当前日期
|
||||
thisDate = dayIsIt(thisDay);
|
||||
//当前月天数
|
||||
thisMonthDays = computeMonthDays(thisYear, thisMonth);
|
||||
//上月所在年份
|
||||
lastMonthOfYear = computeLastMonth(thisYear, thisMonth)[0];
|
||||
//上月所在月份
|
||||
lastMonth = computeLastMonth(thisYear, thisMonth)[1]
|
||||
//下个月所在年份
|
||||
nextMonthOfYear = computeNextMonth(thisYear, thisMonth)[0];
|
||||
//下个所在月份
|
||||
nextMonth = computeNextMonth(thisYear, thisMonth)[1]
|
||||
|
||||
//上月有几天
|
||||
lastMonthDays = computeMonthDays(lastMonthOfYear, lastMonth);
|
||||
//当月第一天是周几
|
||||
monthFirstDayDay = dayIsIt(1);
|
||||
//当月最后一天是周几
|
||||
monthLastDayDay = dayIsIt(thisMonthDays);
|
||||
|
||||
//第一周
|
||||
theFirstWeek = computeFirstWeek();
|
||||
|
||||
//第二周
|
||||
theSecondWeek = computeMidWeek(theFirstWeek[6].day + 1);
|
||||
|
||||
//第三周
|
||||
theThirdWeek = computeMidWeek(theSecondWeek[6].day + 1);
|
||||
|
||||
//第四周
|
||||
theFourthWeek = computeMidWeek(theThirdWeek[6].day + 1);
|
||||
|
||||
//第五周
|
||||
switch (true) {
|
||||
case (thisMonthDays - theFourthWeek[6].day) === 7:
|
||||
fifthWeek = computeLastWeek(theFourthWeek[6].day + 1);
|
||||
thisMonthHasSixthWeek = true;
|
||||
break;
|
||||
case (thisMonthDays - theFourthWeek[6].day) > 7:
|
||||
fifthWeek = computeMidWeek(theFourthWeek[6].day + 1);
|
||||
thisMonthHasSixthWeek = true;
|
||||
break;
|
||||
default:
|
||||
fifthWeek = computeLastWeek(theFourthWeek[6].day + 1)
|
||||
thisMonthHasSixthWeek = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//第六周
|
||||
sixthWeek = thisMonthHasSixthWeek
|
||||
? computeLastWeek(fifthWeek[6].day + 1)
|
||||
: computeMidWeek(fifthWeek[6].day + 1, true);
|
||||
return {
|
||||
theFirstWeek,
|
||||
theSecondWeek,
|
||||
theThirdWeek,
|
||||
theFourthWeek,
|
||||
fifthWeek,
|
||||
sixthWeek
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//判断大月
|
||||
const isSolarMonth = function (m) { return !!~SOLAR_MONTH.indexOf(m) }
|
||||
|
||||
//判断闰年
|
||||
const isLeapYear = function (y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 }
|
||||
|
||||
//计算是周几
|
||||
const dayIsIt = function (n) {
|
||||
let _date = thisYear + '-' + thisMonth + '-' + n;
|
||||
let d = new Date(Date.parse(_date.replace(/\-/g, "/"))).getDay();
|
||||
return d === 0 ? 7 : d;
|
||||
}
|
||||
|
||||
//判断某个月有几天
|
||||
const computeMonthDays = function(y, m) {
|
||||
let d = NaN;
|
||||
if (isLeapYear(y) && m === 2) { d = 29; }
|
||||
else if (m === 2) { d = 28; }
|
||||
else if (isSolarMonth(m)) { d = 31; }
|
||||
else { d = 30; }
|
||||
return d;
|
||||
}
|
||||
|
||||
//计算上个月和上个月所在的年份
|
||||
const computeLastMonth = function(y, m) {
|
||||
let ly = NaN;
|
||||
let lm = NaN;
|
||||
if (m !== 1) { lm = m - 1; ly = y }
|
||||
else { lm = 12; ly = y - 1 }
|
||||
return [ly, lm]
|
||||
}
|
||||
|
||||
//计算下个月和下个月所在的年份
|
||||
const computeNextMonth = function(y, m) {
|
||||
let ny = NaN;
|
||||
let nm = NaN;
|
||||
if (m !== 12) { nm = m + 1; ny = y }
|
||||
else { nm = 1; ny = y + 1 }
|
||||
return [ny, nm]
|
||||
}
|
||||
|
||||
//计算当月首周
|
||||
const computeFirstWeek = function() {
|
||||
let array = [];
|
||||
array.length = 7;
|
||||
let i = 8 - monthFirstDayDay
|
||||
let times = monthFirstDayDay - 2
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
array[index] = {
|
||||
"year": lastMonthOfYear == thisYear ? thisYear : thisYear - 1,
|
||||
"month": thisMonth == 1 ? 12 : thisMonth - 1,
|
||||
"day": lastMonthDays - times
|
||||
};
|
||||
times--
|
||||
}
|
||||
for (let index = 0; index < i; index++) {
|
||||
array[(7 - i) + index] = {
|
||||
"year": thisYear,
|
||||
"month": thisMonth,
|
||||
"day": index + 1
|
||||
};
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
|
||||
//计算其他周
|
||||
const computeMidWeek = function(d, s) {
|
||||
let array = [];
|
||||
array.length = 7;
|
||||
if(s && thisMonth==12){
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
array[index] = {
|
||||
"year": thisYear+1,
|
||||
"month": 1,
|
||||
"day": d + index
|
||||
};
|
||||
}
|
||||
}else{
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
array[index] = {
|
||||
"year": thisYear,
|
||||
"month": thisMonthHasSixthWeek === false && s ? thisMonth + 1 : thisMonth,
|
||||
"day": d + index
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
|
||||
//计算当月最后一周
|
||||
const computeLastWeek = function(d) {
|
||||
let array = [];
|
||||
let times = thisMonthDays - d + 1
|
||||
for (let index = 0; index < times; index++) {
|
||||
array[index] = {
|
||||
"year": thisYear,
|
||||
"month": thisMonth,
|
||||
"day": d + index
|
||||
}
|
||||
}
|
||||
for (let index = 0; index < 7 - times; index++) {
|
||||
array[times + index] = {
|
||||
"year": nextMonthOfYear == thisYear ? thisYear : thisYear + 1,
|
||||
"month": nextMonth == 1 ? 1 : thisMonth + 1,
|
||||
"day": index + 1
|
||||
};
|
||||
}
|
||||
array.length = 7;
|
||||
return array
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
<script>
|
||||
import { createEventDispatcher, onDestroy, onMount, tick } from 'svelte'
|
||||
import Icon from '../Icon.svelte'
|
||||
import { chooseAnimation, isEnterKey, isEscKey } from '../../utils'
|
||||
|
||||
/** Show a header on the dialog with this text
|
||||
* @svelte-prop {String} [message]
|
||||
* */
|
||||
export let title = ''
|
||||
|
||||
/** Text or html message for this dialog
|
||||
* @svelte-prop {String} message
|
||||
* */
|
||||
export let message
|
||||
|
||||
/** Text to show on the confirmation button
|
||||
* @svelte-prop {String} [confirmText=OK]
|
||||
* */
|
||||
export let confirmText = 'OK'
|
||||
|
||||
/** Text to show on the cancel button
|
||||
* @svelte-prop {String} [cancelText=Cancel]
|
||||
* */
|
||||
export let cancelText = 'Cancel'
|
||||
|
||||
/** Focus on confirm or cancel button when dialog opens
|
||||
* @svelte-prop {String} [focusOn=confirm]
|
||||
* @values <code>confirm</code>, <code>cancel</code>
|
||||
* */
|
||||
export let focusOn = 'confirm'
|
||||
|
||||
/** Show this icon on left-side of dialog. It will use the color from <code>type</code>
|
||||
* @svelte-prop {String} [icon]
|
||||
* */
|
||||
export let icon = ''
|
||||
|
||||
/** Fontawesome icon pack to use. By default the <code>Icon</code> component uses <code>fas</code>
|
||||
* @svelte-prop {String} [iconPack]
|
||||
* @values <code>fas</code>, <code>fab</code>, etc...
|
||||
* */
|
||||
export let iconPack = ''
|
||||
|
||||
/** Show an input field
|
||||
* @svelte-prop {Boolean} [hasInput=false]
|
||||
* */
|
||||
export let hasInput = false
|
||||
|
||||
export let prompt = null
|
||||
|
||||
/** Show the cancel button. True for <code>confirm()</code>
|
||||
* @svelte-prop {Boolean} [showCancel=false]
|
||||
* */
|
||||
export let showCancel = false
|
||||
|
||||
/** Dialog's size
|
||||
* @svelte-prop {String} [size]
|
||||
* @values $$sizes$$
|
||||
* */
|
||||
export let size = ''
|
||||
|
||||
/** Type (color) to use on confirm button and icon
|
||||
* @svelte-prop {String} [type=is-primary]
|
||||
* @values $$colors$$
|
||||
* */
|
||||
export let type = 'is-primary'
|
||||
|
||||
export let active = true
|
||||
|
||||
/** Animation to use when showing dialog
|
||||
* @svelte-prop {String|Function} [animation=scale]
|
||||
* @values Any transition name that ships with Svelte, or a custom function
|
||||
* */
|
||||
export let animation = 'scale'
|
||||
|
||||
/** Props to pass to animation function
|
||||
* @svelte-prop {Object} [animProps={ start: 1.2 }]
|
||||
* */
|
||||
export let animProps = { start: 1.2 }
|
||||
|
||||
/** Props (attributes) to use to on prompt input element
|
||||
* @svelte-prop {Object} [inputProps]
|
||||
* */
|
||||
export let inputProps = {}
|
||||
|
||||
// export let showClose = true
|
||||
let resolve
|
||||
export const promise = new Promise((fulfil) => (resolve = fulfil))
|
||||
|
||||
// TODO: programmatic subcomponents
|
||||
export const subComponent = null
|
||||
export let appendToBody = true
|
||||
|
||||
let modal
|
||||
let cancelButton
|
||||
let confirmButton
|
||||
let input
|
||||
let validationMessage = ''
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: _animation = chooseAnimation(animation)
|
||||
$: {
|
||||
if (modal && active && appendToBody) {
|
||||
modal.parentNode.removeChild(modal)
|
||||
document.body.appendChild(modal)
|
||||
}
|
||||
}
|
||||
$: newInputProps = { required: true, ...inputProps }
|
||||
|
||||
onMount(async () => {
|
||||
await tick()
|
||||
|
||||
if (hasInput) {
|
||||
input.focus()
|
||||
} else if (focusOn === 'cancel' && showCancel) {
|
||||
cancelButton.focus()
|
||||
} else {
|
||||
confirmButton.focus()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function cancel() {
|
||||
resolve(hasInput ? null : false)
|
||||
close()
|
||||
}
|
||||
|
||||
function close() {
|
||||
resolve(hasInput ? null : false)
|
||||
active = false
|
||||
dispatch('destroyed')
|
||||
}
|
||||
|
||||
async function confirm() {
|
||||
if (input && !input.checkValidity()) {
|
||||
validationMessage = input.validationMessage
|
||||
|
||||
await tick()
|
||||
input.select()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
validationMessage = ''
|
||||
|
||||
resolve(hasInput ? prompt: true)
|
||||
close()
|
||||
}
|
||||
|
||||
function keydown(e) {
|
||||
if (active && isEscKey(e)) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'node_modules/bulma/sass/utilities/all';
|
||||
|
||||
.dialog {
|
||||
.modal-card {
|
||||
max-width: 460px;
|
||||
width: auto;
|
||||
.modal-card-head {
|
||||
font-size: $size-5;
|
||||
font-weight: $weight-semibold;
|
||||
}
|
||||
.modal-card-body {
|
||||
.field {
|
||||
margin-top: 16px;
|
||||
}
|
||||
&.is-titleless {
|
||||
border-top-left-radius: $radius-large;
|
||||
border-top-right-radius: $radius-large;
|
||||
}
|
||||
}
|
||||
.modal-card-foot {
|
||||
justify-content: flex-end;
|
||||
.button {
|
||||
display: inline; // Fix Safari centering
|
||||
min-width: 5em;
|
||||
font-weight: $weight-semibold;
|
||||
}
|
||||
}
|
||||
@include tablet {
|
||||
min-width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-small {
|
||||
.modal-card,
|
||||
.input,
|
||||
.button {
|
||||
@include control-small;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-medium {
|
||||
.modal-card,
|
||||
.input,
|
||||
.button {
|
||||
@include control-medium;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-large {
|
||||
.modal-card,
|
||||
.input,
|
||||
.button {
|
||||
@include control-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:window on:keydown={keydown}></svelte:window>
|
||||
<svelte:options accessors/>
|
||||
|
||||
{#if active}
|
||||
<div class="modal dialog {size} is-active" bind:this={modal}>
|
||||
<div class="modal-background" on:click={close}></div>
|
||||
<div class="modal-card" transition:_animation={animProps}>
|
||||
{#if title}
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">{title}</p>
|
||||
<!-- NOTE: don't think we need this... -->
|
||||
<!-- {#if showClose}
|
||||
<button class="delete" aria-label="close" on:click={close}></button>
|
||||
{/if} -->
|
||||
</header>
|
||||
{/if}
|
||||
<section class="modal-card-body" class:is-titleless={!title} class:is-flex={icon}>
|
||||
<div class="media">
|
||||
{#if icon}
|
||||
<div class="media-left">
|
||||
<Icon pack={iconPack} {icon} {type} size="is-large"></Icon>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="media-content">
|
||||
<p>{@html message}</p>
|
||||
|
||||
{#if hasInput}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input
|
||||
bind:value={prompt}
|
||||
class="input"
|
||||
bind:this={input}
|
||||
{...newInputProps}
|
||||
on:keyup={e => isEnterKey(e) && confirm()}>
|
||||
<p class="help is-danger">{validationMessage}</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="modal-card-foot">
|
||||
{#if showCancel}
|
||||
<button
|
||||
class="button"
|
||||
bind:this={cancelButton}
|
||||
on:click={cancel}>
|
||||
{cancelText}
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
class="button {type}"
|
||||
bind:this={confirmButton}
|
||||
on:click={confirm}>
|
||||
{confirmText}
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
|
@ -0,0 +1,39 @@
|
|||
import Dialog from './Dialog.svelte'
|
||||
|
||||
function createDialog(props) {
|
||||
if (typeof props === 'string') props = { message: props }
|
||||
|
||||
const dialog = new Dialog({
|
||||
target: document.body,
|
||||
props,
|
||||
intro: true,
|
||||
});
|
||||
|
||||
dialog.$on('destroy', () => {
|
||||
dialog.$destroy
|
||||
})
|
||||
|
||||
return dialog.promise
|
||||
}
|
||||
|
||||
export function alert(props) {
|
||||
return createDialog(props);
|
||||
}
|
||||
|
||||
export function confirm(props) {
|
||||
if (typeof props === 'string') props = { message: props }
|
||||
|
||||
return createDialog({ showCancel: true, ...props });
|
||||
}
|
||||
|
||||
export function prompt(props) {
|
||||
if (typeof props === 'string') props = { message: props }
|
||||
|
||||
return createDialog({ hasInput: true, confirmText: 'Done', ...props });
|
||||
}
|
||||
|
||||
Dialog.alert = alert
|
||||
Dialog.confirm = confirm
|
||||
Dialog.prompt = prompt
|
||||
|
||||
export default Dialog
|
|
@ -0,0 +1,24 @@
|
|||
<script>
|
||||
import * as transitions from 'svelte/transition'
|
||||
|
||||
export let open = true
|
||||
export let animation = 'slide'
|
||||
|
||||
let _animation = transitions[animation]
|
||||
$: _animation = typeof animation === 'function' ? animation : transitions[animation]
|
||||
|
||||
function toggle() {
|
||||
open = !open
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="collapse">
|
||||
<div class="collapse-trigger" on:click={toggle}>
|
||||
<slot name="trigger" />
|
||||
</div>
|
||||
{#if open}
|
||||
<div class="collapse-content" transition:_animation|local>
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
|
@ -0,0 +1,122 @@
|
|||
<script>
|
||||
import { onMount, setContext } from 'svelte'
|
||||
import { omit } from '../utils'
|
||||
|
||||
/** Type (color) of the field and help message. Also adds a matching icon.
|
||||
* @svelte-prop {String} [type]
|
||||
* @values $$colors$$
|
||||
* */
|
||||
export let type = ''
|
||||
|
||||
/** Label for input
|
||||
* @svelte-prop {String} [label]
|
||||
* */
|
||||
export let label = null
|
||||
|
||||
/** Same as native <code>for</code> on label
|
||||
* @svelte-prop {String} [labelFor]
|
||||
* */
|
||||
export let labelFor = ''
|
||||
|
||||
/** Message to show beneath input
|
||||
* @svelte-prop {String} [message]
|
||||
* */
|
||||
export let message = ''
|
||||
|
||||
/** Direct child components/elements of Field will be grouped horizontally
|
||||
* @svelte-prop {Boolean} grouped=false
|
||||
* */
|
||||
export let grouped = false
|
||||
|
||||
/** Allow grouped controls to cover multiple lines
|
||||
* @svelte-prop {Boolean} groupMultiline=false
|
||||
* */
|
||||
export let groupMultiline = false
|
||||
|
||||
/** Alter the alignment of the field
|
||||
* @svelte-prop {String} [position]
|
||||
* @values is-centered, is-right
|
||||
* */
|
||||
export let position = ''
|
||||
|
||||
/** Automatically attach child controls together
|
||||
* @svelte-prop {Boolean} addons=true
|
||||
* */
|
||||
export let addons = true
|
||||
|
||||
export let expanded = false
|
||||
|
||||
setContext('type', () => type)
|
||||
|
||||
let el
|
||||
let labelEl
|
||||
let messageEl
|
||||
let fieldType = ''
|
||||
let hasIcons = false
|
||||
let iconType = ''
|
||||
let mounted = false
|
||||
let newPosition = ''
|
||||
|
||||
// Determine the icon type
|
||||
$: {
|
||||
if (['is-danger', 'is-success'].includes(type)) {
|
||||
iconType = type
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (grouped) fieldType = 'is-grouped'
|
||||
else if (mounted) {
|
||||
const childNodes = Array.prototype.filter.call(el.children, c => !([labelEl, messageEl].includes(c)))
|
||||
if (childNodes.length > 1 && addons) {
|
||||
fieldType = 'has-addons'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update has-addons-* or is-grouped-* classes based on position prop
|
||||
$: {
|
||||
if (position) {
|
||||
const pos = position.split('-')
|
||||
if (pos.length >= 1) {
|
||||
const prefix = grouped ? 'is-grouped-' : 'has-addons-'
|
||||
newPosition = prefix + pos[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: props = { ...omit($$props, 'addons', 'class', 'expanded', 'grouped', 'label', 'labelFor', 'position', 'type') }
|
||||
|
||||
onMount(() => {
|
||||
mounted = true
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.field {
|
||||
&.is-grouped {
|
||||
.field {
|
||||
flex-shrink: 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
&.is-expanded {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div {...props} class="field {type} {fieldType} {newPosition} {$$props.class || ''}" class:is-expanded={expanded} class:is-grouped-multiline={groupMultiline} bind:this={el}>
|
||||
{#if label}
|
||||
<label for={labelFor} class="label" bind:this={labelEl}>{label}</label>
|
||||
{/if}
|
||||
<slot statusType={type} />
|
||||
{#if message}
|
||||
<p class="help {type}" bind:this={messageEl}>{message}</p>
|
||||
{/if}
|
||||
</div>
|