ggaction 0.0.13 → 0.0.16

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.
Files changed (359) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +41 -12
  3. package/knowledge/action-cards.json +1 -1
  4. package/knowledge/intent-taxonomy.json +1 -1
  5. package/knowledge/mcp-resources.json +1 -1
  6. package/knowledge/task-packet.schema.json +1 -1
  7. package/knowledge/task-resolver.js +1 -1
  8. package/package.json +39 -7
  9. package/src/BasicChartProgram.js +3 -1
  10. package/src/ChartProgram.js +2 -0
  11. package/src/accessibility.js +157 -0
  12. package/src/actions/basic.js +2 -2
  13. package/src/actions/boxPlots/components.js +20 -12
  14. package/src/actions/boxPlots/create.js +4 -5
  15. package/src/actions/boxPlots/edit.js +34 -9
  16. package/src/actions/boxPlots/materialize.js +12 -4
  17. package/src/actions/boxPlots/options.js +48 -16
  18. package/src/actions/canvas/actions.js +3 -3
  19. package/src/actions/canvas/fitting.js +1 -1
  20. package/src/actions/categoryOrder/index.js +21 -12
  21. package/src/actions/charts/area.js +6 -2
  22. package/src/actions/charts/bar.js +3 -2
  23. package/src/actions/charts/beeswarm.js +1 -1
  24. package/src/actions/charts/density.js +7 -3
  25. package/src/actions/charts/ecdf.js +6 -3
  26. package/src/actions/charts/endpoints.js +29 -7
  27. package/src/actions/charts/heatmap.js +3 -2
  28. package/src/actions/charts/histogram.js +5 -4
  29. package/src/actions/charts/horizon.js +4 -2
  30. package/src/actions/charts/interval-regression.js +7 -4
  31. package/src/actions/charts/line.js +4 -2
  32. package/src/actions/charts/parallel.js +9 -3
  33. package/src/actions/charts/pie.js +11 -3
  34. package/src/actions/charts/polar.js +17 -6
  35. package/src/actions/charts/radar.js +9 -3
  36. package/src/actions/charts/radial.js +12 -4
  37. package/src/actions/charts/raincloud.js +2 -2
  38. package/src/actions/charts/rug-strip.js +8 -4
  39. package/src/actions/charts/scatter.js +4 -2
  40. package/src/actions/composition/actions.js +29 -24
  41. package/src/actions/coordinates/actions.js +2 -2
  42. package/src/actions/coordinates/edit.js +76 -0
  43. package/src/actions/data/basicBin2d.js +4 -5
  44. package/src/actions/data/bin.js +3 -3
  45. package/src/actions/data/bin2d.js +63 -193
  46. package/src/actions/data/bin2dMaterialize.js +4 -5
  47. package/src/actions/data/box.js +4 -4
  48. package/src/actions/data/complete.js +26 -0
  49. package/src/actions/data/computed.js +4 -4
  50. package/src/actions/data/create.js +7 -14
  51. package/src/actions/data/density.js +15 -23
  52. package/src/actions/data/derived.js +57 -31
  53. package/src/actions/data/ecdf.js +2 -2
  54. package/src/actions/data/edit.js +551 -0
  55. package/src/actions/data/filter.js +28 -22
  56. package/src/actions/data/fold.js +2 -2
  57. package/src/actions/data/gradientProfile.js +2 -2
  58. package/src/actions/data/horizon.js +2 -2
  59. package/src/actions/data/impute.js +26 -0
  60. package/src/actions/data/index.js +62 -47
  61. package/src/actions/data/interval.js +2 -2
  62. package/src/actions/data/intervalEdit.js +26 -18
  63. package/src/actions/data/normalize.js +27 -0
  64. package/src/actions/data/regression.js +21 -27
  65. package/src/actions/data/revise.js +48 -0
  66. package/src/actions/data/revisionBindings.js +125 -0
  67. package/src/actions/data/shared.js +20 -4
  68. package/src/actions/data/stack.js +2 -2
  69. package/src/actions/data/summary.js +3 -3
  70. package/src/actions/data/timeUnit.js +6 -3
  71. package/src/actions/data/window.js +3 -3
  72. package/src/actions/encodings/angle.js +1 -1
  73. package/src/actions/encodings/appearance.js +4 -4
  74. package/src/actions/encodings/barWidth.js +1 -1
  75. package/src/actions/encodings/channels.js +415 -0
  76. package/src/actions/encodings/color/index.js +3 -2
  77. package/src/actions/encodings/density.js +7 -4
  78. package/src/actions/encodings/histogram.js +4 -3
  79. package/src/actions/encodings/horizon.js +6 -8
  80. package/src/actions/encodings/index.js +4 -0
  81. package/src/actions/encodings/offset.js +22 -15
  82. package/src/actions/encodings/parallel.js +4 -5
  83. package/src/actions/encodings/pathOrder.js +6 -11
  84. package/src/actions/encodings/position/apply.js +53 -7
  85. package/src/actions/encodings/position/index.js +14 -6
  86. package/src/actions/encodings/position/policies/bar.js +9 -0
  87. package/src/actions/encodings/position/resolve.js +24 -7
  88. package/src/actions/encodings/ranged.js +5 -5
  89. package/src/actions/encodings/remove.js +13 -9
  90. package/src/actions/encodings/ruleAppearance.js +2 -24
  91. package/src/actions/encodings/seriesLayout.js +2 -1
  92. package/src/actions/encodings/shared.js +82 -14
  93. package/src/actions/encodings/stroke.js +226 -0
  94. package/src/actions/encodings/strokeDash.js +2 -2
  95. package/src/actions/encodings/text.js +1 -1
  96. package/src/actions/errorBands/create.js +34 -20
  97. package/src/actions/errorBands/edit.js +34 -137
  98. package/src/actions/errorBars/create.js +43 -20
  99. package/src/actions/errorBars/edit.js +29 -125
  100. package/src/actions/facets/actions.js +267 -73
  101. package/src/actions/facets/derive.js +99 -28
  102. package/src/actions/facets/guides.js +4 -5
  103. package/src/actions/facets/replay.js +4 -5
  104. package/src/actions/gradientPlots/components.js +15 -8
  105. package/src/actions/gradientPlots/create.js +4 -5
  106. package/src/actions/gradientPlots/edit.js +18 -9
  107. package/src/actions/gradientPlots/materialize.js +5 -3
  108. package/src/actions/gradientPlots/options.js +10 -2
  109. package/src/actions/gradientPlots/rebind.js +4 -5
  110. package/src/actions/guides/applicability.js +8 -2
  111. package/src/actions/guides/axes/axes.js +23 -4
  112. package/src/actions/guides/axes/axis.js +2 -2
  113. package/src/actions/guides/axes/edit.js +2 -2
  114. package/src/actions/guides/axes/labels.js +67 -21
  115. package/src/actions/guides/axes/lines.js +15 -9
  116. package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
  117. package/src/actions/guides/axes/parallel/resolve.js +6 -2
  118. package/src/actions/guides/axes/parallel.js +5 -5
  119. package/src/actions/guides/axes/remove.js +4 -4
  120. package/src/actions/guides/axes/tickGroups.js +6 -5
  121. package/src/actions/guides/axes/ticks.js +19 -6
  122. package/src/actions/guides/axes/titles.js +21 -13
  123. package/src/actions/guides/grids/grid.js +18 -29
  124. package/src/actions/guides/grids/resolve.js +7 -2
  125. package/src/actions/guides/guides.js +20 -4
  126. package/src/actions/guides/legends/blocks.js +426 -0
  127. package/src/actions/guides/legends/categorical/actions.js +138 -52
  128. package/src/actions/guides/legends/categorical/components.js +55 -45
  129. package/src/actions/guides/legends/categorical/index.js +37 -33
  130. package/src/actions/guides/legends/categorical/layout.js +98 -16
  131. package/src/actions/guides/legends/categorical/options.js +2 -2
  132. package/src/actions/guides/legends/categorical/recipes.js +111 -20
  133. package/src/actions/guides/legends/categorical/resolve.js +12 -8
  134. package/src/actions/guides/legends/categorical/symbols.js +104 -52
  135. package/src/actions/guides/legends/continuous/common.js +76 -20
  136. package/src/actions/guides/legends/continuous/gradient.js +95 -158
  137. package/src/actions/guides/legends/continuous/index.js +2 -0
  138. package/src/actions/guides/legends/continuous/interval.js +21 -16
  139. package/src/actions/guides/legends/continuous/opacity.js +37 -83
  140. package/src/actions/guides/legends/continuous/stroke.js +225 -0
  141. package/src/actions/guides/legends/creation.js +14 -1
  142. package/src/actions/guides/legends/edit.js +159 -60
  143. package/src/actions/guides/legends/focused.js +5 -5
  144. package/src/actions/guides/legends/index.js +2 -0
  145. package/src/actions/guides/legends/lane.js +59 -24
  146. package/src/actions/guides/legends/lifecycle.js +19 -8
  147. package/src/actions/guides/legends/remove.js +17 -8
  148. package/src/actions/guides/legends/sampling.js +140 -0
  149. package/src/actions/guides/legends/size.js +100 -108
  150. package/src/actions/guides/legends/strokeWidth.js +38 -92
  151. package/src/actions/guides/legends/target.js +112 -1
  152. package/src/actions/guides/legends/transition.js +165 -16
  153. package/src/actions/guides/polar/axes/facade.js +8 -8
  154. package/src/actions/guides/polar/axes/labels.js +29 -10
  155. package/src/actions/guides/polar/axes/lines.js +19 -19
  156. package/src/actions/guides/polar/axes/shared.js +16 -0
  157. package/src/actions/guides/polar/axes/ticks.js +10 -16
  158. package/src/actions/guides/polar/axes/titles.js +6 -6
  159. package/src/actions/guides/polar/grids.js +12 -14
  160. package/src/actions/guides/polar/resolve.js +12 -8
  161. package/src/actions/index.js +16 -3
  162. package/src/actions/intervals/revision.js +126 -0
  163. package/src/actions/marks/arc/actions.js +80 -22
  164. package/src/actions/marks/area/actions.js +38 -13
  165. package/src/actions/marks/area/materialize.js +17 -1
  166. package/src/actions/marks/bar/create.js +12 -3
  167. package/src/actions/marks/bar/edit.js +21 -4
  168. package/src/actions/marks/bar/materialize.js +34 -40
  169. package/src/actions/marks/index.js +10 -1
  170. package/src/actions/marks/line/actions.js +40 -17
  171. package/src/actions/marks/line/materialize.js +29 -10
  172. package/src/actions/marks/point/create.js +9 -3
  173. package/src/actions/marks/point/edit.js +19 -7
  174. package/src/actions/marks/point/jitter.js +6 -8
  175. package/src/actions/marks/point/materialize.js +48 -22
  176. package/src/actions/marks/point/packing.js +6 -8
  177. package/src/actions/marks/rect/actions.js +36 -15
  178. package/src/actions/marks/references.js +602 -33
  179. package/src/actions/marks/remove.js +67 -41
  180. package/src/actions/marks/rule/actions.js +51 -14
  181. package/src/actions/marks/shared.js +1 -1
  182. package/src/actions/marks/text/actions.js +79 -14
  183. package/src/actions/marks/text/index.js +4 -0
  184. package/src/actions/marks/text/layout.js +157 -17
  185. package/src/actions/marks/text/removal.js +173 -0
  186. package/src/actions/marks/text/selection.js +72 -0
  187. package/src/actions/marks/tick/actions.js +25 -8
  188. package/src/actions/primitives/createGraphics.js +5 -4
  189. package/src/actions/primitives/editGraphics.js +31 -4
  190. package/src/actions/primitives/graphicProperties.js +6 -0
  191. package/src/actions/primitives/semantic.js +11 -3
  192. package/src/actions/primitives/semanticAction.js +90 -14
  193. package/src/actions/primitives/semanticValidation/dataset.js +2 -4
  194. package/src/actions/primitives/semanticValidation/guide.js +1 -1
  195. package/src/actions/primitives/semanticValidation/index.js +9 -1
  196. package/src/actions/primitives/semanticValidation/layer.js +5 -0
  197. package/src/actions/primitives/semanticValidation/scale.js +28 -7
  198. package/src/actions/regression/components.js +36 -25
  199. package/src/actions/regression/create.js +13 -6
  200. package/src/actions/regression/edit.js +24 -11
  201. package/src/actions/resources/index.js +7 -0
  202. package/src/actions/resources/remove.js +173 -0
  203. package/src/actions/scales/channels.js +212 -0
  204. package/src/actions/scales/consumers/common.js +1 -1
  205. package/src/actions/scales/consumers/families.js +3 -2
  206. package/src/actions/scales/consumers/index.js +19 -2
  207. package/src/actions/scales/consumers/seriesLayout.js +28 -14
  208. package/src/actions/scales/create.js +55 -23
  209. package/src/actions/scales/definitions.js +94 -40
  210. package/src/actions/scales/edit.js +67 -12
  211. package/src/actions/scales/editPolicy.js +81 -11
  212. package/src/actions/scales/index.js +6 -0
  213. package/src/actions/scales/materialize.js +5 -4
  214. package/src/actions/scales/offset.js +48 -0
  215. package/src/actions/scales/parallel.js +71 -0
  216. package/src/actions/scales/preview.js +111 -10
  217. package/src/actions/scales/quantitativeColor.js +4 -5
  218. package/src/actions/selection/actions.js +179 -66
  219. package/src/actions/selection/index.js +3 -0
  220. package/src/actions/textMetrics/index.js +56 -0
  221. package/src/actions/theme/actions.js +70 -15
  222. package/src/actions/theme/composition.js +238 -0
  223. package/src/actions/theme/index.js +9 -2
  224. package/src/actions/theme/reconcile.js +313 -121
  225. package/src/actions/theme/state.js +160 -0
  226. package/src/actions/titles/actions.js +8 -8
  227. package/src/actions/titles/resolve.js +3 -3
  228. package/src/actions/violinPlots/create.js +6 -3
  229. package/src/actions/violinPlots/edit.js +2 -1
  230. package/src/core/action.js +117 -35
  231. package/src/core/compositionState.js +6 -1
  232. package/src/core/diagnostics.js +16 -0
  233. package/src/core/extensionRegistry.js +27 -0
  234. package/src/core/font.js +18 -0
  235. package/src/core/identifiers.js +5 -4
  236. package/src/core/immutable.js +10 -3
  237. package/src/core/optionRequirements.js +8 -0
  238. package/src/core/programState.js +21 -1
  239. package/src/core/resourceReferences.js +341 -0
  240. package/src/core/textMetricProfile.js +28 -0
  241. package/src/core/textMetrics.js +24 -3
  242. package/src/core/validation.js +22 -10
  243. package/src/core/vocabulary.js +16 -3
  244. package/src/diagnostics.js +1 -0
  245. package/src/grammar/bars/aggregate.js +4 -1
  246. package/src/grammar/bars/geometry.js +44 -0
  247. package/src/grammar/bin.js +54 -9
  248. package/src/grammar/complete.js +279 -0
  249. package/src/grammar/computed.js +265 -64
  250. package/src/grammar/coordinates.js +37 -0
  251. package/src/grammar/density.js +239 -37
  252. package/src/grammar/displayLabels.js +57 -0
  253. package/src/grammar/facets/dependencies.js +133 -1
  254. package/src/grammar/facets/guides.js +3 -0
  255. package/src/grammar/facets/index.js +7 -47
  256. package/src/grammar/facets/scales.js +15 -18
  257. package/src/grammar/impute.js +341 -0
  258. package/src/grammar/markLabelSelection.js +57 -0
  259. package/src/grammar/markLabels.js +18 -1
  260. package/src/grammar/normalize.js +366 -0
  261. package/src/grammar/pathSeries.js +26 -8
  262. package/src/grammar/pointShapes.js +13 -4
  263. package/src/grammar/polar.js +90 -8
  264. package/src/grammar/regression/index.js +1 -0
  265. package/src/grammar/regression/parameters.js +23 -0
  266. package/src/grammar/roundedRect.js +180 -0
  267. package/src/grammar/rules.js +1 -0
  268. package/src/grammar/scales/colorConsumers.js +20 -1
  269. package/src/grammar/scales/continuous.js +2 -2
  270. package/src/grammar/scales/definition.js +27 -4
  271. package/src/grammar/scales/index.js +1 -0
  272. package/src/grammar/scales/ordinal.js +12 -3
  273. package/src/grammar/scales/policies.js +2 -2
  274. package/src/grammar/scales/size.js +456 -0
  275. package/src/grammar/scales/types.js +8 -0
  276. package/src/grammar/schemas/concreteGraphic.js +14 -2
  277. package/src/grammar/schemas/graphic.js +15 -0
  278. package/src/grammar/schemas/graphicBounds.js +190 -41
  279. package/src/grammar/schemas/semanticPath.js +7 -2
  280. package/src/grammar/statisticalReference.js +103 -0
  281. package/src/grammar/strokeStyle.js +77 -0
  282. package/src/grammar/summary.js +78 -16
  283. package/src/grammar/timeUnit.js +216 -5
  284. package/src/grammar/transformTopology.js +4 -0
  285. package/src/grammar/transforms.js +394 -28
  286. package/src/grammar/weightedStatistics.js +374 -0
  287. package/src/grammar/window.js +221 -16
  288. package/src/layout/aspect.js +80 -0
  289. package/src/layout/facets.js +59 -5
  290. package/src/layout/labels.js +351 -7
  291. package/src/layout/legend.js +4 -4
  292. package/src/layout/legendItems.js +6 -6
  293. package/src/layout/text.js +10 -9
  294. package/src/layout/title.js +9 -9
  295. package/src/materialization/bars/aggregate.js +25 -2
  296. package/src/materialization/bars/histogram.js +84 -24
  297. package/src/materialization/bars/ranged.js +19 -3
  298. package/src/materialization/bars/resolve.js +7 -4
  299. package/src/materialization/composition.js +3 -1
  300. package/src/materialization/coordinateBounds.js +204 -0
  301. package/src/materialization/dependencies.js +36 -0
  302. package/src/materialization/facetGuides/legacyCategorical.js +3 -0
  303. package/src/materialization/facetGuides/placement.js +9 -3
  304. package/src/materialization/facetGuides/preparation.js +13 -8
  305. package/src/materialization/facetHeaders.js +347 -0
  306. package/src/materialization/facets.js +15 -65
  307. package/src/materialization/guides/layout.js +3 -3
  308. package/src/materialization/guides/resources.js +26 -0
  309. package/src/materialization/legends.js +1 -1
  310. package/src/materialization/marks/index.js +11 -5
  311. package/src/materialization/marks/policies.js +2 -1
  312. package/src/materialization/rect.js +25 -12
  313. package/src/materialization/rectConfig.js +5 -1
  314. package/src/materialization/scaleGuideDependencies.js +10 -0
  315. package/src/materialization/scales/map.js +5 -3
  316. package/src/materialization/scales/policies/binnedPosition.js +2 -2
  317. package/src/materialization/scales/policies/offset.js +50 -8
  318. package/src/materialization/scales/policies/series.js +4 -1
  319. package/src/materialization/scales/resolve.js +22 -6
  320. package/src/materialization/selection/items/arc.js +28 -4
  321. package/src/materialization/selection/items/bar.js +30 -3
  322. package/src/materialization/selection/items/common.js +20 -5
  323. package/src/materialization/selection/items/rect.js +28 -4
  324. package/src/materialization/selection/path.js +1 -1
  325. package/src/materialization/selection/point.js +3 -1
  326. package/src/materialization/text.js +265 -14
  327. package/src/materialization/typography.js +31 -0
  328. package/src/mcp/cli.js +5 -3
  329. package/src/persistence/codec.js +65 -0
  330. package/src/persistence/validation.js +185 -0
  331. package/src/persistence.js +74 -0
  332. package/src/renderers/canvas/circle.js +2 -3
  333. package/src/renderers/canvas/index.js +5 -4
  334. package/src/renderers/canvas/line.js +2 -3
  335. package/src/renderers/canvas/native.js +4 -4
  336. package/src/renderers/canvas/path.js +2 -3
  337. package/src/renderers/canvas/rect.js +2 -3
  338. package/src/renderers/canvas/stroke.js +11 -0
  339. package/src/renderers/nativeBackend.js +10 -0
  340. package/src/renderers/options.js +13 -0
  341. package/src/renderers/pdf.js +25 -54
  342. package/src/renderers/png.js +22 -17
  343. package/src/renderers/svg.js +29 -14
  344. package/src/renderers/text.js +1 -11
  345. package/src/selectors/coordinates.js +3 -1
  346. package/src/selectors/datasets.js +38 -5
  347. package/src/selectors/layers.js +10 -4
  348. package/src/selectors/markOwners.js +46 -0
  349. package/src/selectors/scales.js +6 -4
  350. package/src/theme/defaults.js +103 -1
  351. package/src/version.js +2 -0
  352. package/types/accessibility.d.ts +37 -0
  353. package/types/basic.d.ts +10 -2
  354. package/types/diagnostics.d.ts +15 -0
  355. package/types/index.d.ts +90 -0
  356. package/types/pdf.d.ts +9 -0
  357. package/types/persistence.d.ts +7 -0
  358. package/types/png.d.ts +9 -0
  359. package/types/program.d.ts +944 -118
