ember-container-query 2.0.2 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.stylelintrc.js +64 -0
- package/CHANGELOG.md +42 -0
- package/addon/components/container-query.hbs +7 -7
- package/addon/components/container-query.ts +34 -0
- package/addon/helpers/cq-aspect-ratio.ts +15 -0
- package/addon/helpers/cq-height.ts +15 -0
- package/addon/helpers/cq-width.ts +15 -0
- package/addon/modifiers/container-query.ts +170 -0
- package/app/modifiers/container-query.js +1 -0
- package/components/container-query.d.ts +19 -0
- package/helpers/cq-aspect-ratio.d.ts +10 -0
- package/helpers/cq-height.d.ts +10 -0
- package/helpers/cq-width.d.ts +10 -0
- package/modifiers/container-query.d.ts +54 -0
- package/package.json +67 -30
- package/tsconfig.json +104 -0
- package/types/dummy/index.d.ts +0 -0
- package/types/global.d.ts +6 -0
- package/addon/components/container-query.js +0 -84
- package/addon/helpers/cq-aspect-ratio.js +0 -10
- package/addon/helpers/cq-height.js +0 -10
- package/addon/helpers/cq-width.js +0 -10
package/.stylelintrc.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable-next-line n/no-unpublished-require */
|
|
4
|
+
const { browsers } = require('./tests/dummy/config/targets');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
extends: ['stylelint-config-standard'],
|
|
8
|
+
plugins: ['stylelint-no-unsupported-browser-features', 'stylelint-order'],
|
|
9
|
+
rules: {
|
|
10
|
+
/*
|
|
11
|
+
Customize plugins
|
|
12
|
+
*/
|
|
13
|
+
'order/properties-order': [
|
|
14
|
+
[
|
|
15
|
+
// Defined by ember-css-modules
|
|
16
|
+
'composes',
|
|
17
|
+
],
|
|
18
|
+
{
|
|
19
|
+
unspecified: 'bottomAlphabetical',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
'plugin/no-unsupported-browser-features': [
|
|
24
|
+
true,
|
|
25
|
+
{
|
|
26
|
+
browsers,
|
|
27
|
+
ignore: [
|
|
28
|
+
// grid-template-columns falsely identified as multicolumn
|
|
29
|
+
'multicolumn',
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
Customize rules
|
|
36
|
+
*/
|
|
37
|
+
'declaration-block-no-redundant-longhand-properties': [
|
|
38
|
+
true,
|
|
39
|
+
{
|
|
40
|
+
ignoreShorthands: ['grid-gap', 'grid-template'],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
'property-no-unknown': [
|
|
45
|
+
true,
|
|
46
|
+
{
|
|
47
|
+
ignoreProperties: [
|
|
48
|
+
// Defined by ember-css-modules
|
|
49
|
+
'composes',
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
|
|
54
|
+
'selector-pseudo-class-no-unknown': [
|
|
55
|
+
true,
|
|
56
|
+
{
|
|
57
|
+
ignorePseudoClasses: [
|
|
58
|
+
// Defined by ember-css-modules
|
|
59
|
+
'global',
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
};
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
## 2.1.1 (2022-12-02)
|
|
2
|
+
|
|
3
|
+
### Bug Fix
|
|
4
|
+
* [#128](https://github.com/ijlee2/ember-container-query/pull/128) Replaced @ember/render-modifiers with ember-modifier ([@ijlee2](https://github.com/ijlee2))
|
|
5
|
+
* [#126](https://github.com/ijlee2/ember-container-query/pull/126) Listed ember-test-selectors as a dependency ([@ijlee2](https://github.com/ijlee2))
|
|
6
|
+
|
|
7
|
+
### Enhancement
|
|
8
|
+
* [#128](https://github.com/ijlee2/ember-container-query/pull/128) Replaced @ember/render-modifiers with ember-modifier ([@ijlee2](https://github.com/ijlee2))
|
|
9
|
+
|
|
10
|
+
### Internal
|
|
11
|
+
* [#133](https://github.com/ijlee2/ember-container-query/pull/133) Addressed ember-modifier deprecations ([@ijlee2](https://github.com/ijlee2))
|
|
12
|
+
* [#132](https://github.com/ijlee2/ember-container-query/pull/132) Updated dependencies to their latest version ([@ijlee2](https://github.com/ijlee2))
|
|
13
|
+
* [#128](https://github.com/ijlee2/ember-container-query/pull/128) Replaced @ember/render-modifiers with ember-modifier ([@ijlee2](https://github.com/ijlee2))
|
|
14
|
+
* [#125](https://github.com/ijlee2/ember-container-query/pull/125) Updated dependencies to their latest version ([@ijlee2](https://github.com/ijlee2))
|
|
15
|
+
* [#124](https://github.com/ijlee2/ember-container-query/pull/124) Installed stylelint to help with maintaining the demo app ([@ijlee2](https://github.com/ijlee2))
|
|
16
|
+
|
|
17
|
+
### Committers: 1
|
|
18
|
+
- Isaac Lee ([@ijlee2](https://github.com/ijlee2))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## 2.1.0 (2022-06-03)
|
|
22
|
+
|
|
23
|
+
### Enhancement
|
|
24
|
+
* [#119](https://github.com/ijlee2/ember-container-query/pull/119) Introduced TypeScript (Part 3) ([@ijlee2](https://github.com/ijlee2))
|
|
25
|
+
|
|
26
|
+
### Internal
|
|
27
|
+
* [#123](https://github.com/ijlee2/ember-container-query/pull/123) Updated GitHub actions to v3 ([@ijlee2](https://github.com/ijlee2))
|
|
28
|
+
* [#122](https://github.com/ijlee2/ember-container-query/pull/122) Updated Node version in CI to 16 ([@ijlee2](https://github.com/ijlee2))
|
|
29
|
+
* [#121](https://github.com/ijlee2/ember-container-query/pull/121) Updated ember-on-resize-modifier to v1.1.0 ([@ijlee2](https://github.com/ijlee2))
|
|
30
|
+
* [#117](https://github.com/ijlee2/ember-container-query/pull/117) Updated dependencies to their latest version ([@ijlee2](https://github.com/ijlee2))
|
|
31
|
+
* [#115](https://github.com/ijlee2/ember-container-query/pull/115) Updated eslint to v8 ([@ijlee2](https://github.com/ijlee2))
|
|
32
|
+
|
|
33
|
+
### Documentation
|
|
34
|
+
* [#120](https://github.com/ijlee2/ember-container-query/pull/120) Introduced TypeScript (Part 4) ([@ijlee2](https://github.com/ijlee2))
|
|
35
|
+
* [#118](https://github.com/ijlee2/ember-container-query/pull/118) Introduced TypeScript (Part 2) ([@ijlee2](https://github.com/ijlee2))
|
|
36
|
+
* [#114](https://github.com/ijlee2/ember-container-query/pull/114) Introduced TypeScript (Part 1) ([@ijlee2](https://github.com/ijlee2))
|
|
37
|
+
* [#116](https://github.com/ijlee2/ember-container-query/pull/116) Updated demo app ([@ijlee2](https://github.com/ijlee2))
|
|
38
|
+
|
|
39
|
+
### Committers: 1
|
|
40
|
+
- Isaac Lee ([@ijlee2](https://github.com/ijlee2))
|
|
41
|
+
|
|
42
|
+
|
|
1
43
|
## 2.0.2 (2022-04-25)
|
|
2
44
|
|
|
3
45
|
### Bug Fix
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
<Tag
|
|
3
3
|
class="container-query"
|
|
4
4
|
data-test-container-query
|
|
5
|
-
{{
|
|
6
|
-
|
|
5
|
+
{{container-query
|
|
6
|
+
dataAttributePrefix=@dataAttributePrefix
|
|
7
|
+
debounce=@debounce
|
|
8
|
+
features=@features
|
|
9
|
+
onQuery=this.updateState
|
|
10
|
+
}}
|
|
7
11
|
...attributes
|
|
8
12
|
>
|
|
9
13
|
{{yield (hash
|
|
14
|
+
dimensions=this.dimensions
|
|
10
15
|
features=this.queryResults
|
|
11
|
-
dimensions=(hash
|
|
12
|
-
aspectRatio=this.aspectRatio
|
|
13
|
-
height=this.height
|
|
14
|
-
width=this.width
|
|
15
|
-
)
|
|
16
16
|
)}}
|
|
17
17
|
</Tag>
|
|
18
18
|
{{/let}}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
|
+
import Component from '@glimmer/component';
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import type {
|
|
5
|
+
Dimensions,
|
|
6
|
+
Features,
|
|
7
|
+
QueryResults,
|
|
8
|
+
} from 'ember-container-query/modifiers/container-query';
|
|
9
|
+
|
|
10
|
+
interface ContainerQueryComponentArgs {
|
|
11
|
+
dataAttributePrefix?: string;
|
|
12
|
+
debounce?: number;
|
|
13
|
+
features?: Features;
|
|
14
|
+
tagName?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default class ContainerQueryComponent extends Component<ContainerQueryComponentArgs> {
|
|
18
|
+
@tracked dimensions?: Dimensions;
|
|
19
|
+
@tracked queryResults?: QueryResults;
|
|
20
|
+
|
|
21
|
+
// The dynamic tag is restricted to be immutable
|
|
22
|
+
tagName = this.args.tagName ?? 'div';
|
|
23
|
+
|
|
24
|
+
@action updateState({
|
|
25
|
+
dimensions,
|
|
26
|
+
queryResults,
|
|
27
|
+
}: {
|
|
28
|
+
dimensions: Dimensions;
|
|
29
|
+
queryResults: QueryResults;
|
|
30
|
+
}): void {
|
|
31
|
+
this.dimensions = dimensions;
|
|
32
|
+
this.queryResults = queryResults;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { helper } from '@ember/component/helper';
|
|
2
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
3
|
+
|
|
4
|
+
function cqAspectRatio(
|
|
5
|
+
positional: unknown[],
|
|
6
|
+
named: Record<string, unknown>
|
|
7
|
+
): Metadata {
|
|
8
|
+
const dimension = 'aspectRatio';
|
|
9
|
+
const max = (named['max'] as number | undefined) ?? Infinity;
|
|
10
|
+
const min = (named['min'] as number | undefined) ?? 0;
|
|
11
|
+
|
|
12
|
+
return { dimension, max, min };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default helper(cqAspectRatio);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { helper } from '@ember/component/helper';
|
|
2
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
3
|
+
|
|
4
|
+
function cqHeight(
|
|
5
|
+
positional: unknown[],
|
|
6
|
+
named: Record<string, unknown>
|
|
7
|
+
): Metadata {
|
|
8
|
+
const dimension = 'height';
|
|
9
|
+
const max = (named['max'] as number | undefined) ?? Infinity;
|
|
10
|
+
const min = (named['min'] as number | undefined) ?? 0;
|
|
11
|
+
|
|
12
|
+
return { dimension, max, min };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default helper(cqHeight);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { helper } from '@ember/component/helper';
|
|
2
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
3
|
+
|
|
4
|
+
function cqWidth(
|
|
5
|
+
positional: unknown[],
|
|
6
|
+
named: Record<string, unknown>
|
|
7
|
+
): Metadata {
|
|
8
|
+
const dimension = 'width';
|
|
9
|
+
const max = (named['max'] as number | undefined) ?? Infinity;
|
|
10
|
+
const min = (named['min'] as number | undefined) ?? 0;
|
|
11
|
+
|
|
12
|
+
return { dimension, max, min };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default helper(cqWidth);
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { registerDestructor } from '@ember/destroyable';
|
|
2
|
+
import { action } from '@ember/object';
|
|
3
|
+
import { debounce as _debounce } from '@ember/runloop';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
import Modifier, { ArgsFor, NamedArgs, PositionalArgs } from 'ember-modifier';
|
|
6
|
+
|
|
7
|
+
export type Metadata = {
|
|
8
|
+
dimension: 'aspectRatio' | 'height' | 'width';
|
|
9
|
+
max: number;
|
|
10
|
+
min: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Features = {
|
|
14
|
+
[featureName: string]: Metadata;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Dimensions = {
|
|
18
|
+
aspectRatio: number;
|
|
19
|
+
height: number;
|
|
20
|
+
width: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type QueryResults = {
|
|
24
|
+
[featureName: string]: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface ContainerQueryModifierSignature {
|
|
28
|
+
Args: {
|
|
29
|
+
Named: {
|
|
30
|
+
dataAttributePrefix?: string;
|
|
31
|
+
debounce?: number;
|
|
32
|
+
features?: Features;
|
|
33
|
+
onQuery?: ({
|
|
34
|
+
dimensions,
|
|
35
|
+
queryResults,
|
|
36
|
+
}: {
|
|
37
|
+
dimensions: Dimensions;
|
|
38
|
+
queryResults: QueryResults;
|
|
39
|
+
}) => void;
|
|
40
|
+
};
|
|
41
|
+
Positional: [];
|
|
42
|
+
};
|
|
43
|
+
Element: Element;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default class ContainerQueryModifier extends Modifier<ContainerQueryModifierSignature> {
|
|
47
|
+
/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
|
|
48
|
+
/* @ts-ignore */
|
|
49
|
+
@service private declare readonly resizeObserver;
|
|
50
|
+
|
|
51
|
+
dimensions!: Dimensions;
|
|
52
|
+
queryResults!: QueryResults;
|
|
53
|
+
|
|
54
|
+
private _dataAttributes: string[] = [];
|
|
55
|
+
private _element?: Element;
|
|
56
|
+
private _named!: NamedArgs<ContainerQueryModifierSignature>;
|
|
57
|
+
|
|
58
|
+
get dataAttributePrefix(): string {
|
|
59
|
+
return this._named.dataAttributePrefix ?? 'container-query';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get debounce(): number {
|
|
63
|
+
return this._named.debounce ?? 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get features(): Features {
|
|
67
|
+
return this._named.features ?? {};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
constructor(owner: unknown, args: ArgsFor<ContainerQueryModifierSignature>) {
|
|
71
|
+
super(owner, args);
|
|
72
|
+
|
|
73
|
+
registerDestructor(this, () => {
|
|
74
|
+
this.resizeObserver.unobserve(this._element, this.onResize);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
modify(
|
|
79
|
+
element: Element,
|
|
80
|
+
_positional: PositionalArgs<ContainerQueryModifierSignature>,
|
|
81
|
+
named: NamedArgs<ContainerQueryModifierSignature>
|
|
82
|
+
): void {
|
|
83
|
+
this._named = named;
|
|
84
|
+
|
|
85
|
+
this.registerResizeObserver(element);
|
|
86
|
+
this.queryContainer(element);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@action private onResize(resizeObserverEntry: ResizeObserverEntry): void {
|
|
90
|
+
const element = resizeObserverEntry.target;
|
|
91
|
+
|
|
92
|
+
if (this.debounce > 0) {
|
|
93
|
+
_debounce(this, this.queryContainer, element, this.debounce);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.queryContainer(element);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private registerResizeObserver(element: Element): void {
|
|
101
|
+
this.resizeObserver.unobserve(this._element, this.onResize);
|
|
102
|
+
|
|
103
|
+
this._element = element;
|
|
104
|
+
this.resizeObserver.observe(this._element, this.onResize);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private queryContainer(element: Element): void {
|
|
108
|
+
this.measureDimensions(element);
|
|
109
|
+
this.evaluateQueries();
|
|
110
|
+
this.resetDataAttributes(element);
|
|
111
|
+
this.setDataAttributes(element);
|
|
112
|
+
|
|
113
|
+
this._named.onQuery?.({
|
|
114
|
+
dimensions: this.dimensions,
|
|
115
|
+
queryResults: this.queryResults,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private measureDimensions(element: Element): void {
|
|
120
|
+
const height = element.clientHeight;
|
|
121
|
+
const width = element.clientWidth;
|
|
122
|
+
|
|
123
|
+
this.dimensions = {
|
|
124
|
+
aspectRatio: width / height,
|
|
125
|
+
height,
|
|
126
|
+
width,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private evaluateQueries(): void {
|
|
131
|
+
const queryResults = {} as QueryResults;
|
|
132
|
+
|
|
133
|
+
for (const [featureName, metadata] of Object.entries(this.features)) {
|
|
134
|
+
const { dimension, min, max } = metadata;
|
|
135
|
+
const value = this.dimensions[dimension];
|
|
136
|
+
|
|
137
|
+
queryResults[featureName] = min <= value && value < max;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.queryResults = queryResults;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private resetDataAttributes(element: Element): void {
|
|
144
|
+
this._dataAttributes.forEach((dataAttribute) => {
|
|
145
|
+
element.removeAttribute(dataAttribute);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
this._dataAttributes = [];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private setDataAttributes(element: Element): void {
|
|
152
|
+
const prefix = this.dataAttributePrefix;
|
|
153
|
+
|
|
154
|
+
for (const [featureName, meetsFeature] of Object.entries(
|
|
155
|
+
this.queryResults
|
|
156
|
+
)) {
|
|
157
|
+
if (!meetsFeature) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const dataAttribute = prefix
|
|
162
|
+
? `data-${prefix}-${featureName}`
|
|
163
|
+
: `data-${featureName}`;
|
|
164
|
+
|
|
165
|
+
element.setAttribute(dataAttribute, '');
|
|
166
|
+
|
|
167
|
+
this._dataAttributes.push(dataAttribute);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from 'ember-container-query/modifiers/container-query';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import type { Dimensions, Features, QueryResults } from 'ember-container-query/modifiers/container-query';
|
|
3
|
+
interface ContainerQueryComponentArgs {
|
|
4
|
+
dataAttributePrefix?: string;
|
|
5
|
+
debounce?: number;
|
|
6
|
+
features?: Features;
|
|
7
|
+
tagName?: string;
|
|
8
|
+
}
|
|
9
|
+
export default class ContainerQueryComponent extends Component<ContainerQueryComponentArgs> {
|
|
10
|
+
dimensions?: Dimensions;
|
|
11
|
+
queryResults?: QueryResults;
|
|
12
|
+
tagName: string;
|
|
13
|
+
updateState({ dimensions, queryResults, }: {
|
|
14
|
+
dimensions: Dimensions;
|
|
15
|
+
queryResults: QueryResults;
|
|
16
|
+
}): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=container-query.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
2
|
+
declare const _default: import("@ember/component/helper").FunctionBasedHelper<{
|
|
3
|
+
Args: {
|
|
4
|
+
Positional: unknown[];
|
|
5
|
+
Named: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
Return: Metadata;
|
|
8
|
+
}>;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=cq-aspect-ratio.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
2
|
+
declare const _default: import("@ember/component/helper").FunctionBasedHelper<{
|
|
3
|
+
Args: {
|
|
4
|
+
Positional: unknown[];
|
|
5
|
+
Named: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
Return: Metadata;
|
|
8
|
+
}>;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=cq-height.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Metadata } from 'ember-container-query/modifiers/container-query';
|
|
2
|
+
declare const _default: import("@ember/component/helper").FunctionBasedHelper<{
|
|
3
|
+
Args: {
|
|
4
|
+
Positional: unknown[];
|
|
5
|
+
Named: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
Return: Metadata;
|
|
8
|
+
}>;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=cq-width.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Modifier, { ArgsFor, NamedArgs, PositionalArgs } from 'ember-modifier';
|
|
2
|
+
export type Metadata = {
|
|
3
|
+
dimension: 'aspectRatio' | 'height' | 'width';
|
|
4
|
+
max: number;
|
|
5
|
+
min: number;
|
|
6
|
+
};
|
|
7
|
+
export type Features = {
|
|
8
|
+
[featureName: string]: Metadata;
|
|
9
|
+
};
|
|
10
|
+
export type Dimensions = {
|
|
11
|
+
aspectRatio: number;
|
|
12
|
+
height: number;
|
|
13
|
+
width: number;
|
|
14
|
+
};
|
|
15
|
+
export type QueryResults = {
|
|
16
|
+
[featureName: string]: boolean;
|
|
17
|
+
};
|
|
18
|
+
interface ContainerQueryModifierSignature {
|
|
19
|
+
Args: {
|
|
20
|
+
Named: {
|
|
21
|
+
dataAttributePrefix?: string;
|
|
22
|
+
debounce?: number;
|
|
23
|
+
features?: Features;
|
|
24
|
+
onQuery?: ({ dimensions, queryResults, }: {
|
|
25
|
+
dimensions: Dimensions;
|
|
26
|
+
queryResults: QueryResults;
|
|
27
|
+
}) => void;
|
|
28
|
+
};
|
|
29
|
+
Positional: [];
|
|
30
|
+
};
|
|
31
|
+
Element: Element;
|
|
32
|
+
}
|
|
33
|
+
export default class ContainerQueryModifier extends Modifier<ContainerQueryModifierSignature> {
|
|
34
|
+
private readonly resizeObserver;
|
|
35
|
+
dimensions: Dimensions;
|
|
36
|
+
queryResults: QueryResults;
|
|
37
|
+
private _dataAttributes;
|
|
38
|
+
private _element?;
|
|
39
|
+
private _named;
|
|
40
|
+
get dataAttributePrefix(): string;
|
|
41
|
+
get debounce(): number;
|
|
42
|
+
get features(): Features;
|
|
43
|
+
constructor(owner: unknown, args: ArgsFor<ContainerQueryModifierSignature>);
|
|
44
|
+
modify(element: Element, _positional: PositionalArgs<ContainerQueryModifierSignature>, named: NamedArgs<ContainerQueryModifierSignature>): void;
|
|
45
|
+
private onResize;
|
|
46
|
+
private registerResizeObserver;
|
|
47
|
+
private queryContainer;
|
|
48
|
+
private measureDimensions;
|
|
49
|
+
private evaluateQueries;
|
|
50
|
+
private resetDataAttributes;
|
|
51
|
+
private setDataAttributes;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=container-query.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-container-query",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Container queries using Ember modifiers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"container-queries",
|
|
@@ -26,13 +26,18 @@
|
|
|
26
26
|
"build": "ember build --environment=production",
|
|
27
27
|
"build:test": "ember build --environment=test",
|
|
28
28
|
"changelog": "lerna-changelog",
|
|
29
|
-
"lint": "
|
|
29
|
+
"lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
|
|
30
|
+
"lint:css": "stylelint \"tests/dummy/app/**/*.css\" --cache",
|
|
31
|
+
"lint:css:fix": "stylelint \"tests/dummy/app/**/*.css\" --fix",
|
|
30
32
|
"lint:dependency": "ember dependency-lint",
|
|
31
|
-
"lint:fix": "npm
|
|
33
|
+
"lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
|
|
32
34
|
"lint:hbs": "ember-template-lint .",
|
|
33
35
|
"lint:hbs:fix": "ember-template-lint . --fix",
|
|
34
|
-
"lint:js": "eslint . --cache",
|
|
36
|
+
"lint:js": "eslint . --cache --ext=.js,.ts",
|
|
35
37
|
"lint:js:fix": "eslint . --fix",
|
|
38
|
+
"lint:types": "tsc --noEmit",
|
|
39
|
+
"prepack": "ember ts:precompile",
|
|
40
|
+
"postpack": "ember ts:clean",
|
|
36
41
|
"start": "ember serve",
|
|
37
42
|
"test": "DEVICE='w3-h3' ember test",
|
|
38
43
|
"test:ember": "ember test",
|
|
@@ -49,30 +54,58 @@
|
|
|
49
54
|
}
|
|
50
55
|
},
|
|
51
56
|
"dependencies": {
|
|
52
|
-
"@ember/render-modifiers": "^2.0.4",
|
|
53
57
|
"ember-cli-babel": "^7.26.11",
|
|
54
|
-
"ember-cli-htmlbars": "^6.
|
|
58
|
+
"ember-cli-htmlbars": "^6.1.1",
|
|
59
|
+
"ember-cli-typescript": "^5.2.1",
|
|
55
60
|
"ember-element-helper": "^0.6.1",
|
|
56
|
-
"ember-
|
|
61
|
+
"ember-modifier": "^3.2.7",
|
|
62
|
+
"ember-resize-observer-service": "^1.1.0",
|
|
63
|
+
"ember-test-selectors": "^6.0.0"
|
|
57
64
|
},
|
|
58
65
|
"devDependencies": {
|
|
59
66
|
"@ember/optional-features": "^2.0.0",
|
|
60
|
-
"@ember/test-helpers": "^2.
|
|
61
|
-
"@embroider/test-setup": "^
|
|
67
|
+
"@ember/test-helpers": "^2.8.1",
|
|
68
|
+
"@embroider/test-setup": "^2.0.2",
|
|
62
69
|
"@glimmer/component": "^1.1.2",
|
|
63
70
|
"@glimmer/tracking": "^1.1.2",
|
|
64
|
-
"@percy/cli": "^1.
|
|
65
|
-
"@percy/ember": "^
|
|
66
|
-
"
|
|
71
|
+
"@percy/cli": "^1.16.0",
|
|
72
|
+
"@percy/ember": "^4.0.0",
|
|
73
|
+
"@types/ember-qunit": "^5.0.2",
|
|
74
|
+
"@types/ember-resolver": "^5.0.13",
|
|
75
|
+
"@types/ember__application": "^4.0.4",
|
|
76
|
+
"@types/ember__array": "^4.0.3",
|
|
77
|
+
"@types/ember__component": "^4.0.11",
|
|
78
|
+
"@types/ember__controller": "^4.0.4",
|
|
79
|
+
"@types/ember__debug": "^4.0.3",
|
|
80
|
+
"@types/ember__destroyable": "^4.0.1",
|
|
81
|
+
"@types/ember__engine": "^4.0.4",
|
|
82
|
+
"@types/ember__error": "^4.0.1",
|
|
83
|
+
"@types/ember__object": "^4.0.5",
|
|
84
|
+
"@types/ember__polyfills": "^4.0.1",
|
|
85
|
+
"@types/ember__routing": "^4.0.12",
|
|
86
|
+
"@types/ember__runloop": "^4.0.2",
|
|
87
|
+
"@types/ember__service": "^4.0.1",
|
|
88
|
+
"@types/ember__string": "^3.0.10",
|
|
89
|
+
"@types/ember__template": "^4.0.1",
|
|
90
|
+
"@types/ember__test": "^4.0.1",
|
|
91
|
+
"@types/ember__test-helpers": "^2.8.2",
|
|
92
|
+
"@types/ember__utils": "^4.0.2",
|
|
93
|
+
"@types/htmlbars-inline-precompile": "^3.0.0",
|
|
94
|
+
"@types/qunit": "^2.19.3",
|
|
95
|
+
"@types/rsvp": "^4.0.4",
|
|
96
|
+
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
|
97
|
+
"@typescript-eslint/parser": "^5.45.0",
|
|
67
98
|
"broccoli-asset-rev": "^3.0.0",
|
|
68
|
-
"
|
|
99
|
+
"concurrently": "^7.6.0",
|
|
100
|
+
"d3-array": "^3.2.0",
|
|
69
101
|
"d3-axis": "^3.0.0",
|
|
70
102
|
"d3-scale": "^4.0.2",
|
|
71
103
|
"d3-selection": "^3.0.0",
|
|
72
104
|
"d3-shape": "^3.1.0",
|
|
105
|
+
"ember-a11y-refocus": "^3.0.2",
|
|
73
106
|
"ember-a11y-testing": "^5.0.0",
|
|
74
|
-
"ember-auto-import": "^2.
|
|
75
|
-
"ember-cli": "~4.
|
|
107
|
+
"ember-auto-import": "^2.5.0",
|
|
108
|
+
"ember-cli": "~4.8.0",
|
|
76
109
|
"ember-cli-dependency-checker": "^3.3.1",
|
|
77
110
|
"ember-cli-dependency-lint": "^2.0.1",
|
|
78
111
|
"ember-cli-inject-live-reload": "^2.1.0",
|
|
@@ -81,31 +114,35 @@
|
|
|
81
114
|
"ember-cli-terser": "^4.0.2",
|
|
82
115
|
"ember-css-modules": "^2.0.1",
|
|
83
116
|
"ember-disable-prototype-extensions": "^1.1.3",
|
|
84
|
-
"ember-export-application-global": "^2.0.1",
|
|
85
117
|
"ember-load-initializers": "^2.1.2",
|
|
86
118
|
"ember-named-blocks-polyfill": "^0.2.5",
|
|
87
119
|
"ember-page-title": "^7.0.0",
|
|
88
|
-
"ember-qunit": "^
|
|
120
|
+
"ember-qunit": "^6.0.0",
|
|
89
121
|
"ember-resolver": "^8.0.3",
|
|
90
|
-
"ember-source": "~4.
|
|
122
|
+
"ember-source": "~4.8.0",
|
|
91
123
|
"ember-source-channel-url": "^3.0.0",
|
|
92
|
-
"ember-svg-jar": "^2.
|
|
93
|
-
"ember-template-lint": "^
|
|
94
|
-
"ember-
|
|
95
|
-
"ember-truth-helpers": "^3.0.0",
|
|
124
|
+
"ember-svg-jar": "^2.4.2",
|
|
125
|
+
"ember-template-lint": "^5.0.2",
|
|
126
|
+
"ember-truth-helpers": "^3.1.1",
|
|
96
127
|
"ember-try": "^2.0.0",
|
|
97
|
-
"eslint": "^
|
|
128
|
+
"eslint": "^8.28.0",
|
|
98
129
|
"eslint-config-prettier": "^8.5.0",
|
|
99
|
-
"eslint-plugin-ember": "^
|
|
100
|
-
"eslint-plugin-
|
|
101
|
-
"eslint-plugin-prettier": "^4.
|
|
130
|
+
"eslint-plugin-ember": "^11.2.1",
|
|
131
|
+
"eslint-plugin-n": "^15.5.1",
|
|
132
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
133
|
+
"eslint-plugin-qunit": "^7.3.4",
|
|
134
|
+
"eslint-plugin-simple-import-sort": "^8.0.0",
|
|
102
135
|
"lerna-changelog": "^2.2.0",
|
|
103
136
|
"loader.js": "^4.7.0",
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"qunit": "^2.18.2",
|
|
137
|
+
"prettier": "^2.8.0",
|
|
138
|
+
"qunit": "^2.19.3",
|
|
107
139
|
"qunit-dom": "^2.0.0",
|
|
108
|
-
"
|
|
140
|
+
"stylelint": "^14.15.0",
|
|
141
|
+
"stylelint-config-standard": "^29.0.0",
|
|
142
|
+
"stylelint-no-unsupported-browser-features": "^6.0.1",
|
|
143
|
+
"stylelint-order": "^5.0.0",
|
|
144
|
+
"typescript": "^4.9.3",
|
|
145
|
+
"webpack": "^5.75.0"
|
|
109
146
|
},
|
|
110
147
|
"engines": {
|
|
111
148
|
"node": "12.* || 14.* || >= 16"
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ES2020",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
|
|
7
|
+
// Trying to check Ember apps and addons with `allowJs: true` is a recipe
|
|
8
|
+
// for many unresolveable type errors, because with *considerable* extra
|
|
9
|
+
// configuration it ends up including many files which are *not* valid and
|
|
10
|
+
// cannot be: they *appear* to be resolve-able to TS, but are in fact not in
|
|
11
|
+
// valid Node-resolveable locations and may not have TS-ready types. This
|
|
12
|
+
// will likely improve over time
|
|
13
|
+
"allowJs": false,
|
|
14
|
+
|
|
15
|
+
// Don't check the types of dependencies
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
|
|
18
|
+
// --- TS for SemVer Types compatibility
|
|
19
|
+
// Strictness settings -- you should *not* change these: Ember code is not
|
|
20
|
+
// guaranteed to type check with these set to looser values.
|
|
21
|
+
"strict": true,
|
|
22
|
+
"noUncheckedIndexedAccess": true,
|
|
23
|
+
|
|
24
|
+
// Interop: these are viral and will require anyone downstream of your
|
|
25
|
+
// package to *also* set them to true. If you *must* enable them to consume
|
|
26
|
+
// an upstream package, you should document that for downstream consumers to
|
|
27
|
+
// be aware of.
|
|
28
|
+
//
|
|
29
|
+
// These *are* safe for apps to enable, since they do not *have* downstream
|
|
30
|
+
// consumers; but leaving them off is still preferred when possible, since
|
|
31
|
+
// it makes it easier to switch between apps and addons and have the same
|
|
32
|
+
// rules for what can be imported and how.
|
|
33
|
+
"allowSyntheticDefaultImports": false,
|
|
34
|
+
"esModuleInterop": false,
|
|
35
|
+
|
|
36
|
+
// --- Lint-style rules
|
|
37
|
+
|
|
38
|
+
// TypeScript also supplies some lint-style checks; nearly all of them are
|
|
39
|
+
// better handled by ESLint with the `@typescript-eslint`. This one is more
|
|
40
|
+
// like a safety check, though, so we leave it on.
|
|
41
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
42
|
+
|
|
43
|
+
// --- Compilation/integration settings
|
|
44
|
+
// Setting `noEmitOnError` here allows ember-cli-typescript to catch errors
|
|
45
|
+
// and inject them into Ember CLI's build error reporting, which provides
|
|
46
|
+
// nice feedback for when
|
|
47
|
+
"noEmitOnError": false,
|
|
48
|
+
|
|
49
|
+
// We use Babel for emitting runtime code, because it's very important that
|
|
50
|
+
// we always and only use the same transpiler for non-stable features, in
|
|
51
|
+
// particular decorators. If you were to change this to `true`, it could
|
|
52
|
+
// lead to accidentally generating code with `tsc` instead of Babel, and
|
|
53
|
+
// could thereby result in broken code at runtime.
|
|
54
|
+
"noEmit": true,
|
|
55
|
+
|
|
56
|
+
// Ember makes heavy use of decorators; TS does not support them at all
|
|
57
|
+
// without this flag.
|
|
58
|
+
"experimentalDecorators": true,
|
|
59
|
+
|
|
60
|
+
// Support generation of source maps. Note: you must *also* enable source
|
|
61
|
+
// maps in your `ember-cli-babel` config and/or `babel.config.js`.
|
|
62
|
+
"declaration": true,
|
|
63
|
+
"declarationMap": true,
|
|
64
|
+
"inlineSourceMap": true,
|
|
65
|
+
"inlineSources": true,
|
|
66
|
+
|
|
67
|
+
// The combination of `baseUrl` with `paths` allows Ember's classic package
|
|
68
|
+
// layout, which is not resolveable with the Node resolution algorithm, to
|
|
69
|
+
// work with TypeScript.
|
|
70
|
+
"baseUrl": ".",
|
|
71
|
+
"paths": {
|
|
72
|
+
"dummy/tests/*": [
|
|
73
|
+
"tests/*"
|
|
74
|
+
],
|
|
75
|
+
"dummy/*": [
|
|
76
|
+
"tests/dummy/app/*",
|
|
77
|
+
"app/*"
|
|
78
|
+
],
|
|
79
|
+
"ember-container-query": [
|
|
80
|
+
"addon"
|
|
81
|
+
],
|
|
82
|
+
"ember-container-query/*": [
|
|
83
|
+
"addon/*"
|
|
84
|
+
],
|
|
85
|
+
"ember-container-query/test-support": [
|
|
86
|
+
"addon-test-support"
|
|
87
|
+
],
|
|
88
|
+
"ember-container-query/test-support/*": [
|
|
89
|
+
"addon-test-support/*"
|
|
90
|
+
],
|
|
91
|
+
"*": [
|
|
92
|
+
"types/*"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"include": [
|
|
97
|
+
"app/**/*",
|
|
98
|
+
"addon/**/*",
|
|
99
|
+
"tests/**/*",
|
|
100
|
+
"types/**/*",
|
|
101
|
+
"test-support/**/*",
|
|
102
|
+
"addon-test-support/**/*"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
File without changes
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { action } from '@ember/object';
|
|
2
|
-
import Component from '@glimmer/component';
|
|
3
|
-
import { tracked } from '@glimmer/tracking';
|
|
4
|
-
import { debounce } from '@ember/runloop';
|
|
5
|
-
|
|
6
|
-
export default class ContainerQueryComponent extends Component {
|
|
7
|
-
@tracked queryResults = {};
|
|
8
|
-
@tracked aspectRatio;
|
|
9
|
-
@tracked height;
|
|
10
|
-
@tracked width;
|
|
11
|
-
|
|
12
|
-
get features() {
|
|
13
|
-
return this.args.features ?? {};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get dataAttributePrefix() {
|
|
17
|
-
return this.args.dataAttributePrefix ?? 'container-query';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get debounce() {
|
|
21
|
-
return this.args.debounce ?? 0;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// The dynamic tag is restricted to be immutable
|
|
25
|
-
tagName = this.args.tagName ?? 'div';
|
|
26
|
-
|
|
27
|
-
@action onResize(resizeObserverEntry) {
|
|
28
|
-
const element = resizeObserverEntry.target;
|
|
29
|
-
|
|
30
|
-
if (this.debounce > 0) {
|
|
31
|
-
debounce(this, this.queryContainer, element, this.debounce);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
this.queryContainer(element);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
@action queryContainer(element) {
|
|
39
|
-
this.measureDimensions(element);
|
|
40
|
-
this.evaluateQueries();
|
|
41
|
-
this.setDataAttributes(element);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
measureDimensions(element) {
|
|
45
|
-
this.height = element.clientHeight;
|
|
46
|
-
this.width = element.clientWidth;
|
|
47
|
-
this.aspectRatio = this.width / this.height;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
evaluateQueries() {
|
|
51
|
-
const queryResults = {};
|
|
52
|
-
|
|
53
|
-
for (const [featureName, metadata] of Object.entries(this.features)) {
|
|
54
|
-
const { dimension, min, max } = metadata;
|
|
55
|
-
const value = this[dimension];
|
|
56
|
-
|
|
57
|
-
queryResults[featureName] = min <= value && value < max;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
this.queryResults = queryResults;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
setDataAttributes(element) {
|
|
64
|
-
const prefix = this.dataAttributePrefix;
|
|
65
|
-
|
|
66
|
-
for (const [featureName, meetsFeature] of Object.entries(
|
|
67
|
-
this.queryResults
|
|
68
|
-
)) {
|
|
69
|
-
let attributeName;
|
|
70
|
-
|
|
71
|
-
if (prefix) {
|
|
72
|
-
attributeName = `data-${prefix}-${featureName}`;
|
|
73
|
-
} else {
|
|
74
|
-
attributeName = `data-${featureName}`;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (meetsFeature) {
|
|
78
|
-
element.setAttribute(attributeName, '');
|
|
79
|
-
} else {
|
|
80
|
-
element.removeAttribute(attributeName);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|