svelteplot 0.5.1-pr-238.4 → 0.5.1-pr-244.1

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,6 +1,5 @@
1
- import type { ChannelName, ScaleName, ScaleType, ScaledChannelName } from './types/index.js';
1
+ import type { ScaleName, ScaleType, ScaledChannelName } from './types/index.js';
2
2
  export declare const SCALE_TYPES: Record<ScaleName, symbol>;
3
- export declare const ORIGINAL_NAME_KEYS: Record<ChannelName, symbol>;
4
3
  export declare const SCALES: ScaleName[];
5
4
  export declare const VALID_SCALE_TYPES: Record<ScaleName, Set<ScaleType>>;
6
5
  /**
package/dist/constants.js CHANGED
@@ -10,28 +10,6 @@ export const SCALE_TYPES = {
10
10
  fy: Symbol('fy'),
11
11
  projection: Symbol('projection')
12
12
  };
13
- export const ORIGINAL_NAME_KEYS = {
14
- x: Symbol('origName_x'),
15
- x1: Symbol('origName_x1'),
16
- x2: Symbol('origName_x2'),
17
- y: Symbol('origName_y'),
18
- y1: Symbol('origName_y1'),
19
- y2: Symbol('origName_y2'),
20
- fill: Symbol('origName_color'),
21
- stroke: Symbol('origName_color'),
22
- opacity: Symbol('origName_opacity'),
23
- symbol: Symbol('origName_symbol'),
24
- r: Symbol('origName_r'),
25
- z: Symbol('origName_z'),
26
- sort: Symbol('origName_sort'),
27
- filter: Symbol('origName_filter'),
28
- interval: Symbol('origName_interval'),
29
- length: Symbol('origName_length'),
30
- fx: Symbol('origName_fx'),
31
- fy: Symbol('origName_fy'),
32
- fillOpacity: Symbol('origName_opacity'),
33
- strokeOpacity: Symbol('origName_opacity')
34
- };
35
13
  export const SCALES = [
36
14
  'x',
37
15
  'y',
@@ -1,5 +1,10 @@
1
1
  import { isDate } from './typeChecks.js';
2
2
  export default function (value) {
3
3
  const t = typeof value;
4
- return t === 'string' || t === 'number' || t === 'boolean' || isDate(value) || t === null;
4
+ return (t === 'string' ||
5
+ t === 'number' ||
6
+ t === 'boolean' ||
7
+ t === 'object' ||
8
+ isDate(value) ||
9
+ t === null);
5
10
  }
@@ -1,7 +1,6 @@
1
1
  import { min, max, mode, sum, mean, median, variance, deviation, quantile } from 'd3-array';
2
2
  import { resolveChannel } from './resolve.js';
3
3
  import { POSITION_CHANNELS } from './index.js';
4
- import { ORIGINAL_NAME_KEYS } from '../constants.js';
5
4
  const niceReduceNames = {
6
5
  count: 'Frequency',
7
6
  deviation: 'Standard Deviation',
@@ -73,10 +72,10 @@ export function reduceOutputs(newDatum, data, options, outputs, channels, newCha
73
72
  if (typeof channels[k] === 'string') {
74
73
  // the named reducer is applied to a column name, so we can use a combination
75
74
  // of both as axis labels, e.g. MEAN(weight)
76
- newChannels[ORIGINAL_NAME_KEYS[k]] = `${reducerName} ( ${channels[k]} )`;
75
+ newChannels[`__${k}_origField`] = `${reducerName} ( ${channels[k]} )`;
77
76
  }
78
77
  else {
79
- newChannels[ORIGINAL_NAME_KEYS[k]] = reducerName;
78
+ newChannels[`__${k}_origField`] = reducerName;
80
79
  }
81
80
  }
82
81
  }
@@ -1,6 +1,6 @@
1
1
  import { extent, ascending } from 'd3-array';
2
2
  import { isColorOrNull, isDate, isDateOrNull, isNumberOrNull, isNumberOrNullOrNaN, isStringOrNull } from './typeChecks.js';
3
- import { CHANNEL_SCALE, ORIGINAL_NAME_KEYS, VALID_SCALE_TYPES } from '../constants.js';
3
+ import { CHANNEL_SCALE, VALID_SCALE_TYPES } from '../constants.js';
4
4
  import { isSymbolOrNull } from './typeChecks.js';
5
5
  import { resolveProp, toChannelOption } from './resolve.js';
6
6
  import isDataRecord from './isDataRecord.js';
@@ -126,9 +126,9 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
126
126
  }
127
127
  // special handling of marks using the stackX/stackY transform
128
128
  if ((name === 'x' || name === 'y') &&
129
- mark.options[ORIGINAL_NAME_KEYS[name]] &&
130
- !mark.options[ORIGINAL_NAME_KEYS[name]].startsWith('__')) {
131
- propNames.add(mark.options[ORIGINAL_NAME_KEYS[name]]);
129
+ mark.options[`__${name}_origField`] &&
130
+ !mark.options[`__${name}_origField`].startsWith('__')) {
131
+ propNames.add(mark.options[`__${name}_origField`]);
132
132
  }
133
133
  }
134
134
  else {
@@ -114,7 +114,6 @@
114
114
  {data}
115
115
  channels={['x1', 'x2', 'y1', 'y2', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
116
116
  required={['x1', 'y1']}
117
- {...markProps}
118
117
  {...options}>
119
118
  {#snippet children({ mark, usedScales, scaledData })}
120
119
  {@const grouped = groupAndSort(scaledData)}
@@ -135,7 +134,7 @@
135
134
  usedScales
136
135
  )}
137
136
  <path
138
- class={['area', className, styleClass]}
137
+ class={['svelteplot-area', className, styleClass]}
139
138
  clip-path={options.clipPath}
140
139
  d={areaPath(areaData)}
141
140
  {@attach addEventHandlers({
@@ -81,7 +81,9 @@ Helper component for rendering rectangular marks in SVG
81
81
  useInsetAsFallbackVertically ? inset : 0
82
82
  ) as number)
83
83
  );
84
- const borderRadius = $derived((options.borderRadius ?? 0) as BorderRadius);
84
+ const borderRadius = $derived(
85
+ resolveProp(options.borderRadius, datum?.datum, 0) as BorderRadius
86
+ );
85
87
  const hasBorderRadius = $derived(
86
88
  (typeof borderRadius === 'number' && borderRadius > 0) ||
87
89
  (typeof borderRadius === 'object' &&
@@ -4,15 +4,6 @@ import { bin as d3Bin, extent, thresholdFreedmanDiaconis, thresholdScott, thresh
4
4
  import { reduceOutputs } from '../helpers/reduce.js';
5
5
  import { groupFacetsAndZ } from '../helpers/group.js';
6
6
  import { isDate } from '../helpers/typeChecks.js';
7
- import { ORIGINAL_NAME_KEYS } from '../constants';
8
- const CHANNELS = {
9
- x: Symbol('x'),
10
- x1: Symbol('x1'),
11
- x2: Symbol('x2'),
12
- y: Symbol('y'),
13
- y1: Symbol('y1'),
14
- y2: Symbol('y2')
15
- };
16
7
  const ThresholdGenerators = {
17
8
  auto: thresholdScott,
18
9
  scott: thresholdScott,
@@ -50,19 +41,19 @@ function binBy(byDim, { data, ...channels }, options) {
50
41
  [byDim === 'x' ? 'insetLeft' : 'insetTop']: 0.5,
51
42
  [byDim === 'x' ? 'insetRight' : 'insetBottom']: 0.5,
52
43
  ...channels,
53
- [`${byDim}`]: CHANNELS[byDim], // `__${byDim}`,
54
- [`${byDim}1`]: CHANNELS[`${byDim}1`],
55
- [`${byDim}2`]: CHANNELS[`${byDim}2`],
56
- [ORIGINAL_NAME_KEYS[byDim]]: typeof channels[byDim] === 'string' ? channels[byDim] : null
44
+ [`${byDim}`]: `__${byDim}`,
45
+ [`${byDim}1`]: `__${byDim}1`,
46
+ [`${byDim}2`]: `__${byDim}2`,
47
+ [`__${byDim}_origField`]: typeof channels[byDim] === 'string' ? channels[byDim] : null
57
48
  };
58
49
  const newData = [];
59
50
  let passedGroups = [];
60
51
  const bins = bin(data);
61
52
  (options.cumulative < 0 ? bins.toReversed() : bins).forEach((group) => {
62
53
  const itemBinProps = {
63
- [CHANNELS[`${byDim}1`]]: group.x0,
64
- [CHANNELS[`${byDim}2`]]: group.x1,
65
- [CHANNELS[`${byDim}`]]: isDate(group.x0)
54
+ [`__${byDim}1`]: group.x0,
55
+ [`__${byDim}2`]: group.x1,
56
+ [`__${byDim}`]: isDate(group.x0)
66
57
  ? new Date(Math.round((group.x0.getTime() + group.x1.getTime()) * 0.5))
67
58
  : (group.x0 + group.x1) * 0.5
68
59
  };
@@ -110,12 +101,11 @@ export function bin({ data, ...channels }, options = { thresholds: 'auto', cumul
110
101
  // channels.x is the input
111
102
  binX.value((d) => resolveChannel('x', d, channels));
112
103
  binY.value((d) => resolveChannel('y', d, channels));
113
- let yThresholds = [];
114
104
  if (interval) {
115
105
  const [xlo, xhi] = extent(data.map((d) => resolveChannel('x', d, channels)));
116
106
  const [ylo, yhi] = extent(data.map((d) => resolveChannel('y', d, channels)));
117
107
  binX.thresholds(maybeInterval(interval).range(xlo, xhi));
118
- binY.thresholds((yThresholds = maybeInterval(interval).range(ylo, yhi)));
108
+ binY.thresholds(maybeInterval(interval).range(ylo, yhi));
119
109
  }
120
110
  else if (thresholds) {
121
111
  // when binning in x and y, we need to ensure we are using consistent thresholds
@@ -124,7 +114,7 @@ export function bin({ data, ...channels }, options = { thresholds: 'auto', cumul
124
114
  : thresholds;
125
115
  binX.thresholds(t);
126
116
  binY.thresholds(t);
127
- yThresholds = binY(data)
117
+ const yThresholds = binY(data)
128
118
  .slice(1)
129
119
  .map((g) => g.x0);
130
120
  binY.thresholds(yThresholds);
@@ -134,14 +124,14 @@ export function bin({ data, ...channels }, options = { thresholds: 'auto', cumul
134
124
  let newChannels = {
135
125
  inset: 0.5,
136
126
  ...channels,
137
- x: CHANNELS.x,
138
- x1: CHANNELS.x1,
139
- x2: CHANNELS.x2,
140
- y: CHANNELS.y,
141
- y1: CHANNELS.y1,
142
- y2: CHANNELS.y2,
143
- [ORIGINAL_NAME_KEYS.x]: typeof channels.x === 'string' ? channels.x : null,
144
- [ORIGINAL_NAME_KEYS.y]: typeof channels.y === 'string' ? channels.y : null
127
+ x: '__x',
128
+ x1: '__x1',
129
+ x2: '__x2',
130
+ y: '__y',
131
+ y1: '__y1',
132
+ y2: '__y2',
133
+ __x_origField: typeof channels.x === 'string' ? channels.x : null,
134
+ __y_origField: typeof channels.y === 'string' ? channels.y : null
145
135
  };
146
136
  const groupBy = channels.z ? 'z' : channels.fill ? 'fill' : channels.stroke ? 'stroke' : true;
147
137
  const groupByPropName = groupBy !== true && typeof channels[groupBy] === 'string' ? channels[groupBy] : '__group';
@@ -151,30 +141,20 @@ export function bin({ data, ...channels }, options = { thresholds: 'auto', cumul
151
141
  const newData = [];
152
142
  binX(data).forEach((groupX) => {
153
143
  const newRecordBaseX = {
154
- [CHANNELS.x1]: groupX.x0,
155
- [CHANNELS.x2]: groupX.x1,
156
- [CHANNELS.x]: isDate(groupX.x0)
144
+ __x1: groupX.x0,
145
+ __x2: groupX.x1,
146
+ __x: isDate(groupX.x0)
157
147
  ? new Date(Math.round((groupX.x0.getTime() + groupX.x1.getTime()) * 0.5))
158
148
  : (groupX.x0 + groupX.x1) * 0.5
159
149
  };
160
- const [ylo, yhi] = extent(groupX.map((d) => resolveChannel('y', d, channels)));
161
- const tExtentLo = yThresholds.filter((d) => d < ylo).at(-1);
162
- const tExtentHi = yThresholds.filter((d) => d > yhi).at(0);
163
- binY(groupX).forEach((groupY, i) => {
164
- if (groupY.length === 0)
165
- return;
166
- // The first bin.x0 is always equal to the minimum domain value,
167
- // and the last bin.x1 is always equal to the maximum domain value,
168
- // therefore we need to align with the thresholds
169
- const y1 = groupY.x0 === ylo ? tExtentLo : groupY.x0;
170
- const y2 = groupY.x1 === yhi ? tExtentHi : groupY.x1;
150
+ binY(groupX).forEach((groupY) => {
171
151
  const newRecordBaseY = {
172
152
  ...newRecordBaseX,
173
- [CHANNELS.y1]: y1,
174
- [CHANNELS.y2]: y2,
175
- [CHANNELS.y]: isDate(y1)
176
- ? new Date(Math.round((y1.getTime() + y2.getTime()) * 0.5))
177
- : (y1 + y2) * 0.5
153
+ __y1: groupY.x0,
154
+ __y2: groupY.x1,
155
+ __y: isDate(groupY.x0)
156
+ ? new Date(Math.round((groupY.x0.getTime() + groupY.x1.getTime()) * 0.5))
157
+ : (groupY.x0 + groupY.x1) * 0.5
178
158
  };
179
159
  const newGroupChannels = groupFacetsAndZ(groupY, channels, (items, itemGroupProps) => {
180
160
  const newRecord = {
@@ -5,7 +5,7 @@ import { sum, groups as d3Groups, min, range } from 'd3-array';
5
5
  import { groupFacetsAndZ } from '../helpers/group';
6
6
  import { filter } from './filter.js';
7
7
  import { sort } from './sort.js';
8
- import { INDEX, ORIGINAL_NAME_KEYS } from '../constants.js';
8
+ import { INDEX } from '../constants.js';
9
9
  import { indexData, RAW_VALUE } from './recordize.js';
10
10
  const S = {
11
11
  x: Symbol('x'),
@@ -143,8 +143,8 @@ function stackXY(byDim, data, channels, options) {
143
143
  data: out,
144
144
  ...channels,
145
145
  [byDim]: undefined,
146
- ...(typeof channels[byDim] === 'string' && !channels[ORIGINAL_NAME_KEYS[byDim]]
147
- ? { [ORIGINAL_NAME_KEYS[byDim]]: channels[byDim] }
146
+ ...(typeof channels[byDim] === 'string' && !channels[`__${byDim}_origField`]
147
+ ? { [`__${byDim}_origField`]: channels[byDim] }
148
148
  : {}),
149
149
  ...{ [byLow]: S[byLow], [byHigh]: S[byHigh] }
150
150
  };
@@ -1,5 +1,5 @@
1
1
  import type { ConstantAccessor, RawValue } from './index.js';
2
- export type Channels<T> = Record<string | symbol, ChannelAccessor<T> | ConstantAccessor<T, string | number | boolean | symbol>>;
2
+ export type Channels<T> = Record<string, ChannelAccessor<T> | ConstantAccessor<T, string | number | boolean | symbol>>;
3
3
  export type ChannelAccessor<T = Record<string | symbol, RawValue>> = ChannelValue<T> | {
4
4
  /** the channel value */
