Skip to content

Commit b372624

Browse files
committed
initial commit
1 parent b26fd17 commit b372624

File tree

14 files changed

+323
-88
lines changed

14 files changed

+323
-88
lines changed

README.md

Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,94 @@
11
# vue-container-query
22

3-
## Project setup
4-
```
5-
yarn install
6-
```
3+
**Totally based on [d6u/react-container-query](https://github.com/d6u/react-container-query).**
74

8-
### Compiles and hot-reloads for development
9-
```
10-
yarn run serve
11-
```
5+
## Notice
126

13-
### Compiles and minifies for production
14-
```
15-
yarn run build
16-
```
7+
The following documentation is also originated from [d6u/react-container-query](https://github.com/d6u/react-container-query).
178

18-
### Lints and fixes files
19-
```
20-
yarn run lint
9+
Your suggested to pay a visit to the repo `react-container-query`.
10+
11+
## Installation
12+
13+
```sh
14+
npm i -D vue-container-query
2115
```
2216

23-
### Run your unit tests
17+
## API
18+
19+
### `<ContainerQuery :query="query" :initialSize="{ width, height }>`
20+
21+
```html
22+
<template>
23+
<ContainerQuery :query="query" v-model="params">
24+
<pre class="app">{{ params }}</pre>
25+
</ContainerQuery>
26+
</template>
27+
28+
<script>
29+
import { ContainerQuery } from './'
30+
const query = {
31+
'width-between-400-and-599': {
32+
minWidth: 400,
33+
maxWidth: 599
34+
},
35+
'width-larger-than-600': {
36+
minWidth: 600
37+
}
38+
}
39+
40+
export default {
41+
name: 'app',
42+
components: { ContainerQuery },
43+
data () {
44+
return { query, params: {} }
45+
}
46+
}
47+
</script>
2448
```
25-
yarn run test:unit
49+
50+
#### properties
51+
52+
- `props.children`
53+
54+
There should only be **one, and exactly one ** child component.
55+
56+
- `props.query`
57+
58+
"query" is key-value pairs where keys are the class names that will be applied to container element when all constraints are met. The values are the constraints.
59+
60+
- `props.initialSize` (optional)
61+
62+
`initialSize` is an object with optional `width` or `height` property. Because the limitation on how size is computed based on underlying element, in the initial rendering pass, we don't have the size info (because element must be in the DOM have a valid size). At this time `initialSize` will be used as the size of the element.
63+
64+
### `createContainerQueryMixin(query, initialSize)`
65+
66+
```html
67+
68+
<template>
69+
<pre class="app">{{ containerQuery }}</pre>
70+
</template>
71+
72+
<script>
73+
import { createContainerQueryMixin } from './'
74+
const query = {
75+
'width-between-400-and-599': {
76+
minWidth: 400,
77+
maxWidth: 599
78+
},
79+
'width-larger-than-600': {
80+
minWidth: 600
81+
}
82+
}
83+
84+
export default {
85+
name: 'app',
86+
mixins: [
87+
createContainerQueryMixin(query)
88+
],
89+
data () {
90+
return { query, params: {} }
91+
}
92+
}
93+
</script>
2694
```

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
"serve": "vue-cli-service serve",
77
"build": "vue-cli-service build",
88
"lint": "vue-cli-service lint",
9-
"test:unit": "vue-cli-service test:unit"
9+
"test:unit": "vue-cli-service test:unit",
10+
"bundle": "vue-cli-service build --target lib --name VueContainerQuery ./src/index.js"
1011
},
1112
"dependencies": {
13+
"container-query-toolkit": "^0.1.3",
14+
"resize-observer-lite": "^0.2.3",
1215
"vue": "^2.5.17"
1316
},
1417
"devDependencies": {

src/App.vue

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
11
<template>
2-
<div id="app">
3-
<img alt="Vue logo" src="./assets/logo.png">
4-
<HelloWorld msg="Welcome to Your Vue.js App"/>
5-
</div>
2+
<ContainerQuery :query="query" v-model="params">
3+
<pre class="app">{{ params }}</pre>
4+
</ContainerQuery>
65
</template>
76

87
<script>
9-
import HelloWorld from './components/HelloWorld.vue'
8+
import { ContainerQuery } from './'
9+
const query = {
10+
'width-between-400-and-599': {
11+
minWidth: 400,
12+
maxWidth: 599
13+
},
14+
'width-larger-than-600': {
15+
minWidth: 600
16+
}
17+
}
1018
1119
export default {
1220
name: 'app',
13-
components: {
14-
HelloWorld
21+
components: { ContainerQuery },
22+
data () {
23+
return { query, params: {} }
1524
}
1625
}
1726
</script>
1827

1928
<style>
20-
#app {
29+
.app {
2130
font-family: 'Avenir', Helvetica, Arial, sans-serif;
2231
-webkit-font-smoothing: antialiased;
2332
-moz-osx-font-smoothing: grayscale;
24-
text-align: center;
25-
color: #2c3e50;
33+
color: #ffffff;
2634
margin-top: 60px;
35+
background: #2c3e50;
36+
padding: 30px 100px;
2737
}
2838
</style>

src/AppMixin.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template>
2+
<pre class="app">{{ containerQuery }}</pre>
3+
</template>
4+
5+
<script>
6+
import { createContainerQueryMixin } from './'
7+
const query = {
8+
'width-between-400-and-599': {
9+
minWidth: 400,
10+
maxWidth: 599
11+
},
12+
'width-larger-than-600': {
13+
minWidth: 600
14+
}
15+
}
16+
17+
export default {
18+
name: 'app2',
19+
mixins: [
20+
createContainerQueryMixin(query)
21+
],
22+
data () {
23+
return { query, params: {} }
24+
}
25+
}
26+
</script>

src/assets/logo.png

-6.69 KB
Binary file not shown.

src/components/Base.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// @ts-ignore
2+
import matchQueries from 'container-query-toolkit/lib/matchQueries'
3+
import ContainerQueryCore from './ContainerQueryCore'
4+
5+
export default {
6+
methods: {
7+
handleChange () {
8+
throw new Error('Method `handleChange()` not implemented.')
9+
},
10+
11+
disposeObserver () {
12+
if (this.cqCore) {
13+
this.cqCore.disconnect()
14+
}
15+
this.cqCore = null
16+
},
17+
18+
startObserving (query) {
19+
this.cqCore = new ContainerQueryCore(query, params => {
20+
this.handleChange(params)
21+
})
22+
23+
const element = (this.$el || this.$slots.default[0].elm)
24+
this.cqCore.observe(element)
25+
}
26+
},
27+
28+
created () {
29+
const { query, initialSize } = this
30+
const params = initialSize
31+
? matchQueries(query)(initialSize)
32+
: {}
33+
this.handleChange(params)
34+
},
35+
36+
mounted () {
37+
this.startObserving(this.query)
38+
},
39+
40+
destroyed () {
41+
this.disposeObserver()
42+
}
43+
}

src/components/ContainerQueryCore.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import ResizeObserverLite from 'resize-observer-lite'
2+
import matchQueries from 'container-query-toolkit/lib/matchQueries'
3+
import isShallowEqual from './isShallowEqual'
4+
5+
export default class ContainerQueryCore {
6+
constructor (query, callback) {
7+
this.result = {}
8+
this.rol = new ResizeObserverLite((size) => {
9+
const result = matchQueries(query)(size)
10+
if (!isShallowEqual(this.result, result)) {
11+
callback(result)
12+
this.result = result
13+
}
14+
})
15+
}
16+
17+
observe (element) {
18+
this.rol.observe(element)
19+
}
20+
21+
disconnect () {
22+
this.rol.disconnect()
23+
}
24+
}

src/components/HelloWorld.vue

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/components/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Base from './Base'
2+
import isQueriesEqual from './isQueriesEqual'
3+
4+
const kErrMsg = '<vue-Container-query> can only render' +
5+
' one, and exactly one child component'
6+
7+
export const ContainerQuery = {
8+
name: 'vue-container-query',
9+
mixins: [Base],
10+
model: { event: 'change' },
11+
props: {
12+
initialSize: {
13+
type: Object
14+
},
15+
query: {
16+
required: true,
17+
type: Object
18+
}
19+
},
20+
methods: {
21+
handleChange (params) {
22+
this.$emit('change', params)
23+
}
24+
},
25+
watch: {
26+
query: {
27+
deep: true,
28+
immediate: true,
29+
handler (newVal, oldVal) {
30+
if (this.cqCore && !isQueriesEqual(oldVal, newVal)) {
31+
this.disposeObserver()
32+
this.startObserving(newVal)
33+
}
34+
}
35+
}
36+
},
37+
render () {
38+
const slot = this.$slots.default
39+
if (slot && slot.length === 1) {
40+
return slot[0]
41+
}
42+
43+
throw new Error(kErrMsg)
44+
}
45+
}
46+
47+
export function createContainerQueryMixin (query, initialSize) {
48+
return {
49+
mixins: [Base],
50+
data () {
51+
return { query, initialSize, containerQuery: {} }
52+
},
53+
methods: {
54+
handleChange (params) {
55+
this.containerQuery = params
56+
}
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)