@@ -0,0 +1,160 @@
1
+ import {
2
+ cloneAndFreeze,
3
+ freezeOwned,
4
+ isPlainObject
5
+ } from "../../core/immutable.js";
6
+ import {
7
+ normalizeThemeDefinition,
8
+ resolveThemeTokens
9
+ } from "../../theme/defaults.js";
10
+
11
+ export const LOCAL_THEME_OWNER = "local";
12
+
13
+ function ownArray(value) {
14
+ return freezeOwned([...(value ?? [])]);
15
+ }
16
+
17
+ function requireThemeScope(value) {
18
+ if (!["self", "descendants"].includes(value)) {
19
+ throw new Error(`Unsupported theme scope "${value}".`);
20
+ }
21
+ return value;
22
+ }
23
+
24
+ function requireThemeOwner(value) {
25
+ if (typeof value !== "string" || value.length === 0) {
26
+ throw new TypeError("Theme frame owner must be a non-empty string.");
27
+ }
28
+ return value;
29
+ }
30
+
31
+ export function compositionThemeOwner(id, scope = "descendants") {
32
+ if (typeof id !== "string" || id.length === 0) {
33
+ throw new TypeError("Composition theme owner requires a non-empty id.");
34
+ }
35
+ requireThemeScope(scope);
36
+ return scope === "self" ? `composition:${id}:self` : `composition:${id}`;
37
+ }
38
+
39
+ export function createThemeFrame({
40
+ owner = LOCAL_THEME_OWNER,
41
+ scope = "self",
42
+ definition
43
+ }) {
44
+ const normalized = normalizeThemeDefinition(definition);
45
+ return freezeOwned({
46
+ owner: requireThemeOwner(owner),
47
+ scope: requireThemeScope(scope),
48
+ name: normalized.name,
49
+ tokens: normalized.tokens
50
+ });
51
+ }
52
+
53
+ export function upsertThemeFrame(frames = [], frame) {
54
+ if (!Array.isArray(frames)) {
55
+ throw new TypeError("Theme frames must be an array.");
56
+ }
57
+ if (!isPlainObject(frame)) {
58
+ throw new TypeError("Theme frame must be a plain object.");
59
+ }
60
+ return freezeOwned([
61
+ ...frames.filter(current => current.owner !== frame.owner),
62
+ frame
63
+ ]);
64
+ }
65
+
66
+ export function removeThemeFrameOwner(frames = [], owner) {
67
+ if (!Array.isArray(frames)) {
68
+ throw new TypeError("Theme frames must be an array.");
69
+ }
70
+ requireThemeOwner(owner);
71
+ const next = frames.filter(frame => frame.owner !== owner);
72
+ return freezeOwned({
73
+ frames: freezeOwned(next),
74
+ removed: next.length !== frames.length
75
+ });
76
+ }
77
+
78
+ export function moveLocalThemeScope(localOrder = [], scope) {
79
+ if (!Array.isArray(localOrder)) {
80
+ throw new TypeError("Theme localOrder must be an array.");
81
+ }
82
+ requireThemeScope(scope);
83
+ return freezeOwned([
84
+ ...localOrder.filter(current => current !== scope),
85
+ scope
86
+ ]);
87
+ }
88
+
89
+ function ownCanonicalThemeState(state, composition) {
90
+ const frames = ownArray(state.frames);
91
+ const localOrder = ownArray(state.localOrder);
92
+ const overrides = ownArray(state.overrides);
93
+ const result = { frames, localOrder, overrides };
94
+ if (composition || state.descendantFrames !== undefined) {
95
+ result.descendantFrames = ownArray(state.descendantFrames);
96
+ }
97
+ return cloneAndFreeze(result);
98
+ }
99
+
100
+ export function normalizeThemeState(state, { composition = false } = {}) {
101
+ if (state === undefined) {
102
+ return freezeOwned({
103
+ frames: freezeOwned([]),
104
+ ...(composition ? { descendantFrames: freezeOwned([]) } : {}),
105
+ localOrder: freezeOwned([]),
106
+ overrides: freezeOwned([])
107
+ });
108
+ }
109
+ if (!isPlainObject(state)) {
110
+ throw new TypeError("Program theme state must be a plain object.");
111
+ }
112
+ if (Array.isArray(state.frames)) {
113
+ return ownCanonicalThemeState(state, composition);
114
+ }
115
+
116
+ const name = state.name ?? "light";
117
+ const tokens = state.tokens ?? {};
118
+ const scope = state.scope ?? "self";
119
+ const origin = state.origin?.ownerCompositionId;
120
+ const owner = origin === undefined
121
+ ? LOCAL_THEME_OWNER
122
+ : compositionThemeOwner(origin, "descendants");
123
+ const frame = createThemeFrame({
124
+ owner,
125
+ scope,
126
+ definition: { base: name, tokens }
127
+ });
128
+ return freezeOwned({
129
+ frames: freezeOwned([frame]),
130
+ ...(composition && scope === "descendants"
131
+ ? { descendantFrames: freezeOwned([frame]) }
132
+ : composition
133
+ ? { descendantFrames: freezeOwned([]) }
134
+ : {}),
135
+ localOrder: origin === undefined ? freezeOwned([scope]) : freezeOwned([]),
136
+ overrides: cloneAndFreeze(state.overrides ?? [])
137
+ });
138
+ }
139
+
140
+ export function resolveEffectiveThemeFrame(state) {
141
+ const frames = state?.frames;
142
+ return Array.isArray(frames) ? frames.at(-1) : undefined;
143
+ }
144
+
145
+ export function resolveEffectiveThemeTokens(state) {
146
+ const frame = resolveEffectiveThemeFrame(state);
147
+ return frame === undefined
148
+ ? resolveThemeTokens("light")
149
+ : resolveThemeTokens({ base: frame.name, tokens: frame.tokens });
150
+ }
151
+
152
+ export function setThemeStateOverrides(state, overrides) {
153
+ if (!Array.isArray(overrides)) {
154
+ throw new TypeError("Theme overrides must be an array.");
155
+ }
156
+ return freezeOwned({
157
+ ...state,
158
+ overrides: cloneAndFreeze([...overrides].sort())
159
+ });
160
+ }
@@ -115,12 +115,12 @@ function titleTextAction(kind, create) {
115
115
  }));
