@wordpress/core-data 7.39.1-next.v.202602091733.0 → 7.40.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/CHANGELOG.md +2 -0
- package/README.md +41 -0
- package/build/actions.cjs +52 -0
- package/build/actions.cjs.map +2 -2
- package/build/awareness/base-awareness.cjs +1 -8
- package/build/awareness/base-awareness.cjs.map +2 -2
- package/build/awareness/types.cjs.map +1 -1
- package/build/awareness/utils.cjs +8 -51
- package/build/awareness/utils.cjs.map +2 -2
- package/build/entities.cjs +7 -1
- package/build/entities.cjs.map +2 -2
- package/build/hooks/use-entity-block-editor.cjs +13 -19
- package/build/hooks/use-entity-block-editor.cjs.map +2 -2
- package/build/index.cjs +6 -1
- package/build/index.cjs.map +2 -2
- package/build/private-actions.cjs +8 -0
- package/build/private-actions.cjs.map +2 -2
- package/build/private-apis.cjs +2 -1
- package/build/private-apis.cjs.map +2 -2
- package/build/private-selectors.cjs +5 -0
- package/build/private-selectors.cjs.map +2 -2
- package/build/reducer.cjs +31 -1
- package/build/reducer.cjs.map +2 -2
- package/build/resolvers.cjs +26 -1
- package/build/resolvers.cjs.map +2 -2
- package/build/selectors.cjs +15 -0
- package/build/selectors.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs +5 -3
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt.cjs +23 -19
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/actions.mjs +50 -0
- package/build-module/actions.mjs.map +2 -2
- package/build-module/awareness/base-awareness.mjs +1 -8
- package/build-module/awareness/base-awareness.mjs.map +2 -2
- package/build-module/awareness/utils.mjs +8 -51
- package/build-module/awareness/utils.mjs.map +2 -2
- package/build-module/entities.mjs +7 -1
- package/build-module/entities.mjs.map +2 -2
- package/build-module/hooks/use-entity-block-editor.mjs +13 -19
- package/build-module/hooks/use-entity-block-editor.mjs.map +2 -2
- package/build-module/index.mjs +3 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/private-actions.mjs +7 -0
- package/build-module/private-actions.mjs.map +2 -2
- package/build-module/private-apis.mjs +6 -2
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/private-selectors.mjs +8 -1
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/reducer.mjs +29 -1
- package/build-module/reducer.mjs.map +2 -2
- package/build-module/resolvers.mjs +25 -1
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/selectors.mjs +14 -0
- package/build-module/selectors.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +3 -2
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt.mjs +25 -20
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/actions.d.ts +12 -0
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/awareness/base-awareness.d.ts.map +1 -1
- package/build-types/awareness/test/awareness-state.d.ts +2 -0
- package/build-types/awareness/test/awareness-state.d.ts.map +1 -0
- package/build-types/awareness/test/base-awareness.d.ts +2 -0
- package/build-types/awareness/test/base-awareness.d.ts.map +1 -0
- package/build-types/awareness/test/post-editor-awareness.d.ts +2 -0
- package/build-types/awareness/test/post-editor-awareness.d.ts.map +1 -0
- package/build-types/awareness/test/typed-awareness.d.ts +2 -0
- package/build-types/awareness/test/typed-awareness.d.ts.map +1 -0
- package/build-types/awareness/test/utils.d.ts +2 -0
- package/build-types/awareness/test/utils.d.ts.map +1 -0
- package/build-types/awareness/types.d.ts +0 -1
- package/build-types/awareness/types.d.ts.map +1 -1
- package/build-types/awareness/utils.d.ts +2 -3
- package/build-types/awareness/utils.d.ts.map +1 -1
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/hooks/test/use-post-editor-awareness-state.d.ts +2 -0
- package/build-types/hooks/test/use-post-editor-awareness-state.d.ts.map +1 -0
- package/build-types/hooks/use-entity-block-editor.d.ts.map +1 -1
- package/build-types/index.d.ts +5 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/private-actions.d.ts +8 -0
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts +8 -1
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/reducer.d.ts +23 -0
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +3 -0
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +17 -0
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +9 -0
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts +6 -4
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/package.json +18 -18
- package/src/actions.js +78 -0
- package/src/awareness/base-awareness.ts +1 -14
- package/src/awareness/test/awareness-state.ts +417 -0
- package/src/awareness/test/base-awareness.ts +321 -0
- package/src/awareness/test/post-editor-awareness.ts +561 -0
- package/src/awareness/test/typed-awareness.ts +148 -0
- package/src/awareness/test/utils.ts +305 -0
- package/src/awareness/types.ts +0 -1
- package/src/awareness/utils.ts +8 -82
- package/src/entities.js +7 -1
- package/src/hooks/test/use-post-editor-awareness-state.ts +477 -0
- package/src/hooks/use-entity-block-editor.js +15 -21
- package/src/index.js +7 -0
- package/src/private-actions.js +14 -0
- package/src/private-apis.js +5 -1
- package/src/private-selectors.ts +16 -1
- package/src/reducer.js +45 -0
- package/src/resolvers.js +31 -2
- package/src/selectors.ts +41 -0
- package/src/test/actions.js +79 -0
- package/src/test/entity-provider.js +74 -0
- package/src/test/resolvers.js +2 -0
- package/src/test/store.js +30 -0
- package/src/utils/crdt-blocks.ts +2 -2
- package/src/utils/crdt.ts +44 -29
- package/src/utils/test/crdt.ts +212 -7
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { areCollaboratorInfosEqual, generateCollaboratorInfo } from '../utils';
|
|
5
|
+
import type { CollaboratorInfo } from '../types';
|
|
6
|
+
import type { User } from '../../entity-types';
|
|
7
|
+
|
|
8
|
+
// Mock window.navigator.userAgent
|
|
9
|
+
const mockUserAgent = ( userAgent: string ) => {
|
|
10
|
+
Object.defineProperty( window.navigator, 'userAgent', {
|
|
11
|
+
value: userAgent,
|
|
12
|
+
configurable: true,
|
|
13
|
+
} );
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe( 'Awareness Utils', () => {
|
|
17
|
+
describe( 'arecollaboratorInfosEqual', () => {
|
|
18
|
+
// Shared avatar_urls reference for equality checks
|
|
19
|
+
// (arecollaboratorInfosEqual uses === which compares references for objects)
|
|
20
|
+
const sharedAvatarUrls = {
|
|
21
|
+
'24': 'https://example.com/avatar-24.png',
|
|
22
|
+
'48': 'https://example.com/avatar-48.png',
|
|
23
|
+
'96': 'https://example.com/avatar-96.png',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const createCollaboratorInfo = (
|
|
27
|
+
overrides: Partial< CollaboratorInfo > = {}
|
|
28
|
+
): CollaboratorInfo => ( {
|
|
29
|
+
id: 1,
|
|
30
|
+
name: 'Test User',
|
|
31
|
+
slug: 'test-user',
|
|
32
|
+
avatar_urls: sharedAvatarUrls,
|
|
33
|
+
browserType: 'Chrome',
|
|
34
|
+
enteredAt: 1704067200000,
|
|
35
|
+
...overrides,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
test( 'should return true when both collaboratorInfos are undefined', () => {
|
|
39
|
+
expect( areCollaboratorInfosEqual( undefined, undefined ) ).toBe(
|
|
40
|
+
true
|
|
41
|
+
);
|
|
42
|
+
} );
|
|
43
|
+
|
|
44
|
+
test( 'should return false when first collaboratorInfo is undefined', () => {
|
|
45
|
+
const collaboratorInfo = createCollaboratorInfo();
|
|
46
|
+
expect(
|
|
47
|
+
areCollaboratorInfosEqual( undefined, collaboratorInfo )
|
|
48
|
+
).toBe( false );
|
|
49
|
+
} );
|
|
50
|
+
|
|
51
|
+
test( 'should return false when second collaboratorInfo is undefined', () => {
|
|
52
|
+
const collaboratorInfo = createCollaboratorInfo();
|
|
53
|
+
expect(
|
|
54
|
+
areCollaboratorInfosEqual( collaboratorInfo, undefined )
|
|
55
|
+
).toBe( false );
|
|
56
|
+
} );
|
|
57
|
+
|
|
58
|
+
test( 'should return true when collaboratorInfos are identical', () => {
|
|
59
|
+
const collaboratorInfo1 = createCollaboratorInfo();
|
|
60
|
+
const collaboratorInfo2 = createCollaboratorInfo();
|
|
61
|
+
expect(
|
|
62
|
+
areCollaboratorInfosEqual(
|
|
63
|
+
collaboratorInfo1,
|
|
64
|
+
collaboratorInfo2
|
|
65
|
+
)
|
|
66
|
+
).toBe( true );
|
|
67
|
+
} );
|
|
68
|
+
|
|
69
|
+
test( 'should return false when id differs', () => {
|
|
70
|
+
const collaboratorInfo1 = createCollaboratorInfo( { id: 1 } );
|
|
71
|
+
const collaboratorInfo2 = createCollaboratorInfo( { id: 2 } );
|
|
72
|
+
expect(
|
|
73
|
+
areCollaboratorInfosEqual(
|
|
74
|
+
collaboratorInfo1,
|
|
75
|
+
collaboratorInfo2
|
|
76
|
+
)
|
|
77
|
+
).toBe( false );
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
test( 'should return false when name differs', () => {
|
|
81
|
+
const collaboratorInfo1 = createCollaboratorInfo( {
|
|
82
|
+
name: 'User A',
|
|
83
|
+
} );
|
|
84
|
+
const collaboratorInfo2 = createCollaboratorInfo( {
|
|
85
|
+
name: 'User B',
|
|
86
|
+
} );
|
|
87
|
+
expect(
|
|
88
|
+
areCollaboratorInfosEqual(
|
|
89
|
+
collaboratorInfo1,
|
|
90
|
+
collaboratorInfo2
|
|
91
|
+
)
|
|
92
|
+
).toBe( false );
|
|
93
|
+
} );
|
|
94
|
+
|
|
95
|
+
test( 'should return false when slug differs', () => {
|
|
96
|
+
const collaboratorInfo1 = createCollaboratorInfo( {
|
|
97
|
+
slug: 'user-a',
|
|
98
|
+
} );
|
|
99
|
+
const collaboratorInfo2 = createCollaboratorInfo( {
|
|
100
|
+
slug: 'user-b',
|
|
101
|
+
} );
|
|
102
|
+
expect(
|
|
103
|
+
areCollaboratorInfosEqual(
|
|
104
|
+
collaboratorInfo1,
|
|
105
|
+
collaboratorInfo2
|
|
106
|
+
)
|
|
107
|
+
).toBe( false );
|
|
108
|
+
} );
|
|
109
|
+
|
|
110
|
+
test( 'should return false when browserType differs', () => {
|
|
111
|
+
const collaboratorInfo1 = createCollaboratorInfo( {
|
|
112
|
+
browserType: 'Chrome',
|
|
113
|
+
} );
|
|
114
|
+
const collaboratorInfo2 = createCollaboratorInfo( {
|
|
115
|
+
browserType: 'Firefox',
|
|
116
|
+
} );
|
|
117
|
+
expect(
|
|
118
|
+
areCollaboratorInfosEqual(
|
|
119
|
+
collaboratorInfo1,
|
|
120
|
+
collaboratorInfo2
|
|
121
|
+
)
|
|
122
|
+
).toBe( false );
|
|
123
|
+
} );
|
|
124
|
+
|
|
125
|
+
test( 'should return false when enteredAt differs', () => {
|
|
126
|
+
const collaboratorInfo1 = createCollaboratorInfo( {
|
|
127
|
+
enteredAt: 1000,
|
|
128
|
+
} );
|
|
129
|
+
const collaboratorInfo2 = createCollaboratorInfo( {
|
|
130
|
+
enteredAt: 2000,
|
|
131
|
+
} );
|
|
132
|
+
expect(
|
|
133
|
+
areCollaboratorInfosEqual(
|
|
134
|
+
collaboratorInfo1,
|
|
135
|
+
collaboratorInfo2
|
|
136
|
+
)
|
|
137
|
+
).toBe( false );
|
|
138
|
+
} );
|
|
139
|
+
|
|
140
|
+
test( 'should return false when objects have different number of keys', () => {
|
|
141
|
+
const collaboratorInfo1 = createCollaboratorInfo();
|
|
142
|
+
// Create collaboratorInfo2 with an extra key by casting
|
|
143
|
+
const collaboratorInfo2 = {
|
|
144
|
+
...createCollaboratorInfo(),
|
|
145
|
+
extraKey: 'extra',
|
|
146
|
+
} as unknown as CollaboratorInfo;
|
|
147
|
+
expect(
|
|
148
|
+
areCollaboratorInfosEqual(
|
|
149
|
+
collaboratorInfo1,
|
|
150
|
+
collaboratorInfo2
|
|
151
|
+
)
|
|
152
|
+
).toBe( false );
|
|
153
|
+
} );
|
|
154
|
+
} );
|
|
155
|
+
|
|
156
|
+
describe( 'generateCollaboratorInfo', () => {
|
|
157
|
+
const createMockUser = (
|
|
158
|
+
overrides: Partial< User< 'view' > > = {}
|
|
159
|
+
): User< 'view' > =>
|
|
160
|
+
( {
|
|
161
|
+
id: 1,
|
|
162
|
+
name: 'Test User',
|
|
163
|
+
slug: 'test-user',
|
|
164
|
+
avatar_urls: {
|
|
165
|
+
'24': 'https://example.com/avatar-24.png',
|
|
166
|
+
'48': 'https://example.com/avatar-48.png',
|
|
167
|
+
'96': 'https://example.com/avatar-96.png',
|
|
168
|
+
},
|
|
169
|
+
...overrides,
|
|
170
|
+
} ) as User< 'view' >;
|
|
171
|
+
|
|
172
|
+
beforeEach( () => {
|
|
173
|
+
// Reset to Chrome by default
|
|
174
|
+
mockUserAgent(
|
|
175
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
|
176
|
+
);
|
|
177
|
+
jest.spyOn( Date, 'now' ).mockReturnValue( 1704067200000 );
|
|
178
|
+
} );
|
|
179
|
+
|
|
180
|
+
afterEach( () => {
|
|
181
|
+
jest.restoreAllMocks();
|
|
182
|
+
} );
|
|
183
|
+
|
|
184
|
+
test( 'should generate collaboratorInfo with user properties', () => {
|
|
185
|
+
const user = createMockUser( { id: 42, name: 'Jane Doe' } );
|
|
186
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
187
|
+
|
|
188
|
+
expect( collaboratorInfo.id ).toBe( 42 );
|
|
189
|
+
expect( collaboratorInfo.name ).toBe( 'Jane Doe' );
|
|
190
|
+
expect( collaboratorInfo.slug ).toBe( 'test-user' );
|
|
191
|
+
} );
|
|
192
|
+
|
|
193
|
+
test( 'should include browser type', () => {
|
|
194
|
+
const user = createMockUser();
|
|
195
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
196
|
+
|
|
197
|
+
expect( collaboratorInfo.browserType ).toBe( 'Chrome' );
|
|
198
|
+
} );
|
|
199
|
+
|
|
200
|
+
test( 'should detect Firefox browser', () => {
|
|
201
|
+
mockUserAgent(
|
|
202
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
|
|
203
|
+
);
|
|
204
|
+
const user = createMockUser();
|
|
205
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
206
|
+
|
|
207
|
+
expect( collaboratorInfo.browserType ).toBe( 'Firefox' );
|
|
208
|
+
} );
|
|
209
|
+
|
|
210
|
+
test( 'should detect Microsoft Edge browser', () => {
|
|
211
|
+
mockUserAgent(
|
|
212
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59'
|
|
213
|
+
);
|
|
214
|
+
const user = createMockUser();
|
|
215
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
216
|
+
|
|
217
|
+
expect( collaboratorInfo.browserType ).toBe( 'Microsoft Edge' );
|
|
218
|
+
} );
|
|
219
|
+
|
|
220
|
+
test( 'should detect Safari browser', () => {
|
|
221
|
+
mockUserAgent(
|
|
222
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15'
|
|
223
|
+
);
|
|
224
|
+
const user = createMockUser();
|
|
225
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
226
|
+
|
|
227
|
+
expect( collaboratorInfo.browserType ).toBe( 'Safari' );
|
|
228
|
+
} );
|
|
229
|
+
|
|
230
|
+
test( 'should detect Internet Explorer browser (MSIE)', () => {
|
|
231
|
+
mockUserAgent(
|
|
232
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; MSIE 10.0; rv:11.0) like Gecko'
|
|
233
|
+
);
|
|
234
|
+
const user = createMockUser();
|
|
235
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
236
|
+
|
|
237
|
+
expect( collaboratorInfo.browserType ).toBe( 'Internet Explorer' );
|
|
238
|
+
} );
|
|
239
|
+
|
|
240
|
+
test( 'should detect Internet Explorer browser (Trident)', () => {
|
|
241
|
+
mockUserAgent(
|
|
242
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'
|
|
243
|
+
);
|
|
244
|
+
const user = createMockUser();
|
|
245
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
246
|
+
|
|
247
|
+
expect( collaboratorInfo.browserType ).toBe( 'Internet Explorer' );
|
|
248
|
+
} );
|
|
249
|
+
|
|
250
|
+
test( 'should detect Opera browser (Opera)', () => {
|
|
251
|
+
mockUserAgent(
|
|
252
|
+
'Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.18'
|
|
253
|
+
);
|
|
254
|
+
const user = createMockUser();
|
|
255
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
256
|
+
|
|
257
|
+
expect( collaboratorInfo.browserType ).toBe( 'Opera' );
|
|
258
|
+
} );
|
|
259
|
+
|
|
260
|
+
test( 'should detect Opera browser (OPR)', () => {
|
|
261
|
+
// Note: Modern Opera (Chromium-based) includes both "Chrome" and "Safari"
|
|
262
|
+
// in the user agent. The browser detection checks Chrome and Safari before
|
|
263
|
+
// OPR, so we use a synthetic user agent to test the OPR detection path.
|
|
264
|
+
mockUserAgent(
|
|
265
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) OPR/77.0.4054.203'
|
|
266
|
+
);
|
|
267
|
+
const user = createMockUser();
|
|
268
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
269
|
+
|
|
270
|
+
expect( collaboratorInfo.browserType ).toBe( 'Opera' );
|
|
271
|
+
} );
|
|
272
|
+
|
|
273
|
+
test( 'should return Unknown for unrecognized browser', () => {
|
|
274
|
+
mockUserAgent( 'Some Unknown Browser/1.0' );
|
|
275
|
+
const user = createMockUser();
|
|
276
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
277
|
+
|
|
278
|
+
expect( collaboratorInfo.browserType ).toBe( 'Unknown' );
|
|
279
|
+
} );
|
|
280
|
+
|
|
281
|
+
test( 'should include enteredAt timestamp', () => {
|
|
282
|
+
const user = createMockUser();
|
|
283
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
284
|
+
|
|
285
|
+
expect( collaboratorInfo.enteredAt ).toBe( 1704067200000 );
|
|
286
|
+
} );
|
|
287
|
+
|
|
288
|
+
test( 'should include avatar_urls from user', () => {
|
|
289
|
+
const user = createMockUser( {
|
|
290
|
+
avatar_urls: {
|
|
291
|
+
'24': 'https://example.com/small.png',
|
|
292
|
+
'48': 'https://example.com/medium.png',
|
|
293
|
+
'96': 'https://example.com/large.png',
|
|
294
|
+
},
|
|
295
|
+
} );
|
|
296
|
+
const collaboratorInfo = generateCollaboratorInfo( user );
|
|
297
|
+
|
|
298
|
+
expect( collaboratorInfo.avatar_urls ).toEqual( {
|
|
299
|
+
'24': 'https://example.com/small.png',
|
|
300
|
+
'48': 'https://example.com/medium.png',
|
|
301
|
+
'96': 'https://example.com/large.png',
|
|
302
|
+
} );
|
|
303
|
+
} );
|
|
304
|
+
} );
|
|
305
|
+
} );
|
package/src/awareness/types.ts
CHANGED
package/src/awareness/utils.ts
CHANGED
|
@@ -4,82 +4,6 @@
|
|
|
4
4
|
import type { User } from '../entity-types';
|
|
5
5
|
import type { CollaboratorInfo } from './types';
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* The color palette for the collaborator highlight.
|
|
9
|
-
*/
|
|
10
|
-
const COLOR_PALETTE = [
|
|
11
|
-
'#3858E9', // blueberry
|
|
12
|
-
'#B42AED', // purple
|
|
13
|
-
'#E33184', // pink
|
|
14
|
-
'#F3661D', // orange
|
|
15
|
-
'#ECBD3A', // yellow
|
|
16
|
-
'#97FE17', // green
|
|
17
|
-
'#00FDD9', // teal
|
|
18
|
-
'#37C5F0', // cyan
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a random integer between min and max, inclusive.
|
|
23
|
-
*
|
|
24
|
-
* @param min - The minimum value.
|
|
25
|
-
* @param max - The maximum value.
|
|
26
|
-
* @return A random integer between min and max.
|
|
27
|
-
*/
|
|
28
|
-
function generateRandomInt( min: number, max: number ): number {
|
|
29
|
-
return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get a unique collaborator color from the palette, or generate a variation if none are available.
|
|
34
|
-
* If the previously used color is available from localStorage, use it.
|
|
35
|
-
*
|
|
36
|
-
* @param existingColors - Colors that are already in use.
|
|
37
|
-
* @return The new collaborator color, in hex format.
|
|
38
|
-
*/
|
|
39
|
-
function getNewCollaboratorColor( existingColors: string[] ): string {
|
|
40
|
-
const availableColors = COLOR_PALETTE.filter(
|
|
41
|
-
( color ) => ! existingColors.includes( color )
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
let hexColor: string;
|
|
45
|
-
|
|
46
|
-
if ( availableColors.length > 0 ) {
|
|
47
|
-
const randomIndex = generateRandomInt( 0, availableColors.length - 1 );
|
|
48
|
-
hexColor = availableColors[ randomIndex ];
|
|
49
|
-
} else {
|
|
50
|
-
// All colors are used, generate a variation of a random palette color
|
|
51
|
-
const randomIndex = generateRandomInt( 0, COLOR_PALETTE.length - 1 );
|
|
52
|
-
const baseColor = COLOR_PALETTE[ randomIndex ];
|
|
53
|
-
hexColor = generateColorVariation( baseColor );
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return hexColor;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Generate a variation of a hex color by adjusting its lightness.
|
|
61
|
-
*
|
|
62
|
-
* @param hexColor - The base hex color (e.g., '#3858E9').
|
|
63
|
-
* @return A varied hex color.
|
|
64
|
-
*/
|
|
65
|
-
function generateColorVariation( hexColor: string ): string {
|
|
66
|
-
// Parse hex to RGB
|
|
67
|
-
const r = parseInt( hexColor.slice( 1, 3 ), 16 );
|
|
68
|
-
const g = parseInt( hexColor.slice( 3, 5 ), 16 );
|
|
69
|
-
const b = parseInt( hexColor.slice( 5, 7 ), 16 );
|
|
70
|
-
|
|
71
|
-
// Apply a random lightness shift (-30 to +30)
|
|
72
|
-
const shift = generateRandomInt( -30, 30 );
|
|
73
|
-
const newR = Math.min( 255, Math.max( 0, r + shift ) );
|
|
74
|
-
const newG = Math.min( 255, Math.max( 0, g + shift ) );
|
|
75
|
-
const newB = Math.min( 255, Math.max( 0, b + shift ) );
|
|
76
|
-
|
|
77
|
-
// Convert back to hex
|
|
78
|
-
const toHex = ( n: number ) =>
|
|
79
|
-
n.toString( 16 ).padStart( 2, '0' ).toUpperCase();
|
|
80
|
-
return `#${ toHex( newR ) }${ toHex( newG ) }${ toHex( newB ) }`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
7
|
/**
|
|
84
8
|
* Get the browser name from the user agent.
|
|
85
9
|
* @return The browser name.
|
|
@@ -165,21 +89,23 @@ export function areCollaboratorInfosEqual(
|
|
|
165
89
|
}
|
|
166
90
|
|
|
167
91
|
/**
|
|
168
|
-
* Generate a collaborator info object from a current collaborator
|
|
92
|
+
* Generate a collaborator info object from a current collaborator.
|
|
169
93
|
*
|
|
170
94
|
* @param currentCollaborator - The current collaborator.
|
|
171
|
-
* @param existingColors - The existing colors.
|
|
172
95
|
* @return The collaborator info object.
|
|
173
96
|
*/
|
|
174
97
|
export function generateCollaboratorInfo(
|
|
175
|
-
currentCollaborator: User< 'view'
|
|
176
|
-
existingColors: string[]
|
|
98
|
+
currentCollaborator: User< 'view' >
|
|
177
99
|
): CollaboratorInfo {
|
|
100
|
+
// eslint-disable-next-line camelcase
|
|
101
|
+
const { avatar_urls, id, name, slug } = currentCollaborator;
|
|
178
102
|
return {
|
|
179
|
-
|
|
103
|
+
avatar_urls, // eslint-disable-line camelcase
|
|
180
104
|
browserType: getBrowserName(),
|
|
181
|
-
color: getNewCollaboratorColor( existingColors ),
|
|
182
105
|
enteredAt: Date.now(),
|
|
106
|
+
id,
|
|
107
|
+
name,
|
|
108
|
+
slug,
|
|
183
109
|
};
|
|
184
110
|
}
|
|
185
111
|
|
package/src/entities.js
CHANGED
|
@@ -42,11 +42,17 @@ export const rootEntitiesConfig = [
|
|
|
42
42
|
baseURL: '/',
|
|
43
43
|
baseURLParams: {
|
|
44
44
|
// Please also change the preload path when changing this.
|
|
45
|
-
// @see lib/compat/wordpress-
|
|
45
|
+
// @see lib/compat/wordpress-7.0/preload.php
|
|
46
46
|
_fields: [
|
|
47
47
|
'description',
|
|
48
48
|
'gmt_offset',
|
|
49
49
|
'home',
|
|
50
|
+
'image_sizes',
|
|
51
|
+
'image_size_threshold',
|
|
52
|
+
'image_output_formats',
|
|
53
|
+
'jpeg_interlaced',
|
|
54
|
+
'png_interlaced',
|
|
55
|
+
'gif_interlaced',
|
|
50
56
|
'name',
|
|
51
57
|
'site_icon',
|
|
52
58
|
'site_icon_url',
|