ggaction 0.0.23 → 0.0.24

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.
@@ -1,188 +1 @@
1
- import { selectCartesianAxis, axisTargetArgs, assertCartesianAxisSideAvailable } from "../../../selectors/axes.js";
2
- import { validateAxisPosition, resolveAxisFrameConfig } from "./policy.js";
3
- import { withGuideLayoutValidation } from "../../../materialization/guides/layout.js";
4
- import { action } from "../../../core/action.js";
5
- import { isPlainObject } from "../../../core/immutable.js";
6
- import { validateKeys, validateOptionObject, validateNonNegativeFinite } from "../../../core/validation.js";
7
-
8
- import {
9
- AXIS_COMPONENTS,
10
- axisComponentId as graphicId,
11
- hasAxisComponent as hasComponent,
12
- assertRemovableAxisComponent as assertRemovable,
13
- removeAxisComponent as removeComponent
14
- } from "./components.js";
15
-
16
- const OPTIONS = Object.freeze([
17
- "target", "position", "line", "ticks", "labels", "ticksAndLabels", "title", "offset", "underlay"
18
- ]);
19
- const LINE_OPTIONS = Object.freeze(["color", "lineWidth"]);
20
- const TICK_OPTIONS = Object.freeze([
21
- "count", "values", "rounding", "length", "color", "lineWidth", "alongOffset", "strokeDash", "strokeDashMap"
22
- ]);
23
- const LABEL_OPTIONS = Object.freeze([
24
- "count", "values", "rounding", "offset", "format", "color", "fontSize",
25
- "fontFamily", "fontWeight", "rotation", "maxWidth", "wrap",
26
- "lineHeight", "overlap", "alongOffset", "labelMap", "flush", "colorMap", "align"
27
- ]);
28
- const GROUP_OPTIONS = Object.freeze(["count", "values", "rounding", "ticks", "labels"]);
29
- const TITLE_OPTIONS = Object.freeze([
30
- "text", "at", "offset", "rotation", "color", "fontSize",
31
- "fontFamily", "fontWeight", "alongOffset", "align", "baseline", "overlap"
32
- ]);
33
-
34
- function validateNested(args, key, options, operation, { allowFalse = false } = {}) {
35
- if (!Object.hasOwn(args, key)) return;
36
- if (allowFalse && args[key] === false) return;
37
- if (!isPlainObject(args[key])) {
38
- const accepted = allowFalse ? "false or a plain object" : "a plain object";
39
- throw new TypeError(`${operation}.${key} must be ${accepted}.`);
40
- }
41
- validateKeys(args[key], options, `${operation}.${key}`);
42
- }
43
-
44
- function validateArgs(args, operation) {
45
- if (Object.hasOwn(args, "offset")) validateNonNegativeFinite(args.offset, "Axis frame offset");
46
- resolveAxisFrameConfig(undefined, args);
47
- validateOptionObject(args, OPTIONS, operation, {
48
- allowEmpty: false,
49
- emptyMessage: `${operation} requires at least one axis change.`,
50
- emptyError: Error
51
- });
52
- const removable = { allowFalse: true };
53
- validateNested(args, "line", LINE_OPTIONS, operation, removable);
54
- validateNested(args, "ticks", TICK_OPTIONS, operation, removable);
55
- validateNested(args, "labels", LABEL_OPTIONS, operation, removable);
56
- validateNested(args, "ticksAndLabels", GROUP_OPTIONS, operation, removable);
57
- validateNested(args, "title", TITLE_OPTIONS, operation, removable);
58
- if (args.ticksAndLabels !== undefined && (
59
- args.ticks !== undefined || args.labels !== undefined
60
- )) {
61
- throw new Error(
62
- `${operation} cannot combine ticksAndLabels with ticks or labels.`
63
- );
64
- }
65
- if (args.ticksAndLabels !== false && args.ticksAndLabels?.ticks !== undefined) {
66
- validateNested(args.ticksAndLabels, "ticks", ["length", "color", "lineWidth", "alongOffset", "strokeDash", "strokeDashMap"], `${operation}.ticksAndLabels`);
67
- }
68
- if (args.ticksAndLabels !== false && args.ticksAndLabels?.labels !== undefined) {
69
- validateNested(args.ticksAndLabels, "labels", [
70
- "offset", "format", "color", "fontSize", "fontFamily", "fontWeight",
71
- "rotation", "maxWidth", "wrap", "lineHeight", "overlap", "alongOffset", "labelMap", "flush", "colorMap", "align"
72
- ], `${operation}.ticksAndLabels`);
73
- }
74
- }
75
-
76
- function names(channel) {
77
- const prefix = channel === "x" ? "X" : "Y";
78
- return {
79
- operation: `edit${prefix}Axis`,
80
- line: `edit${prefix}AxisLine`,
81
- ticks: `edit${prefix}AxisTicks`,
82
- labels: `edit${prefix}AxisLabels`,
83
- group: `edit${prefix}AxisTicksAndLabels`,
84
- title: `edit${prefix}AxisTitle`,
85
- remove: `remove${prefix}Axis`
86
- };
87
- }
88
-
89
- function buildPlan(program, channel, args, operation, axisId = channel) {
90
- const shared = { ...axisTargetArgs(axisId, channel),
91
- ...(Object.hasOwn(args, "position") ? { position: args.position } : {}) };
92
- const plan = [];
93
- const addLeaf = (component, edit) => {
94
- const value = args[component];
95
- if (value === false) {
96
- assertRemovable(program, channel, component, operation.operation, axisId);
97
- plan.push({ kind: "remove", component });
98
- } else if (value !== undefined) {
99
- plan.push({ kind: "edit", operation: edit, args: { ...shared, ...value } });
100
- } else if ((args.position !== undefined || Object.hasOwn(args, "offset") || Object.hasOwn(args, "underlay")) && hasComponent(program, channel, component, axisId)) {
101
- plan.push({ kind: "edit", operation: edit, args: shared });
102
- }
103
- };
104
-
105
- addLeaf("line", operation.line);
106
- if (args.ticksAndLabels === false) {
107
- assertRemovable(program, channel, "ticks", operation.operation, axisId);
108
- assertRemovable(program, channel, "labels", operation.operation, axisId);
109
- plan.push(
110
- { kind: "remove", component: "ticks" },
111
- { kind: "remove", component: "labels" }
112
- );
113
- } else if (args.ticksAndLabels !== undefined) {
114
- plan.push({
115
- kind: "edit",
116
- operation: operation.group,
117
- args: { ...shared, ...args.ticksAndLabels }
118
- });
119
- } else {
120
- addLeaf("ticks", operation.ticks);
121
- addLeaf("labels", operation.labels);
122
- }
123
- addLeaf("title", operation.title);
124
-
125
- if (plan.length === 0) {
126
- throw new Error(`${operation.operation} requires an existing ${channel}-axis component.`);
127
- }
128
- return plan;
129
- }
130
-
131
- function applyPlan(program, channel, plan, operation, axisId = channel) {
132
- let next = program;
133
- for (const step of plan) {
134
- next = step.kind === "remove"
135
- ? removeComponent(next, channel, step.component, axisId)
136
- : next[step.operation](step.args);
137
- }
138
-
139
- const hasRetainedGraphic = AXIS_COMPONENTS.some(
140
- component => next.graphicSpec.objects[graphicId(channel, component, axisId)] !== undefined
141
- );
142
- if (!hasRetainedGraphic && (
143
- next.semanticSpec.guides.axis?.[axisId] !== undefined ||
144
- next.guideConfigs.axis?.[axisId] !== undefined
145
- )) {
146
- next = next[operation.remove](axisId === channel ? undefined : axisTargetArgs(axisId, channel));
147
- }
148
- return next;
149
- }
150
-
151
- function makeEditAxis(channel) {
152
- const operation = names(channel);
153
- return action(
154
- {
155
- op: operation.operation,
156
- description: `Edit selected existing ${channel}-axis components.`
157
- },
158
- withGuideLayoutValidation(function (args = {}) {
159
- validateArgs(args, operation.operation);
160
- const selected = selectCartesianAxis(this, channel, args, { whole: true });
161
- const axisId = selected.id; args = selected.options;
162
- let source = this;
163
- if (selected.owner?.named && args.position !== undefined) {
164
- const position = validateAxisPosition(channel, args.position);
165
- assertCartesianAxisSideAvailable(this, { id: axisId, channel,
166
- coordinate: selected.owner.coordinate, position });
167
- source = source.editSemantic({ property: `guide.axis.${axisId}.position`, value: position });
168
- }
169
- const frame = resolveAxisFrameConfig(source.guideConfigs.axis?.[axisId]?.frame, args);
170
- source = frame === undefined ? source._withoutMaterializationConfig(["guides", "axis", axisId, "frame"])
171
- : source._withGuideConfig(axisId, "frame", frame);
172
- const plan = buildPlan(source, channel, args, operation, axisId);
173
-
174
- // Run the complete proposal against an immutable speculative branch so a
175
- // later leaf failure cannot begin the returned action trace or state.
176
- applyPlan(source, channel, plan, operation, axisId);
177
- return applyPlan(source, channel, plan, operation, axisId);
178
- })
179
- );
180
- }
181
-
182
- const editXAxis = /* @__PURE__ */ makeEditAxis("x");
183
- const editYAxis = /* @__PURE__ */ makeEditAxis("y");
184
-
185
- export function registerCompleteAxisEditActions(ProgramClass) {
186
- ProgramClass.prototype.editXAxis = editXAxis;
187
- ProgramClass.prototype.editYAxis = editYAxis;
188
- }
1
+ import{resolveAxisTickEditConfig as x}from"./ticks.js";import{resolveAxisLabelEditConfig as L}from"./labels.js";import{validateAxisTickGroupEditConfig as T}from"./tickGroups.js";import{selectCartesianAxis as w,axisTargetArgs as k,assertCartesianAxisSideAvailable as C}from"../../../selectors/axes.js";import{validateAxisPosition as $,resolveAxisFrameConfig as h}from"./policy.js";import{withGuideLayoutValidation as E,withPendingRelativeAxisTitle as j}from"../../../materialization/guides/layout.js";import{action as S}from"../../../core/action.js";import{applyMaterializationPlan as N}from"../../../materialization/planner.js";import{isPlainObject as u}from"../../../core/immutable.js";import{isLabelRelativeTitleOffset as O}from"../../../grammar/axisTextPlacement.js";import{validateKeys as P,validateOptionObject as g,validateNonNegativeFinite as y}from"../../../core/validation.js";import{AXIS_COMPONENTS as z,axisComponentId as M,hasAxisComponent as R,assertRemovableAxisComponent as m,removeAxisComponent as W}from"./components.js";const _=Object.freeze(["target","position","line","ticks","labels","ticksAndLabels","title","offset","underlay"]),G=Object.freeze(["color","lineWidth"]),F=Object.freeze(["count","values","rounding","length","color","lineWidth","alongOffset","strokeDash","strokeDashMap"]),D=Object.freeze(["count","values","rounding","offset","format","color","fontSize","fontFamily","fontWeight","rotation","maxWidth","wrap","lineHeight","overlap","alongOffset","labelMap","flush","flushThreshold","colorMap","align"]),X=Object.freeze(["count","values","rounding","ticks","labels"]),Y=Object.freeze(["text","at","offset","rotation","color","fontSize","fontFamily","fontWeight","alongOffset","align","baseline","overlap"]);function a(e,i,t,n,{allowFalse:o=!1}={}){if(Object.hasOwn(e,i)&&!(o&&e[i]===!1)){if(!u(e[i])){const f=o?"false or a plain object":"a plain object";throw new TypeError(`${n}.${i} must be ${f}.`)}P(e[i],t,`${n}.${i}`)}}function q(e,i){Object.hasOwn(e,"offset")&&y(e.offset,"Axis frame offset"),h(void 0,e),g(e,_,i,{allowEmpty:!1,emptyMessage:`${i} requires at least one axis change.`,emptyError:Error});const t={allowFalse:!0};if(a(e,"line",G,i,t),a(e,"ticks",F,i,t),a(e,"labels",D,i,t),a(e,"ticksAndLabels",X,i,t),a(e,"title",Y,i,t),e.ticksAndLabels!==void 0&&(e.ticks!==void 0||e.labels!==void 0))throw new Error(`${i} cannot combine ticksAndLabels with ticks or labels.`);e.ticksAndLabels!==!1&&e.ticksAndLabels?.ticks!==void 0&&a(e.ticksAndLabels,"ticks",["length","color","lineWidth","alongOffset","strokeDash","strokeDashMap"],`${i}.ticksAndLabels`),e.ticksAndLabels!==!1&&e.ticksAndLabels?.labels!==void 0&&a(e.ticksAndLabels,"labels",["offset","format","color","fontSize","fontFamily","fontWeight","rotation","maxWidth","wrap","lineHeight","overlap","alongOffset","labelMap","flush","flushThreshold","colorMap","align"],`${i}.ticksAndLabels`)}function H(e){const i=e==="x"?"X":"Y";return{operation:`edit${i}Axis`,line:`edit${i}AxisLine`,ticks:`edit${i}AxisTicks`,labels:`edit${i}AxisLabels`,group:`edit${i}AxisTicksAndLabels`,title:`edit${i}AxisTitle`,remove:`remove${i}Axis`}}function K(e,i,t,n){u(t.ticks)&&x(e,i,t.ticks,n),u(t.labels)&&L(e,i,t.labels,n),u(t.ticksAndLabels)&&T(e,i,t.ticksAndLabels,n)}function B(e,i,t,n,o=i){const f={...k(o,i),...Object.hasOwn(t,"position")?{position:t.position}:{}},l=[],d=(c,s)=>{const r=t[c];r===!1?(m(e,i,c,n.operation,o),l.push({kind:"remove",component:c})):r!==void 0?l.push({kind:"edit",operation:s,args:{...f,...r}}):(t.position!==void 0||Object.hasOwn(t,"offset")||Object.hasOwn(t,"underlay"))&&R(e,i,c,o)&&l.push({kind:"edit",operation:s,args:f})};if(d("line",n.line),t.ticksAndLabels===!1?(m(e,i,"ticks",n.operation,o),m(e,i,"labels",n.operation,o),l.push({kind:"remove",component:"ticks"},{kind:"remove",component:"labels"})):t.ticksAndLabels!==void 0?l.push({kind:"edit",operation:n.group,args:{...f,...t.ticksAndLabels}}):(d("ticks",n.ticks),d("labels",n.labels)),d("title",n.title),l.length===0)throw new Error(`${n.operation} requires an existing ${i}-axis component.`);return l}function p(e,i,t,n,o=i){if(O(e.guideConfigs.axis?.[o]?.title?.offset)&&t.some(s=>s.kind==="edit"&&s.operation===n.title)&&e.context.pendingRelativeTitleAxis!==o)return j(e,o,s=>p(s,i,t,n,o));let l=e;const d=O(e.guideConfigs.axis?.[o]?.title?.offset)&&t.some(s=>s.kind==="remove"&&s.component==="title")?[...t.filter(s=>s.kind==="remove"&&s.component==="title"),...t.filter(s=>!(s.kind==="remove"&&s.component==="title"))]:t;for(let s=0;s<d.length;){const r=d[s];if(r.kind==="remove"){l=W(l,i,r.component,o),s+=1;continue}const b=[];for(;s<d.length&&d[s].kind==="edit";){const A=d[s++];b.push({op:A.operation,args:A.args})}l=N(l,b)}return!z.some(s=>l.graphicSpec.objects[M(i,s,o)]!==void 0)&&(l.semanticSpec.guides.axis?.[o]!==void 0||l.guideConfigs.axis?.[o]!==void 0)&&(l=l[n.remove](o===i?void 0:k(o,i))),l}function v(e){const i=H(e);return S({op:i.operation,description:`Edit selected existing ${e}-axis components.`},E(function(t={}){q(t,i.operation);const n=w(this,e,t,{whole:!0}),o=n.id;t=n.options,K(this,e,t,o);let f=this;if(n.owner?.named&&t.position!==void 0){const c=$(e,t.position);C(this,{id:o,channel:e,coordinate:n.owner.coordinate,position:c}),f=f.editSemantic({property:`guide.axis.${o}.position`,value:c})}const l=h(f.guideConfigs.axis?.[o]?.frame,t);f=l===void 0?f._withoutMaterializationConfig(["guides","axis",o,"frame"]):f._withGuideConfig(o,"frame",l);const d=B(f,e,t,i,o);return p(f,e,d,i,o),p(f,e,d,i,o)}))}const U=v("x"),V=v("y");function de(e){e.prototype.editXAxis=U,e.prototype.editYAxis=V}export{de as registerCompleteAxisEditActions};