116
116
  }
117
117
 
118
- export const editTitleText = titleTextAction("title", false);
119
- export const createTitleText = titleTextAction("title", true);
120
- export const editSubtitleText = titleTextAction("subtitle", false);
121
- export const createSubtitleText = titleTextAction("subtitle", true);
118
+ export const editTitleText = /* @__PURE__ */ titleTextAction("title", false);
119
+ export const createTitleText = /* @__PURE__ */ titleTextAction("title", true);
120
+ export const editSubtitleText = /* @__PURE__ */ titleTextAction("subtitle", false);
121
+ export const createSubtitleText = /* @__PURE__ */ titleTextAction("subtitle", true);
122
122
 
123
- export const rematerializeTitle = action(
123
+ export const rematerializeTitle = /* @__PURE__ */ action(
124
124
  { op: "rematerializeTitle", description: "Rematerialize chart title graphics." },
125
125
  withGuideLayoutValidation(function (args = {}) {
126
126
  noOptions(args, "rematerializeTitle");
@@ -142,7 +142,7 @@ export const rematerializeTitle = action(
142
142
  })
143
143
  );
144
144
 
145
- export const createTitle = action(
145
+ export const createTitle = /* @__PURE__ */ action(
146
146
  {
147
147
  op: "createTitle",
148
148
  description: "Create a chart title and optional subtitle.",
@@ -176,7 +176,7 @@ export const createTitle = action(
176
176
  })
177
177
  );
178
178
 
179
- export const editTitle = action(
179
+ export const editTitle = /* @__PURE__ */ action(
180
180
  {
181
181
  op: "editTitle",
182
182
  description: "Edit one stable chart title resource.",
@@ -214,7 +214,7 @@ export const editTitle = action(
214
214
  })
215
215
  );
216
216
 
217
- export const removeTitle = action(
217
+ export const removeTitle = /* @__PURE__ */ action(
218
218
  {
219
219
  op: "removeTitle",
220
220
  description: "Remove the complete chart title resource.",
@@ -212,7 +212,7 @@ export function resolveTitleLayout(program, config) {
212
212
  program.semanticSpec.title.subtitle,
213
213
  "Chart subtitle"
214
214
  )
215
- }, config);
215
+ }, config, program.materializationConfigs.textMetrics);
216
216
  const horizontal = ["top", "bottom"].includes(config.position);
217
217
  let component;
218
218
  if (horizontal) {
@@ -249,10 +249,10 @@ export function resolveTitleLayout(program, config) {
249
249
  ? undefined
250
250
  : component(block.subtitleLines, block.subtitleCenters);
251
251
  const titleBounds = unionTitleBounds([
252
- resolveTitleComponentBounds(title, config.titleStyle),
252
+ resolveTitleComponentBounds(title, config.titleStyle, program.materializationConfigs.textMetrics),
253
253
  ...(subtitle === undefined
254
254
  ? []
255
- : [resolveTitleComponentBounds(subtitle, config.subtitleStyle)])
255
+ : [resolveTitleComponentBounds(subtitle, config.subtitleStyle, program.materializationConfigs.textMetrics)])
256
256
  ]);
257
257
  validateLayout(
258
258
  config.position,
@@ -2,6 +2,7 @@ import { action } from "../../core/action.js";
2
2
  import { validateOptionObject } from "../../core/validation.js";
3
3
  import { findDataset } from "../../selectors/datasets.js";
4
4
  import { findLayer } from "../../selectors/layers.js";
5
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
5
6
  import {
6
7
  applyFacadeGuides,
7
8
  normalizeAppearance,
@@ -20,12 +21,13 @@ const OPTIONS = Object.freeze([
20
21
  ]);
21
22
  const POSITION_OPTIONS = Object.freeze(["field", "fieldType", "scale"]);
22
23
  const DENSITY_OPTIONS = Object.freeze([
23
- "bandwidth", "extent", "steps", "kernel", "normalization", "width", "side"
24
+ "bandwidth", "extent", "steps", "kernel", "normalization", "weight", "width", "side"
24
25
  ]);
25
26
  const WIDTH_OPTIONS = Object.freeze(["band", "resolve"]);
26
27
  const SPLIT_OPTIONS = Object.freeze(["field", "domain"]);
27
28
  const AREA_OPTIONS = Object.freeze([
28
- "fill", "opacity", "stroke", "strokeWidth", "curve"
29
+ "fill", "opacity", "stroke", "strokeWidth", "curve",
30
+ ...STROKE_STYLE_PROPERTIES
29
31
  ]);
30
32
  const CATEGORICAL_TYPES = Object.freeze(["nominal", "ordinal"]);
31
33
  const OPERATION = "createViolinPlot";
@@ -130,7 +132,7 @@ function guideOptions(guides, x, y, category, color) {
130
132
  };
131
133
  }
132
134
 
133
- export const createViolinPlot = action(
135
+ export const createViolinPlot = /* @__PURE__ */ action(
134
136
  {
135
137
  op: "createViolinPlot",
136
138
  description: "Create a categorical kernel-density violin plot."
@@ -221,6 +223,7 @@ export const createViolinPlot = action(
221
223
  steps: transform.steps,
222
224
  kernel: transform.kernel,
223
225
  normalization: transform.normalization,
226
+ ...(transform.weight === undefined ? {} : { weight: transform.weight }),
224
227
  width: transform.placement.width,
225
228
  side: transform.placement.side
226
229
  },
@@ -74,7 +74,7 @@ function assertSplitSelectionCompatibility(program, owner, changesSplit) {
74
74
  }
75
75
  }
76
76
 
77
- export const editViolinPlot = action(
77
+ export const editViolinPlot = /* @__PURE__ */ action(
78
78
  {
79
79
  op: OPERATION,
80
80
  description: "Revise one violin plot's data and statistical roles."
@@ -181,6 +181,7 @@ export const editViolinPlot = action(
181
181
  steps: transform.steps,
182
182
  kernel: transform.kernel,
183
183
  normalization: transform.normalization,
184
+ ...(transform.weight === undefined ? {} : { weight: transform.weight }),
184
185
  width: transform.placement.width,
185
186
  side: transform.placement.side
186
187
  }
@@ -1,6 +1,9 @@
1
- import { cloneAndFreeze, freezeOwned, isPlainObject } from "./immutable.js";
1
+ import { validateKeys } from "./validation.js";
2
+ import { annotateError } from "./diagnostics.js";
3
+ import { cloneAndFreeze, freezeOwned, isOwned, isPlainObject } from "./immutable.js";
2
4
 
3
5
  const metadataByWrappedAction = new WeakMap();
6
+ const implementationByWrappedAction = new WeakMap();
4
7
  let actionCompletionHook;
5
8
 
6
9
  export function setActionCompletionHook(hook) {
@@ -14,6 +17,14 @@ export function getWrappedActionMetadata(value) {
14
17
  return metadataByWrappedAction.get(value);
15
18
  }
16
19
 
20
+ export function invokeWrappedActionImplementation(value, program, args = {}) {
21
+ const implementation = implementationByWrappedAction.get(value);
22
+ if (implementation === undefined) {
23
+ throw new TypeError("Expected an action created by action().");
24
+ }
25
+ return implementation.call(program, args);
26
+ }
27
+
17
28
  function summarizeObject(value, ancestors = new WeakSet()) {
18
29
  if (ancestors.has(value)) {
19
30
  throw new TypeError("Action arguments must not contain circular references.");
@@ -26,6 +37,8 @@ function summarizeObject(value, ancestors = new WeakSet()) {
26
37
  summary[`${key}Count`] = item.length;
27
38
  } else if (isPlainObject(item)) {
28
39
  summary[key] = summarizeObject(item, ancestors);
40
+ } else if (typeof item === "function") {
41
+ summary[`${key}Type`] = "function";
29
42
  } else if (item !== null && typeof item === "object") {
30
43
  summary[`${key}Type`] = item.constructor?.name ?? "object";
31
44
  } else {
@@ -62,13 +75,59 @@ export function createActionNode({ id, op, description, args }) {
62
75
  });
63
76
  }
64
77
 
78
+ // Persistent child tails make appending the active (last) branch independent
79
+ // of sibling count. The public children property remains a stable frozen Array.
80
+ const childLists = new WeakMap();
81
+
82
+ function childList(node) {
83
+ let list = childLists.get(node);
84
+ if (list !== undefined) return list;
85
+ let tail;
86
+ for (const child of node.children) tail = { value: child, previous: tail };
87
+ list = { tail, length: node.children.length };
88
+ if (isOwned(node)) childLists.set(node, list);
89
+ return list;
90
+ }
91
+
92
+ function withChildList(node, list) {
93
+ let children;
94
+ const next = {};
95
+ for (const key of Object.keys(node)) {
96
+ if (key !== "children") Object.defineProperty(next, key, {
97
+ value: node[key], enumerable: true
98
+ });
99
+ }
100
+ Object.defineProperty(next, "children", {
101
+ enumerable: true,
102
+ get() {
103
+ if (children === undefined) {
104
+ const values = new Array(list.length);
105
+ let item = list.tail;
106
+ for (let index = list.length - 1; index >= 0; index -= 1) {
107
+ values[index] = item.value;
108
+ item = item.previous;
109
+ }
110
+ children = freezeOwned(values);
111
+ }
112
+ return children;
113
+ }
114
+ });
115
+ childLists.set(next, list);
116
+ return freezeOwned(next);
117
+ }
118
+
119
+ function childAt(node, index) {
120
+ const list = childList(node);
121
+ return index === list.length - 1 ? list.tail.value : node.children[index];
122
+ }
123
+
65
124
  function nodeAtPath(root, path) {
66
125
  let node = root;
67
126
  for (const index of path) {
68
- if (!Number.isInteger(index) || index < 0 || index >= node.children.length) {
127
+ if (!Number.isInteger(index) || index < 0 || index >= childList(node).length) {
69
128
  throw new Error(`Unknown parent action path "${path.join(".")}".`);
70
129
  }
71
- node = node.children[index];
130
+ node = childAt(node, index);
72
131
  }
73
132
  return node;
74
133
  }
@@ -78,19 +137,28 @@ export function appendActionNodeAtPath(root, parentPath, actionNode) {
78
137
  throw new TypeError("Parent action path must be an array.");
79
138
  }
80
139
  const parent = nodeAtPath(root, parentPath);
81
- const path = [...parentPath, parent.children.length];
140
+ const path = [...parentPath, childList(parent).length];
82
141
 
83
142
  function append(node, depth) {
143
+ const list = childList(node);
84
144
  if (depth === parentPath.length) {
85
- return freezeOwned({
86
- ...node,
87
- children: freezeOwned([...node.children, actionNode])
145
+ return withChildList(node, {
146
+ tail: { value: actionNode, previous: list.tail }, length: list.length + 1
88
147
  });
89
148
  }
90
149
  const index = parentPath[depth];
91
- const children = [...node.children];
92
- children[index] = append(children[index], depth + 1);
93
- return freezeOwned({ ...node, children: freezeOwned(children) });
150
+ const child = append(childAt(node, index), depth + 1);
151
+ if (index === list.length - 1) {
152
+ return withChildList(node, {
153
+ tail: { value: child, previous: list.tail.previous }, length: list.length
154
+ });
155
+ }
156
+ // Restored/extension traces may address an older sibling explicitly.
157
+ let tail;
158
+ for (let position = 0; position < list.length; position += 1) {
159
+ tail = { value: position === index ? child : node.children[position], previous: tail };
160
+ }
161
+ return withChildList(node, { tail, length: list.length });
94
162
  }
95
163
 
96
164
  return { root: append(root, 0), path };
@@ -128,38 +196,52 @@ export function action(metadata, implementation) {
128
196
  });
129
197
 
130
198
  const wrappedAction = function wrappedAction(args = {}) {
131
- if (!isPlainObject(args)) {
132
- throw new TypeError("Action arguments must be a plain object.");
133
- }
134
-
135
- if (scope === "unit") this._assertUnitProgram(ownedMetadata.op);
136
- if (scope === "composition") this._assertCompositionProgram(ownedMetadata.op);
137
-
138
- const summarizedArgs = summarizeArgs(args);
139
- const entered = this._enterAction({
140
- ...ownedMetadata,
141
- args: summarizedArgs
142
- });
143
- let result = implementation.call(entered, args);
144
-
145
- if (!(result instanceof this.constructor)) {
146
- throw new TypeError(`${ownedMetadata.op} must return a ChartProgram.`);
147
- }
148
-
149
- if (this.actionStack.length === 0 && actionCompletionHook !== undefined) {
150
- result = actionCompletionHook(result, {
151
- source: this,
152
- metadata: ownedMetadata,
199
+ try {
200
+ if (!isPlainObject(args)) {
201
+ throw new TypeError("Action arguments must be a plain object.");
202
+ }
203
+
204
+ if (scope === "unit") this._assertUnitProgram(ownedMetadata.op);
205
+ if (scope === "composition") this._assertCompositionProgram(ownedMetadata.op);
206
+
207
+ const summarizedArgs = summarizeArgs(args);
208
+ const entered = this._enterAction({
209
+ ...ownedMetadata,
153
210
  args: summarizedArgs
154
211
  });
212
+ let result = implementation.call(entered, args);
213
+
155
214
  if (!(result instanceof this.constructor)) {
156
- throw new TypeError("Action completion hook must return a ChartProgram.");
215
+ throw new TypeError(`${ownedMetadata.op} must return a ChartProgram.`);
157
216
  }
217
+
218
+ if (this.actionStack.length === 0 && actionCompletionHook !== undefined) {
219
+ result = actionCompletionHook(result, {
220
+ source: this,
221
+ metadata: ownedMetadata,
222
+ args: summarizedArgs
223
+ });
224
+ if (!(result instanceof this.constructor)) {
225
+ throw new TypeError("Action completion hook must return a ChartProgram.");
226
+ }
227
+ }
228
+
229
+ return result._exitAction();
230
+ } catch (error) {
231
+ throw annotateError(error, { code: "action-failed", operation: ownedMetadata.op });
158
232
  }
159
-
160
- return result._exitAction();
161
233
  };
162
234
 
163
235
  metadataByWrappedAction.set(wrappedAction, ownedMetadata);
236
+ implementationByWrappedAction.set(wrappedAction, implementation);
164
237
  return wrappedAction;
165
238
  }
239
+
240
+ // Private built-in convenience: action() owns the object boundary and trace,
241
+ // while each definition supplies its closed option vocabulary exactly once.
242
+ export function closedAction(metadata, options, implementation) {
243
+ return action(metadata, function (args = {}) {
244
+ if (options !== undefined) validateKeys(args, options, metadata.op);
245
+ return implementation.call(this, args);
246
+ });
247
+ }
@@ -150,8 +150,13 @@ function validateFacetSpec(compositionSpec) {
150
150
  "compositionSpec.facet.repeat requires target, channel, and fields."
151
151
  );
152
152
  }
153
+ const repeatChannel = ["x", "y", "theta", "r"].includes(repeat.channel) ||
154
+ (isPlainObject(repeat.channel) &&
155
+ Object.keys(repeat.channel).length === 1 &&
156
+ typeof repeat.channel.parallelDimension === "string" &&
157
+ repeat.channel.parallelDimension.length > 0);
153
158
  if (typeof repeat.target !== "string" || repeat.target.length === 0 ||
154
- !["x", "y"].includes(repeat.channel) ||
159
+ !repeatChannel ||
155
160
  !Array.isArray(repeat.fields) || repeat.fields.length === 0 ||
156
161
  repeat.fields.some(field => typeof field !== "string" || field.length === 0) ||
157
162
  new Set(repeat.fields).size !== repeat.fields.length) {
@@ -0,0 +1,16 @@
1
+ const detailsByError = new WeakMap();
2
+
3
+ export function getErrorDetails(error) {
4
+ return error !== null && (typeof error === "object" || typeof error === "function")
5
+ ? detailsByError.get(error) : undefined;
6
+ }
7
+
8
+ // Attach metadata without modifying the thrown value or its existing class.
9
+ export function annotateError(error, details) {
10
+ if (!(error instanceof Error)) return error;
11
+ const previous = getErrorDetails(error);
12
+ const merged = { ...details, ...previous };
13
+ if (merged.candidates !== undefined) merged.candidates = Object.freeze([...merged.candidates]);
14
+ detailsByError.set(error, Object.freeze(merged));
15
+ return error;
16
+ }
@@ -4,6 +4,32 @@ import { isPlainObject } from "./immutable.js";
4
4
  const ACTION_NAME_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
5
5
  const DEFINITION_KEYS = new Set(["name", "actions"]);
6
6
  const registeredExtensionNames = new Set();
7
+ const extensionByAction = new Map();
8
+ const builtinOpsByClass = new WeakMap();
9
+
10
+ export function recordBuiltinActions(ProgramClass, additional = []) {
11
+ builtinOpsByClass.set(ProgramClass, new Set([
12
+ ...Object.getOwnPropertyNames(ProgramClass.prototype).flatMap(name => {
13
+ const metadata = getWrappedActionMetadata(ProgramClass.prototype[name]);
14
+ return metadata ? [metadata.op] : [];
15
+ }), ...additional
16
+ ]));
17
+ }
18
+
19
+ export function isBuiltinProgramClass(ProgramClass) {
20
+ return builtinOpsByClass.has(ProgramClass);
21
+ }
22
+
23
+ export function requiredTraceExtension(ProgramClass, op) {
24
+ if (op === "program" || builtinOpsByClass.get(ProgramClass)?.has(op)) return undefined;
25
+ const extension = extensionByAction.get(op);
26
+ if (extension !== undefined) return extension;
27
+ throw new TypeError(`Cannot persist unregistered action "${op}".`);
28
+ }
29
+
30
+ export function hasRegisteredExtension(name) {
31
+ return registeredExtensionNames.has(name);
32
+ }
7
33
 
8
34
  function readDataProperty(object, key, owner) {
9
35
  const descriptor = Object.getOwnPropertyDescriptor(object, key);
@@ -101,4 +127,5 @@ export function registerProgramExtension(ProgramClass, definition) {
101
127
 
102
128
  Object.defineProperties(ProgramClass.prototype, descriptors);
103
129
  registeredExtensionNames.add(name);
130
+ for (const actionName of actionNames) extensionByAction.set(actionName, name);
104
131
  }
@@ -0,0 +1,18 @@
1
+ export const DEFAULT_FONT_FAMILY = "sans-serif";
2
+
3
+ export function normalizeRendererFontWeight(fontWeight) {
4
+ if (typeof fontWeight !== "number") return fontWeight;
5
+ return Math.min(900, Math.max(100, Math.round(fontWeight / 100) * 100));
6
+ }
7
+
8
+ export function textMetricKey({ text, fontFamily, fontSize, fontWeight }) {
9
+ return JSON.stringify([text, fontFamily, fontSize, fontWeight]);
10
+ }
11
+
12
+ export function textMetricFontWeight(value = "normal") {
13
+ if (typeof value === "number") return normalizeRendererFontWeight(value);
14
+ if (value === "normal") return 400;
15
+ if (value === "bold") return 700;
16
+ if (/^[1-9]00$/u.test(value)) return Number(value);
17
+ return undefined;
18
+ }
@@ -1,12 +1,13 @@
1
+ import { annotateError } from "./diagnostics.js";
1
2
  export const USER_ID_SOURCE = "[A-Za-z0-9_-]+";
2
3
 
3
4
  const USER_ID_PATTERN = new RegExp(`^${USER_ID_SOURCE}$`);
4
5
 
5
6
  export function validateUserId(id, label = "ID") {
6
7
  if (typeof id !== "string" || !USER_ID_PATTERN.test(id)) {
7
- throw new TypeError(
8
+ throw annotateError(new TypeError(
8
9
  `${label} must contain only letters, numbers, _ or - and must not be empty.`
9
- );
10
+ ), { code: "invalid-value", optionPath: label });
10
11
  }
11
12
 
12
13
  return id;
@@ -20,9 +21,9 @@ export function resolveOptionalUserId(id, {
20
21
  }) {
21
22
  if (id !== undefined) return validateUserId(id, label);
22
23
  if (ambiguous) {
23
- throw new Error(
24
+ throw annotateError(new Error(
24
25
  `${operation} requires an explicit ${label.toLowerCase()} because its default is ambiguous.`
25
- );
26
+ ), { code: "ambiguous-resource", operation, optionPath: label });
26
27
  }
27
28
  return validateUserId(defaultId, label);
28
29
  }
@@ -22,11 +22,18 @@ export function isOwned(value) {
22
22
  return value !== null && typeof value === "object" && ownedValues.has(value);
23
23
  }
24
24
 
25
- export function cloneAndFreeze(value, ancestors = new WeakSet()) {
25
+ export function cloneAndFreeze(value, ancestors = new WeakSet(), path = "state") {
26
+ if (typeof value === "function") {
27
+ throw new TypeError(`Cannot store a function at ${path} in a ChartProgram.`);
28
+ }
26
29
  if (value === null || typeof value !== "object") {
27
30
  return value;
28
31
  }
29
32
 
33
+ // Only library-owned values are recursively immutable; Object.freeze alone
34
+ // does not prove ownership of a caller's descendants.
35
+ if (isOwned(value)) return value;
36
+
30
37
  if (ancestors.has(value)) {
31
38
  throw new TypeError("Cannot store cyclic values in a ChartProgram.");
32
39
  }
@@ -36,12 +43,12 @@ export function cloneAndFreeze(value, ancestors = new WeakSet()) {
36
43
  let clone;
37
44
 
38
45
  if (Array.isArray(value)) {
39
- clone = value.map(item => cloneAndFreeze(item, ancestors));
46
+ clone = value.map((item, index) => cloneAndFreeze(item, ancestors, `${path}[${index}]`));
40
47
  } else if (isPlainObject(value)) {
41
48
  clone = Object.fromEntries(
42
49
  Object.entries(value).map(([key, item]) => [
43
50
  key,
44
- cloneAndFreeze(item, ancestors)
51
+ cloneAndFreeze(item, ancestors, `${path}.${key}`)
45
52
  ])
46
53
  );
47
54
  } else {
@@ -0,0 +1,8 @@
1
+ // The method's value-producing contract is shared by runtime validation and
2
+ // authoring knowledge; editing can inherit these values from stored state.
3
+ export const IMPUTE_REQUIRED_OPTIONS = Object.freeze({
4
+ constant: Object.freeze(["value"]),
5
+ forward: Object.freeze(["sortBy"]),
6
+ backward: Object.freeze(["sortBy"]),
7
+ linear: Object.freeze(["sortBy"])
8
+ });