├── .editorconfig
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── __test__
└── index.test.js
├── circle.yml
├── example
├── App.vue
└── index.js
├── package.json
├── postcss.config.js
├── src
├── Header
│ ├── index.js
│ └── style.module.css
├── index.js
└── style.module.css
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) EGOIST <0x142857@gmail.com> (github.com/egoist)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-windows [](https://npmjs.com/package/vue-windows) [](https://npmjs.com/package/vue-windows) [](https://circleci.com/gh/egoist/vue-windows)
2 |
3 | It's inspired by the [socket.io](http://socket.io/) homepage, only 1kb.
4 |
5 | ## Install
6 |
7 | ```bash
8 | $ npm install --save vue-windows
9 | ```
10 |
11 | ## Usage
12 |
13 | ```vue
14 |
15 |
16 |
17 | editor window body
18 |
19 |
20 | browser window body
21 |
22 |
23 |
24 |
25 |
35 |
36 |
37 |
38 | ```
39 |
40 | ## API
41 |
42 | ### Props
43 |
44 | #### title
45 |
46 | - Type: `string`
47 | - Required: `true`
48 |
49 | #### shadow
50 |
51 | - Type: `boolean`
52 | - Default: `false`
53 |
54 | Whether to show window shadow.
55 |
56 | #### theme
57 |
58 | - Type: `string`
59 | - Default: `default`
60 | - Available: `default`, `dark`
61 |
62 | #### width
63 |
64 | - Type: `number`, `string`
65 | - Default: `100%`
66 |
67 | Number values are resolved into lengths in `px` while string values are used directly.
68 |
69 | #### height
70 |
71 | - Type: `number`, `string`
72 | - Default: `340`
73 |
74 | Number values are resolved into lengths in `px` while string values are used directly.
75 |
76 | ## Contributing
77 |
78 | 1. Fork it!
79 | 2. Create your feature branch: `git checkout -b my-new-feature`
80 | 3. Commit your changes: `git commit -am 'Add some feature'`
81 | 4. Push to the branch: `git push origin my-new-feature`
82 | 5. Submit a pull request :D
83 |
84 | ## Development
85 |
86 | ```bash
87 | yarn
88 | yarn example
89 | ```
90 |
91 | ## License
92 |
93 | [MIT](https://egoist.mit-license.org/) © [EGOIST](https://github.com/egoist)
94 |
--------------------------------------------------------------------------------
/__test__/index.test.js:
--------------------------------------------------------------------------------
1 | const fn = require('../')
2 |
3 | test('main', () => {
4 | expect(fn()).toBe(1)
5 | })
6 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 |
2 | version: 2
3 | jobs:
4 | build:
5 | working_directory: ~/repo
6 | docker:
7 | - image: circleci/node:latest
8 | branches:
9 | ignore:
10 | - gh-pages # list of branches to ignore
11 | - /release\/.*/ # or ignore regexes
12 | steps:
13 | - checkout
14 | - restore_cache:
15 | key: dependency-cache-{{ checksum "yarn.lock" }}
16 | - run:
17 | name: install dependences
18 | command: yarn
19 | - save_cache:
20 | key: dependency-cache-{{ checksum "yarn.lock" }}
21 | paths:
22 | - ./node_modules
23 | - run:
24 | name: test
25 | command: yarn test
26 |
--------------------------------------------------------------------------------
/example/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Vue Windows
4 |
5 |
40 |
41 |
42 |
43 |
51 |
52 |
53 |
54 |
61 |
62 |
63 | Such Window, Very Lovely!
64 |
65 |
Star me on GitHub!
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
114 |
115 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App)
7 | })
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-windows",
3 | "version": "0.3.0",
4 | "description": "Vue component for making neat native-like window.",
5 | "license": "MIT",
6 | "repository": "egoist/vue-windows",
7 | "author": {
8 | "name": "EGOIST",
9 | "email": "0x142857@gmail.com",
10 | "url": "https://github.com/egoist"
11 | },
12 | "scripts": {
13 | "test": "echo fine",
14 | "example": "poi --serve",
15 | "build": "bili --format cjs,umd,es --no-babel.babelrc --jsx vue",
16 | "build:example": "poi --prod",
17 | "prepublishOnly": "npm run build",
18 | "gh": "npm run build:example && gh-pages -d example/dist"
19 | },
20 | "files": [
21 | "dist"
22 | ],
23 | "main": "./dist/vue-windows.cjs.js",
24 | "module": "./dist/vue-windows.es.js",
25 | "cdn": "./dist/vue-windows.js",
26 | "jsdelivr": "./dist/vue-windows.js",
27 | "unpkg": "./dist/vue-windows.js",
28 | "keywords": [
29 | "vue",
30 | "window",
31 | "mock"
32 | ],
33 | "devDependencies": {
34 | "bili": "^3.0.10",
35 | "gh-pages": "^0.11.0",
36 | "highlight.js": "^9.8.0",
37 | "poi": "^12.0.0",
38 | "postcss-cssnext": "^3.1.0",
39 | "vue": "^2.5.18",
40 | "vue-template-compiler": "^2.5.18"
41 | },
42 | "poi": {
43 | "entry": "example/index.js",
44 | "output": {
45 | "dir": "example/dist"
46 | },
47 | "babel": {
48 | "jsx": "vue"
49 | }
50 | },
51 | "dependencies": {
52 | "nano-assign": "^1.0.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-cssnext')()
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/Header/index.js:
--------------------------------------------------------------------------------
1 | import style from './style.module.css'
2 |
3 | export default {
4 | functional: true,
5 | props: {
6 | title: {
7 | type: String,
8 | required: true
9 | },
10 | isURL: {
11 | type: Boolean,
12 | default: false
13 | },
14 | theme: {
15 | type: String
16 | }
17 | },
18 | render(h, { props: { title, isURL, theme } }) {
19 | return (
20 |
28 | )
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Header/style.module.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --red: #f85955;
3 | --dark-red: #d74246;
4 | --yellow: #fbbe3f;
5 | --dark-yellow: #d7a32d;
6 | --green: #45cc4b;
7 | --dark-green: #40ad36;
8 | }
9 |
10 | .header {
11 | height: 40px;
12 | padding-right: 75px;
13 | display: flex;
14 | align-items: center;
15 | }
16 |
17 | .title {
18 | flex: 1 1 320px;
19 | text-align: center;
20 | font-size: 12px;
21 | color: #766F79;
22 | white-space: nowrap;
23 | overflow: hidden;
24 | text-overflow: ellipsis;
25 | }
26 |
27 | .bullets {
28 | margin-left: 12px;
29 | display: flex;
30 | flex: 0 0;
31 | align-items: center;
32 | }
33 |
34 | .bullet {
35 | height: 12px;
36 | width: 12px;
37 | display: block;
38 | background: #ccc;
39 | border-radius: 100%;
40 | border: 1px solid;
41 | }
42 |
43 | .bullet + .bullet {
44 | margin-left: 5px;
45 | }
46 |
47 | .bullet-red {
48 | background: var(--red);
49 | border-color: var(--dark-red);
50 | }
51 |
52 | .bullet-yellow {
53 | background: var(--yellow);
54 | border-color: var(--dark-yellow);
55 | }
56 |
57 | .bullet-green {
58 | background: var(--green);
59 | border-color: var(--dark-green);
60 | }
61 |
62 | .header.isUrl {
63 | background: #e8e8e8;
64 | & .title {
65 | background: #fff;
66 | flex: 1 1 320px;
67 | border-radius: 4px;
68 | line-height: 26px;
69 | margin-left: 17px;
70 | padding: 0 12px;
71 | text-align: left;
72 | }
73 | }
74 |
75 | .header.dark {
76 | & .title {
77 | color: white;
78 | }
79 |
80 | & .bullet {
81 | border-color: transparent;
82 | }
83 |
84 | &.isUrl {
85 | background: rgba(255, 255, 255, .1);
86 | & .title {
87 | background-color: rgba(156, 156, 156, 0.21);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import assign from 'nano-assign'
2 | import styles from './style.module.css'
3 | import Header from './Header/index'
4 |
5 | const EditorWindow = {
6 | name: 'editor-window',
7 | props: {
8 | title: {
9 | required: true,
10 | type: String
11 | },
12 | browser: Boolean,
13 | height: [Number, String],
14 | width: [Number, String],
15 | theme: {
16 | type: String,
17 | validator(v) {
18 | return ['default', 'dark'].indexOf(v) > -1
19 | }
20 | },
21 | shadow: {
22 | type: Boolean,
23 | default: false
24 | }
25 | },
26 | render(h) {
27 | const {browser, title, height, width, theme, shadow} = this.$props
28 |
29 | const className = [
30 | styles.window,
31 | theme && styles[theme],
32 | shadow && styles.shadow
33 | ]
34 |
35 | const style = {
36 | height: Boolean(height) && (typeof height === 'number' ? `${height}px` : height),
37 | width: Boolean(width) && (typeof width === 'number' ? `${width}px` : width)
38 | }
39 |
40 | return h('div', {
41 | class: className,
42 | style
43 | }, [
44 | h(Header, {
45 | props: {
46 | title,
47 | isURL: browser,
48 | theme
49 | }
50 | }),
51 | h('div', {
52 | class: styles.body
53 | }, this.$slots.default)
54 | ])
55 | }
56 | }
57 |
58 | const BrowserWindow = {
59 | name: 'browser-window',
60 | props: EditorWindow.props,
61 | render(h) {
62 | const props = assign({ browser: true }, this.$props)
63 |
64 | if (props.title.substr(0, 8) === 'https://') {
65 | props.title = `https${props.title.substr(5)}`
66 | }
67 |
68 | return h(EditorWindow, {
69 | props
70 | }, this.$slots.default)
71 | }
72 | }
73 |
74 | export {
75 | EditorWindow,
76 | BrowserWindow
77 | }
78 |
--------------------------------------------------------------------------------
/src/style.module.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --black: #151515;
3 | --green: #45cc4b;
4 | --dark-green: #40ad36;
5 | }
6 |
7 | .window {
8 | width: 100%;
9 | height: 340px;
10 | border-radius: 4px;
11 | text-align: left;
12 | vertical-align: top;
13 | display: inline-block;
14 | background-color: white;
15 | z-index: 1;
16 | overflow: hidden;
17 | border: 1px solid #ccc;
18 | }
19 |
20 | .body {
21 | padding: 10px 12px;
22 | position: relative;
23 | height: calc(100% - 40px);
24 | overflow: auto;
25 | }
26 |
27 | .shadow {
28 | box-shadow: rgba(0, 0, 0, 0.55) 0px 20px 68px;
29 | }
30 |
31 | .dark {
32 | color: white;
33 | border-color: var(--black);
34 | background-color: var(--black);
35 | }
36 |
37 | .safe {
38 | color: var(--dark-green);
39 | }
40 |
41 | .safe.dark {
42 | color: var(--green);
43 | background-color: transparent;
44 | }
45 |
--------------------------------------------------------------------------------