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
@@ -1,8 +1,10 @@
1
- import { action } from "../../core/action.js";
1
+ import { action, closedAction } from "../../core/action.js";
2
2
  import { validateUserId } from "../../core/identifiers.js";
3
3
  import { isPlainObject } from "../../core/immutable.js";
4
4
  import { validateKeys } from "../../core/validation.js";
5
- import { resolveEligibleLayer } from "../../selectors/layers.js";
5
+ import { collectResourceReferences } from "../../core/resourceReferences.js";
6
+ import { findLayer, resolveEligibleLayer } from "../../selectors/layers.js";
7
+ import { isSourceOwnedText } from "../../grammar/text.js";
6
8
  import { transformPointHighlightChild } from "../../materialization/selection/point.js";
7
9
  import {
8
10
  transformPathHighlightProperties,
@@ -22,6 +24,10 @@ import {
22
24
  normalizeDimOthers,
23
25
  validateUnitInterval
24
26
  } from "../../materialization/selection/styles.js";
27
+ import {
28
+ normalizeThemeState,
29
+ resolveEffectiveThemeTokens
30
+ } from "../theme/state.js";
25
31
 
26
32
  const SELECTOR_KEYS = Object.freeze([
27
33
  "grain", "field", "channel", "property", "op", "value", "values", "min", "max",
@@ -58,32 +64,38 @@ function resolveTarget(program, target, label = "mark selection") {
58
64
  }
59
65
 
60
66
  function hasLegendSelection(program, target, selection) {
61
- const legend = program.guideConfigs.legend?.series ??
62
- program.guideConfigs.legend?.color;
63
67
  const selector = program.materializationConfigs.selections?.[selection]?.selector;
64
- return legend?.target === target &&
65
- selector?.field !== undefined &&
66
- selector.field === legend.field;
68
+ const layer = findLayer(program, target);
69
+ const field = selector?.field ?? layer?.encoding?.[selector?.channel]?.field;
70
+ if (field === undefined) return false;
71
+ return ["series", "color", "stroke"].some(kind => {
72
+ const legend = program.guideConfigs.legend?.[kind];
73
+ return legend?.target === target && legend.field === field &&
74
+ (selector?.channel === undefined || legend.channels.includes(selector.channel));
75
+ });
67
76
  }
68
77
 
69
- function categoricalLegendKind(program, target) {
70
- return ["series", "color"].find(
78
+ function categoricalLegendKinds(program, target) {
79
+ return ["series", "color", "stroke"].filter(
71
80
  kind => program.guideConfigs.legend?.[kind]?.target === target
72
81
  );
73
82
  }
74
83
 
75
84
  function resetCategoricalLegendSymbols(program, target) {
76
- const kind = categoricalLegendKind(program, target);
77
- if (kind === undefined) return program;
85
+ const kinds = categoricalLegendKinds(program, target);
86
+ if (kinds.length === 0) return program;
78
87
  let next = program;
79
- for (const id of legendGraphicIds(kind).filter(id => id.includes("Symbol"))) {
80
- const graphic = next.graphicSpec.objects[id];
81
- if (graphic === undefined) continue;
82
- next = graphic.type === "collection"
83
- ? next.editGraphics({ target: id, property: "items", value: [] })
84
- : next.editGraphics({ target: id, property: "length", value: 0 });
88
+ for (const kind of kinds) {
89
+ for (const id of legendGraphicIds(kind).filter(id => id.includes("Symbol"))) {
90
+ const graphic = next.graphicSpec.objects[id];
91
+ if (graphic === undefined) continue;
92
+ next = graphic.type === "collection"
93
+ ? next.editGraphics({ target: id, property: "items", value: [] })
94
+ : next.editGraphics({ target: id, property: "length", value: 0 });
95
+ }
96
+ next = next.rematerializeLegendSymbols({ kind });
85
97
  }
86
- return next.rematerializeLegendSymbols();
98
+ return next;
87
99
  }
88
100
 
89
101
  function targetHighlightEntries(program, target) {
@@ -91,7 +103,32 @@ function targetHighlightEntries(program, target) {
91
103
  .filter(([, config]) => config.target === target);
92
104
  }
93
105
 
94
- function rebuildTargetHighlights(program, target) {
106
+ function namedLabelDependents(program, selection) {
107
+ const referenced = new Set(collectResourceReferences(program, {
108
+ kind: "selection",
109
+ id: selection
110
+ }).filter(reference =>
111
+ reference.ownerKind === "markConfig" &&
112
+ reference.path.join(".") === "labelAuthoring.selection.id"
113
+ ).map(reference => reference.ownerId));
114
+ return Object.entries(program.markConfigs)
115
+ .filter(([id, config]) => {
116
+ const layer = findLayer(program, id);
117
+ return isSourceOwnedText(layer) &&
118
+ config?.labelAuthoring?.selection?.kind === "named" &&
119
+ referenced.has(id);
120
+ })
121
+ .map(([id]) => id)
122
+ .sort();
123
+ }
124
+
125
+ function rematerializeLabels(program, ids) {
126
+ let next = program;
127
+ for (const id of ids) next = next.rematerializeTextMark({ id });
128
+ return next;
129
+ }
130
+
131
+ function rebuildTargetHighlights(program, target, { labels = [] } = {}) {
95
132
  const layer = resolveTarget(program, target, "highlight mark");
96
133
  const highlights = targetHighlightEntries(program, target);
97
134
  let baseline = program;
@@ -105,12 +142,26 @@ function rebuildTargetHighlights(program, target) {
105
142
  baseline = baseline[requireSelectionPolicy(
106
143
  layer.mark.type
107
144
  ).rematerializeOp]({ id: target });
145
+ baseline = rematerializeLabels(baseline, labels);
108
146
  baseline = resetCategoricalLegendSymbols(baseline, target);
109
147
  return highlights.length === 0
110
148
  ? baseline
111
149
  : baseline.rematerializeMarkHighlights({ target, highlights });
112
150
  }
113
151
 
152
+ export function rematerializeLabelsBeforeHighlights(
153
+ program,
154
+ target,
155
+ labels,
156
+ { skipWithoutHighlights = false } = {}
157
+ ) {
158
+ return targetHighlightEntries(program, target).length === 0
159
+ ? skipWithoutHighlights
160
+ ? program
161
+ : rematerializeLabels(program, labels)
162
+ : rebuildTargetHighlights(program, target, { labels });
163
+ }
164
+
114
165
  function selectedKeys(args, resolved) {
115
166
  if (args.keys === undefined) return resolved.keys;
116
167
  if (!Array.isArray(args.keys) || !args.keys.every(key =>
@@ -155,9 +206,10 @@ function editSelectedItems(
155
206
  }
156
207
 
157
208
  function applyHighlight(program, config, keys) {
209
+ const style = resolveHighlightStyle(program, config);
158
210
  let next = program[requireSelectionPolicy(config.markType).applyHighlightOp]({
159
211
  selection: config.selection,
160
- style: config.style,
212
+ style,
161
213
  keys
162
214
  });
163
215
  if (config.dimOthers !== false) {
@@ -172,10 +224,63 @@ function applyHighlight(program, config, keys) {
172
224
  : next;
173
225
  }
174
226
 
175
- export const selectMarks = action(
176
- { op: "selectMarks", description: "Create one reusable selection over final mark items." },
227
+ function highlightPaintProperty(markType) {
228
+ return ["line", "rule", "tick"].includes(markType) ? "stroke" : "fill";
229
+ }
230
+
231
+ function requestedPaintSource(args, markType, style) {
232
+ const property = highlightPaintProperty(markType);
233
+ const explicit = args.color !== undefined || args[property] !== undefined;
234
+ if (explicit) return "explicit";
235
+ return Object.hasOwn(style, property) ? "theme" : "preserve";
236
+ }
237
+
238
+ function tracePaintSource(program, id, config) {
239
+ let source;
240
+ for (const node of program.trace.children) {
241
+ if (node.op !== "highlightMarks") continue;
242
+ const requestedId = node.args.selection ?? node.args.id ??
243
+ `${node.args.target ?? config.target}Selection`;
244
+ if (requestedId !== id) continue;
245
+ const property = highlightPaintProperty(config.markType);
246
+ const explicit = node.args.color !== undefined ||
247
+ node.args[property] !== undefined;
248
+ source = explicit
249
+ ? "explicit"
250
+ : Object.hasOwn(config.style, property) ? "theme" : "preserve";
251
+ }
252
+ return source ?? "explicit";
253
+ }
254
+
255
+ function normalizeStoredHighlightConfig(program, id, config) {
256
+ return config.paintSource === undefined
257
+ ? { ...config, paintSource: tracePaintSource(program, id, config) }
258
+ : config;
259
+ }
260
+
261
+ function resolveHighlightStyle(program, config) {
262
+ if (config.paintSource !== "theme") return config.style;
263
+ const property = highlightPaintProperty(config.markType);
264
+ return {
265
+ ...config.style,
266
+ [property]: resolveEffectiveThemeTokens(normalizeThemeState(
267
+ program.materializationConfigs.theme
268
+ )).highlight
269
+ };
270
+ }
271
+
272
+ export function rematerializeThemeHighlights(program) {
273
+ const targets = [...new Set(Object.values(
274
+ program.materializationConfigs.highlights ?? {}
275
+ ).map(config => config.target))];
276
+ let next = program;
277
+ for (const target of targets) next = rebuildTargetHighlights(next, target);
278
+ return next;
279
+ }
280
+
281
+ export const selectMarks = /* @__PURE__ */ closedAction(
282
+ { op: "selectMarks", description: "Create one reusable selection over final mark items." }, SELECT_OPTIONS,
177
283
  function (args = {}) {
178
- validateKeys(args, SELECT_OPTIONS, "selectMarks");
179
284
  const layer = resolveTarget(this, args.target);
180
285
  const resolved = resolveMarkSelection(this, layer.id, selectorFrom(args));
181
286
  const id = resolveSelectionCreationId(this, args.id, layer.id);
@@ -185,20 +290,19 @@ export const selectMarks = action(
185
290
  }
186
291
  );
187
292
 
188
- export const editMarkSelection = action(
293
+ export const editMarkSelection = /* @__PURE__ */ closedAction(
189
294
  {
190
295
  op: "editMarkSelection",
191
296
  description: "Replace one stored mark selector while preserving its identity and target."
192
- },
297
+ }, EDIT_SELECTION_OPTIONS,
193
298
  function (args = {}) {
194
- validateKeys(args, EDIT_SELECTION_OPTIONS, "editMarkSelection");
195
299
  const current = resolveStoredSelection(this, args.selection);
196
300
  const replacement = resolveMarkSelection(
197
301
  this,
198
302
  current.definition.target,
199
303
  selectorFrom(args)
200
304
  );
201
- const next = this
305
+ let next = this
202
306
  ._withSelectionConfig(current.id, {
203
307
  target: current.definition.target,
204
308
  selector: replacement.selector
@@ -207,19 +311,24 @@ export const editMarkSelection = action(
207
311
  const hasDependentHighlight = Object.values(
208
312
  next.materializationConfigs.highlights ?? {}
209
313
  ).some(config => config.selection === current.id);
210
- return hasDependentHighlight
211
- ? rebuildTargetHighlights(next, current.definition.target)
212
- : next;
314
+ const labels = namedLabelDependents(this, current.id);
315
+ if (hasDependentHighlight) {
316
+ return rematerializeLabelsBeforeHighlights(
317
+ next,
318
+ current.definition.target,
319
+ labels
320
+ );
321
+ }
322
+ return rematerializeLabels(next, labels);
213
323
  }
214
324
  );
215
325
 
216
- export const removeMarkHighlight = action(
326
+ export const removeMarkHighlight = /* @__PURE__ */ closedAction(
217
327
  {
218
328
  op: "removeMarkHighlight",
219
329
  description: "Remove one stored highlight assignment and restore the clean mark baseline."
220
- },
330
+ }, REMOVE_SELECTION_OPTIONS,
221
331
  function (args = {}) {
222
- validateKeys(args, REMOVE_SELECTION_OPTIONS, "removeMarkHighlight");
223
332
  const current = resolveStoredSelection(this, args.selection);
224
333
  const dependent = Object.entries(
225
334
  this.materializationConfigs.highlights ?? {}
@@ -237,14 +346,19 @@ export const removeMarkHighlight = action(
237
346
  }
238
347
  );
239
348
 
240
- export const removeMarkSelection = action(
349
+ export const removeMarkSelection = /* @__PURE__ */ closedAction(
241
350
  {
242
351
  op: "removeMarkSelection",
243
352
  description: "Remove one stored selection after removing its dependent highlight."
244
- },
353
+ }, REMOVE_SELECTION_OPTIONS,
245
354
  function (args = {}) {
246
- validateKeys(args, REMOVE_SELECTION_OPTIONS, "removeMarkSelection");
247
355
  const current = resolveStoredSelection(this, args.selection);
356
+ const labelDependents = namedLabelDependents(this, current.id);
357
+ if (labelDependents.length > 0) {
358
+ throw new Error(
359
+ `Selection "${current.id}" is referenced by attached labels: ${labelDependents.join(", ")}.`
360
+ );
361
+ }
248
362
  const hasDependentHighlight = Object.values(
249
363
  this.materializationConfigs.highlights ?? {}
250
364
  ).some(config => config.selection === current.id);
@@ -258,10 +372,9 @@ export const removeMarkSelection = action(
258
372
  }
259
373
  );
260
374
 
261
- export const applyPointHighlight = action(
262
- { op: "applyPointHighlight", description: "Apply selected point appearance and geometry." },
375
+ export const applyPointHighlight = /* @__PURE__ */ closedAction(
376
+ { op: "applyPointHighlight", description: "Apply selected point appearance and geometry." }, INTERNAL_SELECTION_OPTIONS,
263
377
  function (args = {}) {
264
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyPointHighlight");
265
378
  const resolved = resolveStoredSelection(this, args.selection);
266
379
  const keys = selectedKeys(args, resolved);
267
380
  if (resolved.items[0]?.markType !== "point" && resolved.items.length > 0) {
@@ -287,6 +400,15 @@ function transformRectangularProperties(properties, style, offset = false) {
287
400
  };
288
401
  }
289
402
 
403
+ function transformRectangularHighlightChild(item, style, offset) {
404
+ return {
405
+ ...item,
406
+ properties: item.type === "path"
407
+ ? transformPathHighlightProperties(item.properties, style)
408
+ : transformRectangularProperties(item.properties, style, offset)
409
+ };
410
+ }
411
+
290
412
  function applyRectangularHighlight(
291
413
  program,
292
414
  args,
@@ -301,22 +423,18 @@ function applyRectangularHighlight(
301
423
  throw new Error(`${operation} requires a ${markType} selection.`);
302
424
  }
303
425
  if (keys.length === 0) return program;
304
- return editSelectedItems(program, resolved, keys, item => ({
305
- ...item,
306
- properties: transformRectangularProperties(
307
- item.properties, args.style, offset
308
- )
309
- }));
426
+ return editSelectedItems(program, resolved, keys, item =>
427
+ transformRectangularHighlightChild(item, args.style, offset));
310
428
  }
311
429
 
312
- export const applyBarHighlight = action(
430
+ export const applyBarHighlight = /* @__PURE__ */ action(
313
431
  { op: "applyBarHighlight", description: "Apply selected bar appearance." },
314
432
  function (args = {}) {
315
433
  return applyRectangularHighlight(this, args, "applyBarHighlight", "bar");
316
434
  }
317
435
  );
318
436
 
319
- export const applyRectHighlight = action(
437
+ export const applyRectHighlight = /* @__PURE__ */ action(
320
438
  { op: "applyRectHighlight", description: "Apply selected rect appearance." },
321
439
  function (args = {}) {
322
440
  return applyRectangularHighlight(
@@ -329,10 +447,9 @@ export const applyRectHighlight = action(
329
447
  }
330
448
  );
331
449
 
332
- export const applyPathHighlight = action(
333
- { op: "applyPathHighlight", description: "Apply selected line or area path appearance and offset." },
450
+ export const applyPathHighlight = /* @__PURE__ */ closedAction(
451
+ { op: "applyPathHighlight", description: "Apply selected line or area path appearance and offset." }, INTERNAL_SELECTION_OPTIONS,
334
452
  function (args = {}) {
335
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyPathHighlight");
336
453
  const resolved = resolveStoredSelection(this, args.selection);
337
454
  const keys = selectedKeys(args, resolved);
338
455
  const markType = resolved.items[0]?.markType;
@@ -350,10 +467,9 @@ export const applyPathHighlight = action(
350
467
  }
351
468
  );
352
469
 
353
- export const applyRuleHighlight = action(
354
- { op: "applyRuleHighlight", description: "Apply selected rule appearance and offset." },
470
+ export const applyRuleHighlight = /* @__PURE__ */ closedAction(
471
+ { op: "applyRuleHighlight", description: "Apply selected rule appearance and offset." }, INTERNAL_SELECTION_OPTIONS,
355
472
  function (args = {}) {
356
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyRuleHighlight");
357
473
  const resolved = resolveStoredSelection(this, args.selection);
358
474
  const keys = selectedKeys(args, resolved);
359
475
  if (
@@ -370,10 +486,9 @@ export const applyRuleHighlight = action(
370
486
  }
371
487
  );
372
488
 
373
- export const dimUnselectedMarkItems = action(
374
- { op: "dimUnselectedMarkItems", description: "Dim the complement of one mark selection." },
489
+ export const dimUnselectedMarkItems = /* @__PURE__ */ closedAction(
490
+ { op: "dimUnselectedMarkItems", description: "Dim the complement of one mark selection." }, INTERNAL_DIM_OPTIONS,
375
491
  function (args = {}) {
376
- validateKeys(args, INTERNAL_DIM_OPTIONS, "dimUnselectedMarkItems");
377
492
  const opacity = validateUnitInterval(args.opacity, "Dim opacity");
378
493
  const resolved = resolveStoredSelection(this, args.selection);
379
494
  const keys = selectedKeys(args, resolved);
@@ -384,10 +499,9 @@ export const dimUnselectedMarkItems = action(
384
499
  }
385
500
  );
386
501
 
387
- export const placeSelectedMarkItemsLast = action(
388
- { op: "placeSelectedMarkItemsLast", description: "Place selected collection items after their complement." },
502
+ export const placeSelectedMarkItemsLast = /* @__PURE__ */ closedAction(
503
+ { op: "placeSelectedMarkItemsLast", description: "Place selected collection items after their complement." }, INTERNAL_ORDER_OPTIONS,
389
504
  function (args = {}) {
390
- validateKeys(args, INTERNAL_ORDER_OPTIONS, "placeSelectedMarkItemsLast");
391
505
  const resolved = resolveStoredSelection(this, args.selection);
392
506
  const keys = selectedKeys(args, resolved);
393
507
  if (keys.length === 0 || keys.length === resolved.items.length) {
@@ -405,17 +519,16 @@ export const placeSelectedMarkItemsLast = action(
405
519
  }
406
520
  );
407
521
 
408
- export const rematerializeMarkHighlights = action(
409
- { op: "rematerializeMarkHighlights", description: "Reapply stored highlight assignments to one rematerialized mark." },
522
+ export const rematerializeMarkHighlights = /* @__PURE__ */ closedAction(
523
+ { op: "rematerializeMarkHighlights", description: "Reapply stored highlight assignments to one rematerialized mark." }, REMATERIALIZE_OPTIONS,
410
524
  function (args = {}) {
411
- validateKeys(args, REMATERIALIZE_OPTIONS, "rematerializeMarkHighlights");
412
525
  validateUserId(args.target, "Highlight target id");
413
526
  if (!Array.isArray(args.highlights)) {
414
527
  throw new TypeError("rematerializeMarkHighlights requires highlight entries.");
415
528
  }
416
529
  const prepared = args.highlights.map(([id, config]) => ({
417
530
  id,
418
- config,
531
+ config: normalizeStoredHighlightConfig(this, id, config),
419
532
  keys: resolveStoredSelection(this, config.selection).keys
420
533
  }));
421
534
  let next = this;
@@ -430,10 +543,9 @@ export const rematerializeMarkHighlights = action(
430
543
  }
431
544
  );
432
545
 
433
- export const highlightMarks = action(
434
- { op: "highlightMarks", description: "Select and emphasize final visual mark items." },
546
+ export const highlightMarks = /* @__PURE__ */ closedAction(
547
+ { op: "highlightMarks", description: "Select and emphasize final visual mark items." }, HIGHLIGHT_OPTIONS,
435
548
  function (args = {}) {
436
- validateKeys(args, HIGHLIGHT_OPTIONS, "highlightMarks");
437
549
  if (args.select !== undefined && args.selection !== undefined) {
438
550
  throw new Error("highlightMarks accepts select or selection, not both.");
439
551
  }
@@ -492,6 +604,7 @@ export const highlightMarks = action(
492
604
  selection,
493
605
  markType: layer.mark.type,
494
606
  style,
607
+ paintSource: requestedPaintSource(args, layer.mark.type, style),
495
608
  dimOthers,
496
609
  bringToFront
497
610
  };
@@ -9,12 +9,15 @@ import {
9
9
  highlightMarks,
10
10
  placeSelectedMarkItemsLast,
11
11
  rematerializeMarkHighlights,
12
+ rematerializeThemeHighlights,
12
13
  removeMarkHighlight,
13
14
  removeMarkSelection,
14
15
  selectMarks
15
16
  } from "./actions.js";
17
+ import { registerThemeHighlightReconciler } from "../theme/reconcile.js";
16
18
 
17
19
  export function registerSelectionActions(ProgramClass) {
20
+ registerThemeHighlightReconciler(rematerializeThemeHighlights);
18
21
  ProgramClass.prototype.selectMarks = selectMarks;
19
22
  ProgramClass.prototype.editMarkSelection = editMarkSelection;
20
23
  ProgramClass.prototype.removeMarkHighlight = removeMarkHighlight;
@@ -0,0 +1,56 @@
1
+ import { action, closedAction } from "../../core/action.js";
2
+ import { noOptions } from "../../core/validation.js";
3
+ import { normalizeTextMetricProfile } from "../../core/textMetricProfile.js";
4
+ import { rematerializeTypography } from "../../materialization/typography.js";
5
+
6
+ function metricsProgram(parent, child) {
7
+ return typeof child.applyTextMetrics === "function" ? child : new parent.constructor({
8
+ ...child, actionSequence: child._actionSequence
9
+ });
10
+ }
11
+
12
+ export function inheritTextMetrics(parent, child) {
13
+ const profile = parent.materializationConfigs.textMetrics;
14
+ return profile === undefined ? child : metricsProgram(parent, child).applyTextMetrics({ profile });
15
+ }
16
+
17
+ function applyProfile(program, profile) {
18
+ let next = profile === undefined
19
+ ? program._withoutMaterializationConfig(["textMetrics"])
20
+ : program._withMaterializationConfig(["textMetrics"], profile);
21
+ if (next.compositionSpec !== undefined) {
22
+ const children = Object.fromEntries(next.compositionSpec.children.map(id => {
23
+ const child = next.children[id];
24
+ return [id, profile === undefined
25
+ ? child.materializationConfigs.textMetrics === undefined ? child : metricsProgram(next, child).removeTextMetrics()
26
+ : inheritTextMetrics(next, child)];
27
+ }));
28
+ next = next._withCompositionState({ children, compositionSpec: next.compositionSpec });
29
+ for (const id of next.compositionSpec.children) next = next.useProgram({ id });
30
+ return next.materializeComposition();
31
+ }
32
+ return rematerializeTypography(next);
33
+ }
34
+
35
+ export const applyTextMetrics = /* @__PURE__ */ closedAction(
36
+ { op: "applyTextMetrics", description: "Apply measured text widths to chart layout.", scope: "any" }, ["profile"],
37
+ function (args = {}) {
38
+ const profile = normalizeTextMetricProfile(args.profile);
39
+ applyProfile(this, profile);
40
+ return applyProfile(this, profile);
41
+ }
42
+ );
43
+
44
+ export const removeTextMetrics = /* @__PURE__ */ action(
45
+ { op: "removeTextMetrics", description: "Restore estimated text layout.", scope: "any" },
46
+ function (args = {}) {
47
+ noOptions(args, "removeTextMetrics");
48
+ if (this.materializationConfigs.textMetrics === undefined) throw new Error("removeTextMetrics requires an active profile.");
49
+ applyProfile(this, undefined);
50
+ return applyProfile(this, undefined);
51
+ }
52
+ );
53
+
54
+ export function registerTextMetricActions(ProgramClass) {
55
+ Object.assign(ProgramClass.prototype, { applyTextMetrics, removeTextMetrics });
56
+ }
@@ -1,43 +1,98 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { noOptions, validateOptionObject } from "../../core/validation.js";
3
- import { THEME_NAMES } from "../../theme/defaults.js";
3
+ import { normalizeThemeDefinition } from "../../theme/defaults.js";
4
+ import {
5
+ LOCAL_THEME_OWNER,
6
+ createThemeFrame,
7
+ moveLocalThemeScope,
8
+ normalizeThemeState,
9
+ removeThemeFrameOwner,
10
+ upsertThemeFrame
11
+ } from "./state.js";
4
12
 
5
- export const applyTheme = action(
13
+ let compositionThemeHandlers;
14
+
15
+ export function registerCompositionThemeHandlers(handlers) {
16
+ if (handlers === undefined ||
17
+ typeof handlers.apply !== "function" ||
18
+ typeof handlers.remove !== "function") {
19
+ throw new TypeError("Composition theme handlers must provide apply and remove functions.");
20
+ }
21
+ compositionThemeHandlers = handlers;
22
+ }
23
+
24
+ function requireCompositionThemeHandlers() {
25
+ if (compositionThemeHandlers === undefined) {
26
+ throw new Error("Composition theme actions are unavailable from this entry point.");
27
+ }
28
+ return compositionThemeHandlers;
29
+ }
30
+
31
+ export const applyTheme = /* @__PURE__ */ action(
6
32
  {
7
33
  op: "applyTheme",
8
- description: "Apply persistent visual defaults to the chart program."
34
+ description: "Apply persistent visual defaults to the chart program.",
35
+ scope: "any"
9
36
  },
10
37
  function (args = {}) {
11
- validateOptionObject(args, ["theme"], "applyTheme", {
38
+ validateOptionObject(args, ["theme", "scope"], "applyTheme", {
12
39
  allowEmpty: false,
13
40
  emptyMessage: "applyTheme requires theme.",
14
41
  emptyError: Error
15
42
  });
16
- if (!THEME_NAMES.includes(args.theme)) {
17
- throw new Error(`Unsupported theme "${args.theme}".`);
43
+ if (!Object.hasOwn(args, "theme")) {
44
+ throw new Error("applyTheme requires theme.");
18
45
  }
19
- const previous = this.materializationConfigs.theme;
46
+ const definition = normalizeThemeDefinition(args.theme);
47
+ if (args.scope !== undefined &&
48
+ !["self", "descendants"].includes(args.scope)) {
49
+ throw new Error(`Unsupported theme scope "${args.scope}".`);
50
+ }
51
+ if (this.compositionSpec !== undefined) {
52
+ return requireCompositionThemeHandlers().apply(
53
+ this,
54
+ { base: definition.name, tokens: definition.tokens },
55
+ args.scope ?? "descendants"
56
+ );
57
+ }
58
+ const scope = "self";
59
+ const previous = normalizeThemeState(this.materializationConfigs.theme);
60
+ const frame = createThemeFrame({
61
+ owner: LOCAL_THEME_OWNER,
62
+ scope,
63
+ definition: { base: definition.name, tokens: definition.tokens }
64
+ });
20
65
  return this._withMaterializationConfig(["theme"], {
21
- name: args.theme,
22
- overrides: previous?.overrides ?? []
66
+ ...previous,
67
+ frames: upsertThemeFrame(previous.frames, frame),
68
+ localOrder: moveLocalThemeScope(previous.localOrder, scope)
23
69
  });
24
70
  }
25
71
  );
26
72
 
27
- export const removeTheme = action(
73
+ export const removeTheme = /* @__PURE__ */ action(
28
74
  {
29
75
  op: "removeTheme",
30
- description: "Remove program theme defaults while preserving local styles."
76
+ description: "Remove program theme defaults while preserving local styles.",
77
+ scope: "any"
31
78
  },
32
79
  function (args = {}) {
33
80
  noOptions(args, "removeTheme");
34
- if (this.materializationConfigs.theme === undefined) {
81
+ if (this.compositionSpec !== undefined) {
82
+ return requireCompositionThemeHandlers().remove(this);
83
+ }
84
+ const previous = normalizeThemeState(this.materializationConfigs.theme);
85
+ const removed = removeThemeFrameOwner(
86
+ previous.frames,
87
+ LOCAL_THEME_OWNER
88
+ );
89
+ if (!removed.removed) {
35
90
  throw new Error("removeTheme requires an active program theme.");
36
91
  }
37
92
  return this._withMaterializationConfig(["theme"], {
38
- ...this.materializationConfigs.theme,
39
- name: "light",
40
- removing: true
93
+ ...previous,
94
+ frames: removed.frames,
95
+ localOrder: previous.localOrder.filter(scope => scope !== "self")
41
96
  });
42
97
  }
43
98
  );