@deck.gl-community/graph-layers 9.2.0-beta.5 → 9.2.0-beta.8
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/dist/core/graph-engine.d.ts +3 -2
- package/dist/core/graph-engine.d.ts.map +1 -1
- package/dist/core/graph-engine.js +1 -0
- package/dist/core/graph-engine.js.map +1 -1
- package/dist/graph-style-schema.cdn.js +1 -1
- package/dist/graph-style-schema.json +1 -1
- package/dist/index.cjs +307 -202
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layers/edge-attachment-helper.d.ts.map +1 -1
- package/dist/layers/edge-attachment-helper.js.map +1 -1
- package/dist/layers/graph-layer.d.ts +4 -3
- package/dist/layers/graph-layer.d.ts.map +1 -1
- package/dist/layers/graph-layer.js +11 -6
- package/dist/layers/graph-layer.js.map +1 -1
- package/dist/loaders/dot-graph-loader.js +1 -1
- package/dist/loaders/json-graph-loader.js +1 -1
- package/dist/style/graph-layer-stylesheet.d.ts +14 -5
- package/dist/style/graph-layer-stylesheet.d.ts.map +1 -1
- package/dist/style/graph-layer-stylesheet.js +9 -3
- package/dist/style/graph-layer-stylesheet.js.map +1 -1
- package/dist/style/graph-style-engine.d.ts +4 -4
- package/dist/style/graph-style-engine.d.ts.map +1 -1
- package/dist/style/graph-style-engine.js +4 -4
- package/dist/style/graph-style-engine.js.map +1 -1
- package/dist/style/graph-stylesheet-schema.d.ts +13211 -0
- package/dist/style/graph-stylesheet-schema.d.ts.map +1 -0
- package/dist/style/graph-stylesheet-schema.js +354 -0
- package/dist/style/graph-stylesheet-schema.js.map +1 -0
- package/package.json +2 -2
- package/src/core/graph-engine.ts +7 -2
- package/src/index.ts +2 -1
- package/src/layers/edge-attachment-helper.ts +2 -5
- package/src/layers/graph-layer.ts +25 -19
- package/src/style/graph-layer-stylesheet.ts +16 -9
- package/src/style/graph-style-engine.ts +21 -13
- package/src/style/graph-stylesheet-schema.ts +538 -0
- package/dist/style/graph-stylesheet.schema.d.ts +0 -311
- package/dist/style/graph-stylesheet.schema.d.ts.map +0 -1
- package/dist/style/graph-stylesheet.schema.js +0 -238
- package/dist/style/graph-stylesheet.schema.js.map +0 -1
- package/src/style/graph-stylesheet.schema.ts +0 -344
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
// deck.gl-community
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
/* eslint-disable no-continue */
|
|
6
|
+
|
|
7
|
+
import {z, type ZodTypeAny} from 'zod';
|
|
8
|
+
|
|
9
|
+
import {GRAPH_DECKGL_ACCESSOR_MAP} from './graph-style-accessor-map';
|
|
10
|
+
export {GRAPH_DECKGL_ACCESSOR_MAP};
|
|
11
|
+
|
|
12
|
+
const GraphStylePrimitiveSchema = z.union([
|
|
13
|
+
z.string(),
|
|
14
|
+
z.number(),
|
|
15
|
+
z.boolean(),
|
|
16
|
+
z.null(),
|
|
17
|
+
z.array(z.union([z.string(), z.number(), z.boolean(), z.null()]))
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const GraphStyleFunctionSchema = z.custom<(...args: unknown[]) => unknown>(
|
|
21
|
+
(value) => typeof value === 'function',
|
|
22
|
+
{
|
|
23
|
+
message: 'Style functions must be callable.'
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Supported scale identifiers for mapping data values to visual encodings.
|
|
29
|
+
*/
|
|
30
|
+
export const GraphStyleScaleTypeEnum = z.enum([
|
|
31
|
+
'linear',
|
|
32
|
+
'log',
|
|
33
|
+
'pow',
|
|
34
|
+
'sqrt',
|
|
35
|
+
'quantize',
|
|
36
|
+
'quantile',
|
|
37
|
+
'ordinal'
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TypeScript union of {@link GraphStyleScaleTypeEnum} values.
|
|
42
|
+
*/
|
|
43
|
+
export type GraphStyleScaleType = z.infer<typeof GraphStyleScaleTypeEnum>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Configuration for data-driven style scaling. Supports deck.gl compatible numeric and
|
|
47
|
+
* categorical scaling with optional d3-scale like parameters.
|
|
48
|
+
*/
|
|
49
|
+
export const GraphStyleScaleSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
type: GraphStyleScaleTypeEnum.optional(),
|
|
52
|
+
domain: z.array(z.union([z.number(), z.string()])).optional(),
|
|
53
|
+
range: z.array(z.any()).optional(),
|
|
54
|
+
clamp: z.boolean().optional(),
|
|
55
|
+
nice: z.union([z.boolean(), z.number()]).optional(),
|
|
56
|
+
base: z.number().optional(),
|
|
57
|
+
exponent: z.number().optional(),
|
|
58
|
+
unknown: z.any().optional()
|
|
59
|
+
})
|
|
60
|
+
.strict();
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* TypeScript view of {@link GraphStyleScaleSchema} after parsing.
|
|
64
|
+
*/
|
|
65
|
+
export type GraphStyleScale = z.infer<typeof GraphStyleScaleSchema>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Reference to node/edge attributes, optionally including fallback values and scale
|
|
69
|
+
* configuration for data-driven styling.
|
|
70
|
+
*/
|
|
71
|
+
export const GraphStyleAttributeReferenceSchema = z.union([
|
|
72
|
+
z
|
|
73
|
+
.string()
|
|
74
|
+
.regex(/^@.+/, 'Attribute reference strings must start with "@" and include an attribute name.'),
|
|
75
|
+
z
|
|
76
|
+
.object({
|
|
77
|
+
attribute: z.string().min(1, 'Attribute name is required.'),
|
|
78
|
+
fallback: GraphStylePrimitiveSchema.optional(),
|
|
79
|
+
scale: z.union([GraphStyleScaleSchema, GraphStyleFunctionSchema]).optional()
|
|
80
|
+
})
|
|
81
|
+
.strict()
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parsed value produced by {@link GraphStyleAttributeReferenceSchema}.
|
|
86
|
+
*/
|
|
87
|
+
export type GraphStyleAttributeReference = z.infer<typeof GraphStyleAttributeReferenceSchema>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Primitive value allowed in stylesheet definitions. Supports literal values, attribute
|
|
91
|
+
* references and imperative resolver functions.
|
|
92
|
+
*/
|
|
93
|
+
export const GraphStyleLeafValueSchema = z.union([
|
|
94
|
+
GraphStylePrimitiveSchema,
|
|
95
|
+
GraphStyleAttributeReferenceSchema,
|
|
96
|
+
GraphStyleFunctionSchema
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Union of literal, attribute-driven and functional style values.
|
|
101
|
+
*/
|
|
102
|
+
export type GraphStyleLeafValue = z.infer<typeof GraphStyleLeafValueSchema>;
|
|
103
|
+
|
|
104
|
+
const RESERVED_STATE_KEYS = new Set(['attribute', 'fallback', 'scale']);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Mapping of interaction or application state keys to leaf style values.
|
|
108
|
+
*/
|
|
109
|
+
export const GraphStyleStateMapSchema = z.record(
|
|
110
|
+
z
|
|
111
|
+
.string()
|
|
112
|
+
.refine((key) => !RESERVED_STATE_KEYS.has(key), 'State overrides must not use reserved keys.'),
|
|
113
|
+
GraphStyleLeafValueSchema
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Style value that may be either a simple leaf value or a keyed map of overrides.
|
|
118
|
+
*/
|
|
119
|
+
export const GraphStyleValueSchema = z.union([
|
|
120
|
+
GraphStyleLeafValueSchema,
|
|
121
|
+
GraphStyleStateMapSchema
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Parsed style property value that may include state overrides.
|
|
126
|
+
*/
|
|
127
|
+
export type GraphStyleValue = z.infer<typeof GraphStyleValueSchema>;
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
export type GraphStyleType = keyof typeof GRAPH_DECKGL_ACCESSOR_MAP;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* CSS-like pseudo selector supported by the stylesheet for state overrides.
|
|
134
|
+
*/
|
|
135
|
+
export type GraphStyleSelector = `:${string}`;
|
|
136
|
+
|
|
137
|
+
const GraphStyleSelectorKeySchema = z.string().regex(/^:[^\s]+/, 'Selectors must start with ":".');
|
|
138
|
+
|
|
139
|
+
function createSelectorRefinement(
|
|
140
|
+
allowedKeys: readonly string[],
|
|
141
|
+
propertiesSchema: ZodTypeAny
|
|
142
|
+
) {
|
|
143
|
+
const allowedKeySet = new Set<string>(allowedKeys);
|
|
144
|
+
|
|
145
|
+
return (value: unknown, ctx: z.RefinementCtx) => {
|
|
146
|
+
if (typeof value !== 'object' || value === null) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const record = value as Record<string, unknown>;
|
|
151
|
+
|
|
152
|
+
for (const key of Object.keys(record)) {
|
|
153
|
+
if (key === 'type') continue;
|
|
154
|
+
if (allowedKeySet.has(key)) continue;
|
|
155
|
+
|
|
156
|
+
if (!key.startsWith(':')) {
|
|
157
|
+
ctx.addIssue({
|
|
158
|
+
code: z.ZodIssueCode.custom,
|
|
159
|
+
path: [key],
|
|
160
|
+
message: `Unknown style property "${key}".`
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!GraphStyleSelectorKeySchema.safeParse(key).success) {
|
|
166
|
+
ctx.addIssue({
|
|
167
|
+
code: z.ZodIssueCode.custom,
|
|
168
|
+
path: [key],
|
|
169
|
+
message: 'Selectors must start with ":".'
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const selectorResult = propertiesSchema.safeParse(record[key]);
|
|
175
|
+
if (!selectorResult.success) {
|
|
176
|
+
for (const issue of selectorResult.error.issues) {
|
|
177
|
+
ctx.addIssue({
|
|
178
|
+
...issue,
|
|
179
|
+
path: [key, ...(issue.path ?? [])]
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const CircleShape = {
|
|
188
|
+
offset: GraphStyleValueSchema.optional(),
|
|
189
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
190
|
+
fill: GraphStyleValueSchema.optional(),
|
|
191
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
192
|
+
strokeWidth: GraphStyleValueSchema.optional(),
|
|
193
|
+
radius: GraphStyleValueSchema.optional()
|
|
194
|
+
} as const;
|
|
195
|
+
|
|
196
|
+
const CirclePropertiesSchema = z.object(CircleShape).partial().strict();
|
|
197
|
+
|
|
198
|
+
const CircleStylesheetSchema = z
|
|
199
|
+
.object({
|
|
200
|
+
type: z.literal('circle'),
|
|
201
|
+
...CircleShape
|
|
202
|
+
})
|
|
203
|
+
.catchall(z.unknown())
|
|
204
|
+
.superRefine(
|
|
205
|
+
createSelectorRefinement(Object.keys(CircleShape), CirclePropertiesSchema)
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const RectangleShape = {
|
|
209
|
+
offset: GraphStyleValueSchema.optional(),
|
|
210
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
211
|
+
width: GraphStyleValueSchema.optional(),
|
|
212
|
+
height: GraphStyleValueSchema.optional(),
|
|
213
|
+
fill: GraphStyleValueSchema.optional(),
|
|
214
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
215
|
+
strokeWidth: GraphStyleValueSchema.optional()
|
|
216
|
+
} as const;
|
|
217
|
+
|
|
218
|
+
const RectanglePropertiesSchema = z.object(RectangleShape).partial().strict();
|
|
219
|
+
|
|
220
|
+
const RectangleStylesheetSchema = z
|
|
221
|
+
.object({
|
|
222
|
+
type: z.literal('rectangle'),
|
|
223
|
+
...RectangleShape
|
|
224
|
+
})
|
|
225
|
+
.catchall(z.unknown())
|
|
226
|
+
.superRefine(
|
|
227
|
+
createSelectorRefinement(
|
|
228
|
+
Object.keys(RectangleShape),
|
|
229
|
+
RectanglePropertiesSchema
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
const RoundedRectangleShape = {
|
|
234
|
+
offset: GraphStyleValueSchema.optional(),
|
|
235
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
236
|
+
cornerRadius: GraphStyleValueSchema.optional(),
|
|
237
|
+
radius: GraphStyleValueSchema.optional(),
|
|
238
|
+
width: GraphStyleValueSchema.optional(),
|
|
239
|
+
height: GraphStyleValueSchema.optional(),
|
|
240
|
+
fill: GraphStyleValueSchema.optional(),
|
|
241
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
242
|
+
strokeWidth: GraphStyleValueSchema.optional()
|
|
243
|
+
} as const;
|
|
244
|
+
|
|
245
|
+
const RoundedRectanglePropertiesSchema = z
|
|
246
|
+
.object(RoundedRectangleShape)
|
|
247
|
+
.partial()
|
|
248
|
+
.strict();
|
|
249
|
+
|
|
250
|
+
const RoundedRectangleStylesheetSchema = z
|
|
251
|
+
.object({
|
|
252
|
+
type: z.literal('rounded-rectangle'),
|
|
253
|
+
...RoundedRectangleShape
|
|
254
|
+
})
|
|
255
|
+
.catchall(z.unknown())
|
|
256
|
+
.superRefine(
|
|
257
|
+
createSelectorRefinement(
|
|
258
|
+
Object.keys(RoundedRectangleShape),
|
|
259
|
+
RoundedRectanglePropertiesSchema
|
|
260
|
+
)
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const PathRoundedRectangleShape = {
|
|
264
|
+
offset: GraphStyleValueSchema.optional(),
|
|
265
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
266
|
+
width: GraphStyleValueSchema.optional(),
|
|
267
|
+
height: GraphStyleValueSchema.optional(),
|
|
268
|
+
fill: GraphStyleValueSchema.optional(),
|
|
269
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
270
|
+
strokeWidth: GraphStyleValueSchema.optional(),
|
|
271
|
+
cornerRadius: GraphStyleValueSchema.optional()
|
|
272
|
+
} as const;
|
|
273
|
+
|
|
274
|
+
const PathRoundedRectanglePropertiesSchema = z
|
|
275
|
+
.object(PathRoundedRectangleShape)
|
|
276
|
+
.partial()
|
|
277
|
+
.strict();
|
|
278
|
+
|
|
279
|
+
const PathRoundedRectangleStylesheetSchema = z
|
|
280
|
+
.object({
|
|
281
|
+
type: z.literal('path-rounded-rectangle'),
|
|
282
|
+
...PathRoundedRectangleShape
|
|
283
|
+
})
|
|
284
|
+
.catchall(z.unknown())
|
|
285
|
+
.superRefine(
|
|
286
|
+
createSelectorRefinement(
|
|
287
|
+
Object.keys(PathRoundedRectangleShape),
|
|
288
|
+
PathRoundedRectanglePropertiesSchema
|
|
289
|
+
)
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const LabelShape = {
|
|
293
|
+
offset: GraphStyleValueSchema.optional(),
|
|
294
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
295
|
+
color: GraphStyleValueSchema.optional(),
|
|
296
|
+
text: GraphStyleValueSchema.optional(),
|
|
297
|
+
fontSize: GraphStyleValueSchema.optional(),
|
|
298
|
+
textAnchor: GraphStyleValueSchema.optional(),
|
|
299
|
+
alignmentBaseline: GraphStyleValueSchema.optional(),
|
|
300
|
+
angle: GraphStyleValueSchema.optional(),
|
|
301
|
+
scaleWithZoom: GraphStyleValueSchema.optional(),
|
|
302
|
+
textMaxWidth: GraphStyleValueSchema.optional(),
|
|
303
|
+
textWordBreak: GraphStyleValueSchema.optional(),
|
|
304
|
+
textSizeMinPixels: GraphStyleValueSchema.optional()
|
|
305
|
+
} as const;
|
|
306
|
+
|
|
307
|
+
const LabelPropertiesSchema = z.object(LabelShape).partial().strict();
|
|
308
|
+
|
|
309
|
+
const LabelStylesheetSchema = z
|
|
310
|
+
.object({
|
|
311
|
+
type: z.literal('label'),
|
|
312
|
+
...LabelShape
|
|
313
|
+
})
|
|
314
|
+
.catchall(z.unknown())
|
|
315
|
+
.superRefine(
|
|
316
|
+
createSelectorRefinement(Object.keys(LabelShape), LabelPropertiesSchema)
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const MarkerShape = {
|
|
320
|
+
offset: GraphStyleValueSchema.optional(),
|
|
321
|
+
opacity: GraphStyleValueSchema.optional(),
|
|
322
|
+
fill: GraphStyleValueSchema.optional(),
|
|
323
|
+
size: GraphStyleValueSchema.optional(),
|
|
324
|
+
marker: GraphStyleValueSchema.optional(),
|
|
325
|
+
scaleWithZoom: GraphStyleValueSchema.optional()
|
|
326
|
+
} as const;
|
|
327
|
+
|
|
328
|
+
const MarkerPropertiesSchema = z.object(MarkerShape).partial().strict();
|
|
329
|
+
|
|
330
|
+
const MarkerStylesheetSchema = z
|
|
331
|
+
.object({
|
|
332
|
+
type: z.literal('marker'),
|
|
333
|
+
...MarkerShape
|
|
334
|
+
})
|
|
335
|
+
.catchall(z.unknown())
|
|
336
|
+
.superRefine(
|
|
337
|
+
createSelectorRefinement(Object.keys(MarkerShape), MarkerPropertiesSchema)
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
const EdgeUpperShape = {
|
|
341
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
342
|
+
strokeWidth: GraphStyleValueSchema.optional()
|
|
343
|
+
} as const;
|
|
344
|
+
|
|
345
|
+
const EdgeUpperPropertiesSchema = z.object(EdgeUpperShape).partial().strict();
|
|
346
|
+
|
|
347
|
+
const EdgeUpperStylesheetSchema = z
|
|
348
|
+
.object({
|
|
349
|
+
type: z.literal('Edge'),
|
|
350
|
+
...EdgeUpperShape
|
|
351
|
+
})
|
|
352
|
+
.catchall(z.unknown())
|
|
353
|
+
.superRefine(
|
|
354
|
+
createSelectorRefinement(
|
|
355
|
+
Object.keys(EdgeUpperShape),
|
|
356
|
+
EdgeUpperPropertiesSchema
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
const EdgeLowerShape = {
|
|
361
|
+
stroke: GraphStyleValueSchema.optional(),
|
|
362
|
+
strokeWidth: GraphStyleValueSchema.optional()
|
|
363
|
+
} as const;
|
|
364
|
+
|
|
365
|
+
const EdgeLowerPropertiesSchema = z.object(EdgeLowerShape).partial().strict();
|
|
366
|
+
|
|
367
|
+
const EdgeLowerStylesheetSchema = z
|
|
368
|
+
.object({
|
|
369
|
+
type: z.literal('edge'),
|
|
370
|
+
...EdgeLowerShape
|
|
371
|
+
})
|
|
372
|
+
.catchall(z.unknown())
|
|
373
|
+
.superRefine(
|
|
374
|
+
createSelectorRefinement(
|
|
375
|
+
Object.keys(EdgeLowerShape),
|
|
376
|
+
EdgeLowerPropertiesSchema
|
|
377
|
+
)
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
const EdgeLabelShape = {
|
|
381
|
+
color: GraphStyleValueSchema.optional(),
|
|
382
|
+
text: GraphStyleValueSchema.optional(),
|
|
383
|
+
fontSize: GraphStyleValueSchema.optional(),
|
|
384
|
+
textAnchor: GraphStyleValueSchema.optional(),
|
|
385
|
+
alignmentBaseline: GraphStyleValueSchema.optional(),
|
|
386
|
+
scaleWithZoom: GraphStyleValueSchema.optional(),
|
|
387
|
+
textMaxWidth: GraphStyleValueSchema.optional(),
|
|
388
|
+
textWordBreak: GraphStyleValueSchema.optional(),
|
|
389
|
+
textSizeMinPixels: GraphStyleValueSchema.optional()
|
|
390
|
+
} as const;
|
|
391
|
+
|
|
392
|
+
const EdgeLabelPropertiesSchema = z.object(EdgeLabelShape).partial().strict();
|
|
393
|
+
|
|
394
|
+
const EdgeLabelStylesheetSchema = z
|
|
395
|
+
.object({
|
|
396
|
+
type: z.literal('edge-label'),
|
|
397
|
+
...EdgeLabelShape
|
|
398
|
+
})
|
|
399
|
+
.catchall(z.unknown())
|
|
400
|
+
.superRefine(
|
|
401
|
+
createSelectorRefinement(
|
|
402
|
+
Object.keys(EdgeLabelShape),
|
|
403
|
+
EdgeLabelPropertiesSchema
|
|
404
|
+
)
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
const FlowShape = {
|
|
408
|
+
color: GraphStyleValueSchema.optional(),
|
|
409
|
+
width: GraphStyleValueSchema.optional(),
|
|
410
|
+
speed: GraphStyleValueSchema.optional(),
|
|
411
|
+
tailLength: GraphStyleValueSchema.optional()
|
|
412
|
+
} as const;
|
|
413
|
+
|
|
414
|
+
const FlowPropertiesSchema = z.object(FlowShape).partial().strict();
|
|
415
|
+
|
|
416
|
+
const FlowStylesheetSchema = z
|
|
417
|
+
.object({
|
|
418
|
+
type: z.literal('flow'),
|
|
419
|
+
...FlowShape
|
|
420
|
+
})
|
|
421
|
+
.catchall(z.unknown())
|
|
422
|
+
.superRefine(
|
|
423
|
+
createSelectorRefinement(Object.keys(FlowShape), FlowPropertiesSchema)
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
const ArrowShape = {
|
|
427
|
+
color: GraphStyleValueSchema.optional(),
|
|
428
|
+
size: GraphStyleValueSchema.optional(),
|
|
429
|
+
offset: GraphStyleValueSchema.optional()
|
|
430
|
+
} as const;
|
|
431
|
+
|
|
432
|
+
const ArrowPropertiesSchema = z.object(ArrowShape).partial().strict();
|
|
433
|
+
|
|
434
|
+
const ArrowStylesheetSchema = z
|
|
435
|
+
.object({
|
|
436
|
+
type: z.literal('arrow'),
|
|
437
|
+
...ArrowShape
|
|
438
|
+
})
|
|
439
|
+
.catchall(z.unknown())
|
|
440
|
+
.superRefine(
|
|
441
|
+
createSelectorRefinement(Object.keys(ArrowShape), ArrowPropertiesSchema)
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
const GraphNodeStylesheetVariants = [
|
|
445
|
+
CircleStylesheetSchema,
|
|
446
|
+
RectangleStylesheetSchema,
|
|
447
|
+
RoundedRectangleStylesheetSchema,
|
|
448
|
+
PathRoundedRectangleStylesheetSchema,
|
|
449
|
+
LabelStylesheetSchema,
|
|
450
|
+
MarkerStylesheetSchema
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
const GraphEdgeStylesheetVariants = [
|
|
454
|
+
EdgeUpperStylesheetSchema,
|
|
455
|
+
EdgeLowerStylesheetSchema,
|
|
456
|
+
EdgeLabelStylesheetSchema,
|
|
457
|
+
FlowStylesheetSchema,
|
|
458
|
+
ArrowStylesheetSchema
|
|
459
|
+
];
|
|
460
|
+
|
|
461
|
+
const GraphStyleRuleVariants = [
|
|
462
|
+
...GraphNodeStylesheetVariants,
|
|
463
|
+
...GraphEdgeStylesheetVariants
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
type GraphStyleRuleVariantSchema = (typeof GraphStyleRuleVariants)[number];
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Schema that validates stylesheet definitions for all graph style primitives.
|
|
470
|
+
*/
|
|
471
|
+
export const GraphStyleRuleSchema = z.discriminatedUnion(
|
|
472
|
+
'type',
|
|
473
|
+
GraphStyleRuleVariants as [
|
|
474
|
+
GraphStyleRuleVariantSchema,
|
|
475
|
+
...GraphStyleRuleVariantSchema[]
|
|
476
|
+
]
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Runtime type accepted by {@link GraphStyleRuleSchema} before validation.
|
|
481
|
+
*/
|
|
482
|
+
export type GraphStyleRule = z.input<typeof GraphStyleRuleSchema>;
|
|
483
|
+
/**
|
|
484
|
+
* Type returned by {@link GraphStyleRuleSchema} after successful parsing.
|
|
485
|
+
*/
|
|
486
|
+
export type GraphStyleRuleParsed = z.infer<typeof GraphStyleRuleSchema>;
|
|
487
|
+
|
|
488
|
+
const GraphNodeStyleRuleSchema = z.discriminatedUnion(
|
|
489
|
+
'type',
|
|
490
|
+
GraphNodeStylesheetVariants as [
|
|
491
|
+
(typeof GraphNodeStylesheetVariants)[number],
|
|
492
|
+
...(typeof GraphNodeStylesheetVariants)[number][]
|
|
493
|
+
]
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
const GraphEdgeDecoratorRuleSchema = z.discriminatedUnion(
|
|
497
|
+
'type',
|
|
498
|
+
[EdgeLabelStylesheetSchema, FlowStylesheetSchema, ArrowStylesheetSchema] as [
|
|
499
|
+
typeof EdgeLabelStylesheetSchema,
|
|
500
|
+
typeof FlowStylesheetSchema,
|
|
501
|
+
typeof ArrowStylesheetSchema,
|
|
502
|
+
...Array<
|
|
503
|
+
typeof EdgeLabelStylesheetSchema | typeof FlowStylesheetSchema | typeof ArrowStylesheetSchema
|
|
504
|
+
>
|
|
505
|
+
]
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
const EdgeUpperWithDecoratorsSchema = EdgeUpperStylesheetSchema.safeExtend({
|
|
509
|
+
decorators: z.array(GraphEdgeDecoratorRuleSchema).optional()
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
const EdgeLowerWithDecoratorsSchema = EdgeLowerStylesheetSchema.safeExtend({
|
|
513
|
+
decorators: z.array(GraphEdgeDecoratorRuleSchema).optional()
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
const GraphEdgeRuleWithDecoratorsSchema = z.discriminatedUnion('type', [
|
|
517
|
+
EdgeUpperWithDecoratorsSchema,
|
|
518
|
+
EdgeLowerWithDecoratorsSchema
|
|
519
|
+
] as [typeof EdgeUpperWithDecoratorsSchema, typeof EdgeLowerWithDecoratorsSchema]);
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Schema that validates a full graph stylesheet including nodes, edges, and decorators.
|
|
523
|
+
*/
|
|
524
|
+
export const GraphStylesheetSchema = z
|
|
525
|
+
.object({
|
|
526
|
+
nodes: z.array(GraphNodeStyleRuleSchema).optional(),
|
|
527
|
+
edges: z.array(GraphEdgeRuleWithDecoratorsSchema).optional()
|
|
528
|
+
})
|
|
529
|
+
.strict();
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Runtime type accepted by {@link GraphStylesheetSchema} before validation.
|
|
533
|
+
*/
|
|
534
|
+
export type GraphStylesheet = z.input<typeof GraphStylesheetSchema>;
|
|
535
|
+
/**
|
|
536
|
+
* Type returned by {@link GraphStylesheetSchema} after successful parsing.
|
|
537
|
+
*/
|
|
538
|
+
export type GraphStylesheetParsed = z.infer<typeof GraphStylesheetSchema>;
|