@edgeandnode/eds-react 1.1.0 → 1.2.0
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/README.md +27 -3
- package/dist/components/Address.d.ts +3 -3
- package/dist/components/Address.d.ts.map +1 -1
- package/dist/components/Address.js +1 -1
- package/dist/components/Address.js.map +1 -1
- package/dist/components/Avatar.d.ts +3 -3
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js +13 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Breadcrumbs.parts.d.ts +3 -3
- package/dist/components/Breadcrumbs.parts.d.ts.map +1 -1
- package/dist/components/Breadcrumbs.parts.js +1 -1
- package/dist/components/Breadcrumbs.parts.js.map +1 -1
- package/dist/components/Button.js +1 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Card.js +1 -1
- package/dist/components/Card.js.map +1 -1
- package/dist/components/Chip.parts.d.ts.map +1 -1
- package/dist/components/Chip.parts.js +1 -1
- package/dist/components/Chip.parts.js.map +1 -1
- package/dist/components/Cluster.d.ts +3 -3
- package/dist/components/Cluster.d.ts.map +1 -1
- package/dist/components/Cluster.js.map +1 -1
- package/dist/components/Icon.d.ts.map +1 -1
- package/dist/components/Icon.js +0 -2
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +2 -0
- package/dist/components/Link.js.map +1 -1
- package/dist/components/Menu.parts.js +1 -1
- package/dist/components/Menu.parts.js.map +1 -1
- package/dist/components/Search.d.ts.map +1 -1
- package/dist/components/Search.js +1 -1
- package/dist/components/Search.js.map +1 -1
- package/dist/components/SegmentedControl.parts.d.ts.map +1 -1
- package/dist/components/SegmentedControl.parts.js +1 -1
- package/dist/components/SegmentedControl.parts.js.map +1 -1
- package/dist/components/TabSet.parts.js +1 -1
- package/dist/components/TabSet.parts.js.map +1 -1
- package/dist/components/Tooltip.parts.d.ts.map +1 -1
- package/dist/components/Tooltip.parts.js.map +1 -1
- package/dist/components/base/Checkable.parts.js +1 -1
- package/dist/components/base/Checkable.parts.js.map +1 -1
- package/dist/components/base/Field.parts.js +1 -1
- package/dist/components/base/Field.parts.js.map +1 -1
- package/dist/components/base/Portal.js +3 -3
- package/dist/components/base/Portal.js.map +1 -1
- package/dist/components/base/Transition.js +1 -1
- package/dist/components/base/Transition.js.map +1 -1
- package/dist/hooks/useCSSPropsPolyfill.d.ts.map +1 -1
- package/dist/hooks/useCSSPropsPolyfill.js +7 -19
- package/dist/hooks/useCSSPropsPolyfill.js.map +1 -1
- package/dist/hooks/useCSSState.d.ts +4 -0
- package/dist/hooks/useCSSState.d.ts.map +1 -1
- package/dist/hooks/useCSSState.js +24 -6
- package/dist/hooks/useCSSState.js.map +1 -1
- package/dist/hooks/useStyleObserver.d.ts.map +1 -1
- package/dist/hooks/useStyleObserver.js +9 -5
- package/dist/hooks/useStyleObserver.js.map +1 -1
- package/dist/postcss-plugin.d.ts +2 -0
- package/dist/postcss-plugin.d.ts.map +1 -0
- package/dist/postcss-plugin.js +2 -0
- package/dist/postcss-plugin.js.map +1 -0
- package/dist/utils/internal/BatchedElementStyleObserver.d.ts +13 -0
- package/dist/utils/internal/BatchedElementStyleObserver.d.ts.map +1 -0
- package/dist/utils/internal/BatchedElementStyleObserver.js +28 -0
- package/dist/utils/internal/BatchedElementStyleObserver.js.map +1 -0
- package/dist/utils/internal/getStyleQueriesSupported.d.ts +2 -0
- package/dist/utils/internal/getStyleQueriesSupported.d.ts.map +1 -0
- package/dist/utils/internal/getStyleQueriesSupported.js +12 -0
- package/dist/utils/internal/getStyleQueriesSupported.js.map +1 -0
- package/dist/utils/internal/index.d.ts +2 -0
- package/dist/utils/internal/index.d.ts.map +1 -1
- package/dist/utils/internal/index.js +2 -0
- package/dist/utils/internal/index.js.map +1 -1
- package/dist/utils/internal/styleScheduler.d.ts +8 -3
- package/dist/utils/internal/styleScheduler.d.ts.map +1 -1
- package/dist/utils/internal/styleScheduler.js +46 -16
- package/dist/utils/internal/styleScheduler.js.map +1 -1
- package/dist/utils/styleObserver.d.ts +2 -0
- package/dist/utils/styleObserver.d.ts.map +1 -1
- package/dist/utils/styleObserver.js +40 -33
- package/dist/utils/styleObserver.js.map +1 -1
- package/dist/vite-plugin.d.ts +2 -0
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.js +2 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +13 -11
- package/scripts/update-skill.cjs +42 -0
- package/skill/SKILL.md +18 -14
- package/src/components/Address.tsx +12 -10
- package/src/components/Avatar.tsx +61 -49
- package/src/components/Breadcrumbs.parts.tsx +11 -9
- package/src/components/Button.tsx +1 -1
- package/src/components/Card.tsx +1 -1
- package/src/components/Chip.parts.tsx +9 -6
- package/src/components/Cluster.tsx +3 -5
- package/src/components/Icon.tsx +0 -2
- package/src/components/Link.tsx +2 -0
- package/src/components/Menu.parts.tsx +1 -1
- package/src/components/Search.tsx +9 -6
- package/src/components/SegmentedControl.parts.tsx +8 -5
- package/src/components/TabSet.parts.tsx +1 -1
- package/src/components/Tooltip.parts.tsx +4 -1
- package/src/components/base/Checkable.parts.tsx +1 -1
- package/src/components/base/Field.parts.tsx +1 -1
- package/src/components/base/Portal.tsx +3 -3
- package/src/components/base/Transition.tsx +1 -1
- package/src/hooks/useCSSPropsPolyfill.ts +7 -20
- package/src/hooks/useCSSState.ts +29 -8
- package/src/hooks/useStyleObserver.ts +18 -14
- package/src/postcss-plugin.ts +1 -0
- package/src/utils/internal/BatchedElementStyleObserver.ts +31 -0
- package/src/utils/internal/getStyleQueriesSupported.ts +11 -0
- package/src/utils/internal/index.ts +2 -0
- package/src/utils/internal/styleScheduler.ts +43 -15
- package/src/utils/styleObserver.ts +38 -40
- package/src/vite-plugin.ts +1 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Batched style scheduler that collects style operations within a single frame and executes them
|
|
3
|
-
* together using `requestAnimationFrame`.
|
|
4
|
-
* into a single reflow.
|
|
3
|
+
* together using `requestAnimationFrame`. Reads run before writes to avoid layout thrashing.
|
|
5
4
|
*
|
|
6
5
|
* @example
|
|
7
6
|
* ````ts
|
|
@@ -23,8 +22,9 @@
|
|
|
23
22
|
*/
|
|
24
23
|
|
|
25
24
|
class StyleScheduler {
|
|
26
|
-
private
|
|
27
|
-
private pending
|
|
25
|
+
private animationFrameId: number | null = null
|
|
26
|
+
private pending = new Set<() => void>()
|
|
27
|
+
private pendingWrites = new Set<() => void>()
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Schedule an operation to be executed in the next animation frame. All operations scheduled
|
|
@@ -32,24 +32,52 @@ class StyleScheduler {
|
|
|
32
32
|
* Returns a function that cancels the scheduled callback if it hasn't run yet.
|
|
33
33
|
*/
|
|
34
34
|
schedule(callback: () => void): () => void {
|
|
35
|
-
this.
|
|
35
|
+
return this.enqueue(callback, this.pending)
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.rafId = null
|
|
38
|
+
/** Schedule a write after all reads in the frame, including writes queued during those reads. */
|
|
39
|
+
scheduleWrite(callback: () => void): () => void {
|
|
40
|
+
return this.enqueue(callback, this.pendingWrites)
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
private enqueue(callback: () => void, queue: Set<() => void>): () => void {
|
|
44
|
+
const operation = () => callback()
|
|
45
|
+
queue.add(operation)
|
|
46
|
+
this.requestFrame()
|
|
47
|
+
return () => {
|
|
48
|
+
queue.delete(operation)
|
|
45
49
|
}
|
|
50
|
+
}
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
private runBatch(queue: Set<() => void>) {
|
|
53
|
+
try {
|
|
54
|
+
for (const callback of queue) {
|
|
55
|
+
queue.delete(callback)
|
|
56
|
+
callback()
|
|
57
|
+
}
|
|
58
|
+
} finally {
|
|
59
|
+
// Cancellation closures can outlive the batch, including when a callback throws.
|
|
60
|
+
queue.clear()
|
|
50
61
|
}
|
|
51
62
|
}
|
|
52
63
|
|
|
64
|
+
private requestFrame() {
|
|
65
|
+
if (this.animationFrameId !== null) return
|
|
66
|
+
this.animationFrameId = requestAnimationFrame(() => {
|
|
67
|
+
const callbacks = this.pending
|
|
68
|
+
this.pending = new Set()
|
|
69
|
+
try {
|
|
70
|
+
this.runBatch(callbacks)
|
|
71
|
+
const writes = this.pendingWrites
|
|
72
|
+
this.pendingWrites = new Set()
|
|
73
|
+
this.runBatch(writes)
|
|
74
|
+
} finally {
|
|
75
|
+
this.animationFrameId = null
|
|
76
|
+
if (this.pending.size > 0 || this.pendingWrites.size > 0) this.requestFrame()
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
53
81
|
/**
|
|
54
82
|
* Get computed style for an element in a batched manner. Returns a promise that resolves with the
|
|
55
83
|
* computed style once all batched operations are executed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import StyleObserver from 'style-observer'
|
|
2
2
|
|
|
3
|
-
import { styleScheduler } from './internal/index.ts'
|
|
3
|
+
import { BatchedElementStyleObserver, styleScheduler } from './internal/index.ts'
|
|
4
4
|
|
|
5
5
|
export interface StyleObserverRecord<T extends string = string> {
|
|
6
6
|
target: Element
|
|
@@ -59,14 +59,6 @@ class StyleObserverManager {
|
|
|
59
59
|
this.subscriptions.set(element, elementSubscriptions)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
let elementObserved = this.observed.get(element)
|
|
63
|
-
if (!elementObserved) {
|
|
64
|
-
elementObserved = new Set()
|
|
65
|
-
this.observed.set(element, elementObserved)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const newProperties: string[] = []
|
|
69
|
-
|
|
70
62
|
for (const property of properties) {
|
|
71
63
|
let propertySubscriptions = elementSubscriptions.get(property)
|
|
72
64
|
if (!propertySubscriptions) {
|
|
@@ -74,49 +66,55 @@ class StyleObserverManager {
|
|
|
74
66
|
elementSubscriptions.set(property, propertySubscriptions)
|
|
75
67
|
}
|
|
76
68
|
propertySubscriptions.add(callback)
|
|
77
|
-
|
|
78
|
-
if (!elementObserved.has(property)) {
|
|
79
|
-
newProperties.push(property)
|
|
80
|
-
elementObserved.add(property)
|
|
81
|
-
}
|
|
82
69
|
}
|
|
83
70
|
|
|
84
|
-
|
|
85
|
-
const cancelObserve =
|
|
86
|
-
newProperties.length > 0
|
|
87
|
-
? styleScheduler.schedule(() => {
|
|
88
|
-
this.observer.observe(element, newProperties)
|
|
89
|
-
})
|
|
90
|
-
: undefined
|
|
71
|
+
this.scheduleUpdate(element)
|
|
91
72
|
|
|
92
73
|
return () => {
|
|
93
|
-
cancelObserve?.()
|
|
94
|
-
|
|
95
|
-
const removedProperties: string[] = []
|
|
96
|
-
|
|
97
74
|
for (const property of properties) {
|
|
98
75
|
const propertySubscriptions = elementSubscriptions.get(property)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (propertySubscriptions.size === 0) {
|
|
102
|
-
elementSubscriptions.delete(property)
|
|
103
|
-
elementObserved!.delete(property)
|
|
104
|
-
removedProperties.push(property)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
76
|
+
propertySubscriptions?.delete(callback)
|
|
77
|
+
if (propertySubscriptions?.size === 0) elementSubscriptions.delete(property)
|
|
107
78
|
}
|
|
79
|
+
if (elementSubscriptions.size === 0) this.subscriptions.delete(element)
|
|
80
|
+
this.scheduleUpdate(element)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
108
83
|
|
|
109
|
-
|
|
110
|
-
|
|
84
|
+
private pending = new Set<Element>()
|
|
85
|
+
|
|
86
|
+
private scheduleUpdate(element: Element) {
|
|
87
|
+
if (this.pending.has(element)) return
|
|
88
|
+
this.pending.add(element)
|
|
89
|
+
styleScheduler.schedule(() => {
|
|
90
|
+
this.pending.delete(element)
|
|
91
|
+
const properties = new Set(this.subscriptions.get(element)?.keys())
|
|
92
|
+
const observed = this.observed.get(element) ?? new Set<string>()
|
|
93
|
+
const added = [...properties].filter((property) => !observed.has(property))
|
|
94
|
+
const removed = [...observed].filter((property) => !properties.has(property))
|
|
95
|
+
|
|
96
|
+
if (properties.size > 0) {
|
|
97
|
+
this.observed.set(element, properties)
|
|
98
|
+
} else {
|
|
111
99
|
this.observed.delete(element)
|
|
112
100
|
}
|
|
113
101
|
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
102
|
+
if (added.length > 0) {
|
|
103
|
+
if (!this.observer.elementObservers.has(element)) {
|
|
104
|
+
const observer = new BatchedElementStyleObserver(element, (records) => {
|
|
105
|
+
this.observer.changed(records)
|
|
106
|
+
})
|
|
107
|
+
this.observer.elementObservers.set(element, observer)
|
|
108
|
+
styleScheduler.scheduleWrite(() => observer.flush())
|
|
109
|
+
this.observer.observe(element, added)
|
|
110
|
+
} else {
|
|
111
|
+
styleScheduler.scheduleWrite(() => this.observer.observe(element, added))
|
|
112
|
+
}
|
|
118
113
|
}
|
|
119
|
-
|
|
114
|
+
if (removed.length > 0) {
|
|
115
|
+
styleScheduler.scheduleWrite(() => this.observer.unobserve(element, removed))
|
|
116
|
+
}
|
|
117
|
+
})
|
|
120
118
|
}
|
|
121
119
|
}
|
|
122
120
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@edgeandnode/eds-css/vite-plugin'
|