5
5
  value: ChannelValue<T>;
@@ -1,5 +1,5 @@
1
1
  import type { ScaledChannelName, ScaledChannelType } from './channel.js';
2
- export type RawValue = number | Date | boolean | string | symbol;
2
+ export type RawValue = number | Date | boolean | string | symbol | object;
3
3
  export type DataRecord<T = Record<string | symbol, RawValue>> = T;
4
4
  export type ResolvedDataRecord<T = Record<string | symbol, RawValue>> = Partial<Record<ScaledChannelName, any>> & {
5
5
  datum: DataRecord<T>;
@@ -126,5 +126,5 @@ export type BaseRectMarkProps<T> = {
126
126
  insetTop?: ConstantAccessor<number, T>;
127
127
  insetRight?: ConstantAccessor<number, T>;
128
128
  insetBottom?: ConstantAccessor<number, T>;
129
- borderRadius?: BorderRadius;
129
+ borderRadius?: ConstantAccessor<BorderRadius, T>;
130
130
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteplot",
3
- "version": "0.5.1-pr-238.4",
3
+ "version": "0.5.1-pr-244.1",
4
4
  "license": "ISC",
5
5
  "author": {
6
6
  "name": "Gregor Aisch",
@@ -130,6 +130,6 @@
130
130
  "fast-equals": "^5.3.2",
131
131
  "interval-tree-1d": "^1.0.4",
132
132
  "merge-deep": "^3.0.3",
133
- "svelte": "5.43.0"
133
+ "svelte": "5.41.3"
134
134
  }
135
135
  }