layerchart 2.0.0-next.4 → 2.0.0-next.40

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 (179) hide show
  1. package/dist/components/AnnotationLine.svelte +15 -2
  2. package/dist/components/AnnotationPoint.svelte +29 -11
  3. package/dist/components/AnnotationRange.svelte +18 -4
  4. package/dist/components/Arc.svelte +5 -5
  5. package/dist/components/Area.svelte +10 -2
  6. package/dist/components/Axis.svelte +175 -58
  7. package/dist/components/Axis.svelte.d.ts +23 -6
  8. package/dist/components/Bar.svelte +20 -15
  9. package/dist/components/Bar.svelte.d.ts +2 -2
  10. package/dist/components/Bars.svelte +4 -4
  11. package/dist/components/Blur.svelte +7 -6
  12. package/dist/components/Blur.svelte.d.ts +2 -5
  13. package/dist/components/BrushContext.svelte +45 -45
  14. package/dist/components/Calendar.svelte +31 -10
  15. package/dist/components/Calendar.svelte.d.ts +2 -1
  16. package/dist/components/Chart.svelte +76 -27
  17. package/dist/components/Chart.svelte.d.ts +26 -8
  18. package/dist/components/ChartClipPath.svelte +1 -1
  19. package/dist/components/Circle.svelte +44 -3
  20. package/dist/components/CircleClipPath.svelte +8 -1
  21. package/dist/components/ClipPath.svelte +1 -2
  22. package/dist/components/ColorRamp.svelte +1 -1
  23. package/dist/components/ComputedStyles.svelte +9 -2
  24. package/dist/components/Connector.svelte +3 -3
  25. package/dist/components/Connector.svelte.d.ts +1 -1
  26. package/dist/components/Ellipse.svelte +228 -0
  27. package/dist/components/Ellipse.svelte.d.ts +64 -0
  28. package/dist/components/ForceSimulation.svelte +184 -50
  29. package/dist/components/ForceSimulation.svelte.d.ts +95 -21
  30. package/dist/components/Frame.svelte +1 -1
  31. package/dist/components/GeoCircle.svelte +1 -1
  32. package/dist/components/GeoEdgeFade.svelte +1 -1
  33. package/dist/components/GeoPath.svelte +30 -8
  34. package/dist/components/GeoPoint.svelte +4 -5
  35. package/dist/components/GeoSpline.svelte +5 -5
  36. package/dist/components/GeoSpline.svelte.d.ts +1 -1
  37. package/dist/components/GeoTile.svelte +1 -1
  38. package/dist/components/Graticule.svelte +5 -5
  39. package/dist/components/Grid.svelte +60 -63
  40. package/dist/components/Group.svelte +13 -8
  41. package/dist/components/Group.svelte.d.ts +10 -3
  42. package/dist/components/Highlight.svelte +55 -28
  43. package/dist/components/Highlight.svelte.d.ts +4 -0
  44. package/dist/components/Hull.svelte +12 -5
  45. package/dist/components/Labels.svelte +24 -13
  46. package/dist/components/Labels.svelte.d.ts +12 -5
  47. package/dist/components/Legend.svelte +143 -70
  48. package/dist/components/Legend.svelte.d.ts +12 -8
  49. package/dist/components/Line.svelte +40 -3
  50. package/dist/components/LinearGradient.svelte +35 -4
  51. package/dist/components/Link.svelte +1 -1
  52. package/dist/components/Marker.svelte +37 -26
  53. package/dist/components/MonthPath.svelte +26 -12
  54. package/dist/components/MonthPath.svelte.d.ts +4 -3
  55. package/dist/components/MotionPath.svelte +1 -1
  56. package/dist/components/Pack.svelte.d.ts +10 -3
  57. package/dist/components/Partition.svelte.d.ts +10 -3
  58. package/dist/components/Pattern.svelte +5 -5
  59. package/dist/components/Pie.svelte +1 -2
  60. package/dist/components/Points.svelte +11 -72
  61. package/dist/components/Points.svelte.d.ts +1 -8
  62. package/dist/components/Polygon.svelte +309 -0
  63. package/dist/components/Polygon.svelte.d.ts +115 -0
  64. package/dist/components/RadialGradient.svelte +4 -6
  65. package/dist/components/Rect.svelte +55 -5
  66. package/dist/components/Rect.svelte.d.ts +2 -2
  67. package/dist/components/RectClipPath.svelte +4 -3
  68. package/dist/components/RectClipPath.svelte.d.ts +2 -2
  69. package/dist/components/Rule.svelte +167 -77
  70. package/dist/components/Rule.svelte.d.ts +7 -2
  71. package/dist/components/Spline.svelte +59 -28
  72. package/dist/components/Spline.svelte.d.ts +12 -4
  73. package/dist/components/Text.svelte +121 -73
  74. package/dist/components/Text.svelte.d.ts +6 -0
  75. package/dist/components/TileImage.svelte +19 -4
  76. package/dist/components/TransformContext.svelte +9 -3
  77. package/dist/components/TransformControls.svelte +89 -38
  78. package/dist/components/Tree.svelte.d.ts +10 -3
  79. package/dist/components/Treemap.svelte +63 -26
  80. package/dist/components/Treemap.svelte.d.ts +21 -14
  81. package/dist/components/Voronoi.svelte +12 -13
  82. package/dist/components/charts/ArcChart.svelte +43 -71
  83. package/dist/components/charts/ArcChart.svelte.d.ts +10 -3
  84. package/dist/components/charts/AreaChart.svelte +29 -59
  85. package/dist/components/charts/AreaChart.svelte.d.ts +10 -3
  86. package/dist/components/charts/BarChart.svelte +79 -71
  87. package/dist/components/charts/BarChart.svelte.d.ts +10 -3
  88. package/dist/components/charts/DefaultTooltip.svelte +3 -3
  89. package/dist/components/charts/DefaultTooltip.svelte.d.ts +1 -1
  90. package/dist/components/charts/LineChart.svelte +69 -75
  91. package/dist/components/charts/LineChart.svelte.d.ts +21 -8
  92. package/dist/components/charts/PieChart.svelte +44 -71
  93. package/dist/components/charts/PieChart.svelte.d.ts +10 -3
  94. package/dist/components/charts/ScatterChart.svelte +10 -39
  95. package/dist/components/charts/ScatterChart.svelte.d.ts +10 -3
  96. package/dist/components/charts/utils.svelte.d.ts +1 -19
  97. package/dist/components/charts/utils.svelte.js +7 -35
  98. package/dist/components/index.d.ts +4 -0
  99. package/dist/components/index.js +5 -1
  100. package/dist/components/layout/Canvas.svelte +96 -69
  101. package/dist/components/layout/Canvas.svelte.d.ts +6 -0
  102. package/dist/components/layout/Html.svelte +15 -9
  103. package/dist/components/layout/Layer.svelte +6 -4
  104. package/dist/components/layout/Layer.svelte.d.ts +6 -4
  105. package/dist/components/layout/Svg.svelte +19 -11
  106. package/dist/components/layout/WebGL.svelte +26 -6
  107. package/dist/components/layout/WebGL.svelte.d.ts +5 -2
  108. package/dist/components/tooltip/Tooltip.svelte +65 -27
  109. package/dist/components/tooltip/Tooltip.svelte.d.ts +10 -3
  110. package/dist/components/tooltip/TooltipContext.svelte +167 -54
  111. package/dist/components/tooltip/TooltipContext.svelte.d.ts +19 -5
  112. package/dist/components/tooltip/TooltipHeader.svelte +32 -18
  113. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +3 -3
  114. package/dist/components/tooltip/TooltipItem.svelte +46 -37
  115. package/dist/components/tooltip/TooltipItem.svelte.d.ts +3 -3
  116. package/dist/components/tooltip/TooltipList.svelte +12 -10
  117. package/dist/components/tooltip/TooltipSeparator.svelte +18 -10
  118. package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
  119. package/dist/docs/Blockquote.svelte +6 -4
  120. package/dist/docs/Blockquote.svelte.d.ts +4 -19
  121. package/dist/docs/Code.svelte +70 -28
  122. package/dist/docs/Code.svelte.d.ts +9 -24
  123. package/dist/docs/Header1.svelte +4 -2
  124. package/dist/docs/Header1.svelte.d.ts +4 -28
  125. package/dist/docs/Json.svelte +11 -3
  126. package/dist/docs/Json.svelte.d.ts +9 -21
  127. package/dist/docs/Layout.svelte +10 -7
  128. package/dist/docs/Layout.svelte.d.ts +4 -19
  129. package/dist/docs/Link.svelte +7 -3
  130. package/dist/docs/Link.svelte.d.ts +4 -38
  131. package/dist/docs/Preview.svelte +22 -23
  132. package/dist/docs/Preview.svelte.d.ts +5 -6
  133. package/dist/docs/TilesetField.svelte +20 -19
  134. package/dist/docs/TilesetField.svelte.d.ts +5 -22
  135. package/dist/docs/ViewSourceButton.svelte +10 -7
  136. package/dist/docs/ViewSourceButton.svelte.d.ts +7 -21
  137. package/dist/states/series.svelte.d.ts +30 -0
  138. package/dist/states/series.svelte.js +54 -0
  139. package/dist/styles/daisyui-5.css +6 -0
  140. package/dist/styles/shadcn-svelte.css +11 -0
  141. package/dist/styles/skeleton-3.css +15 -0
  142. package/dist/utils/arcText.svelte.js +4 -4
  143. package/dist/utils/array.d.ts +11 -0
  144. package/dist/utils/array.js +23 -0
  145. package/dist/utils/array.test.d.ts +1 -0
  146. package/dist/utils/array.test.js +200 -0
  147. package/dist/utils/attributes.d.ts +3 -13
  148. package/dist/utils/attributes.js +4 -18
  149. package/dist/utils/canvas.d.ts +77 -0
  150. package/dist/utils/canvas.js +105 -41
  151. package/dist/utils/common.d.ts +9 -0
  152. package/dist/utils/common.js +18 -1
  153. package/dist/utils/common.test.js +26 -1
  154. package/dist/utils/genData.d.ts +22 -8
  155. package/dist/utils/genData.js +34 -14
  156. package/dist/utils/graph/dagre.d.ts +4 -4
  157. package/dist/utils/graph/dagre.js +5 -7
  158. package/dist/utils/index.d.ts +1 -0
  159. package/dist/utils/index.js +1 -0
  160. package/dist/utils/math.d.ts +17 -0
  161. package/dist/utils/math.js +17 -0
  162. package/dist/utils/path.d.ts +10 -0
  163. package/dist/utils/path.js +30 -0
  164. package/dist/utils/rect.svelte.d.ts +2 -2
  165. package/dist/utils/rect.svelte.js +73 -1
  166. package/dist/utils/scales.svelte.d.ts +9 -3
  167. package/dist/utils/scales.svelte.js +47 -4
  168. package/dist/utils/shape.d.ts +43 -0
  169. package/dist/utils/shape.js +59 -0
  170. package/dist/utils/stack.js +1 -1
  171. package/dist/utils/string.d.ts +49 -0
  172. package/dist/utils/string.js +4 -2
  173. package/dist/utils/ticks.d.ts +15 -4
  174. package/dist/utils/ticks.js +140 -159
  175. package/dist/utils/ticks.test.js +16 -26
  176. package/dist/utils/treemap.d.ts +1 -1
  177. package/dist/utils/types.d.ts +15 -2
  178. package/package.json +35 -35
  179. package/dist/utils/object.js +0 -2
@@ -0,0 +1,49 @@
1
+ export declare const getStringWidth: any;
2
+ export type RasterizeTextOptions = {
3
+ fontSize?: string;
4
+ fontWeight?: number;
5
+ fontFamily?: string;
6
+ textAlign?: CanvasTextAlign;
7
+ textBaseline?: CanvasTextBaseline;
8
+ spacing?: number;
9
+ width?: number;
10
+ height?: number;
11
+ x?: number;
12
+ y?: number;
13
+ };
14
+ export declare function rasterizeText(text: string, options?: RasterizeTextOptions): number[][];
15
+ export declare function toTitleCase(str: string): string;
16
+ export type TruncateTextOptions = {
17
+ /**
18
+ * The maximum pixel width (optional if maxChars is provided).
19
+ */
20
+ maxWidth?: number;
21
+ /**
22
+ * CSS style for width calculation
23
+ */
24
+ style?: CSSStyleDeclaration;
25
+ /**
26
+ * The maximum character count
27
+ */
28
+ maxChars?: number;
29
+ /**
30
+ * Where to place the ellipsis: 'start', 'middle', or 'end'
31
+ *
32
+ * @default 'end'
33
+ */
34
+ position?: 'start' | 'middle' | 'end';
35
+ /**
36
+ * The character(s) to use as the ellipsis
37
+ *
38
+ * @default '…'
39
+ */
40
+ ellipsis?: string;
41
+ };
42
+ /**
43
+ * Truncates a string to fit within a specified pixel width or character count.
44
+ * If the string's width exceeds the maxWidth, it will be truncated. If the character
45
+ * count exceeds maxChars, it will also be truncated.
46
+ *
47
+ * The ellipsis can be placed at the start, middle, or end of the string.
48
+ */
49
+ export declare function truncateText(text: string, { position, ellipsis, maxWidth, style, maxChars }: TruncateTextOptions): string;
@@ -1,4 +1,4 @@
1
- import { memoize } from 'lodash-es';
1
+ import memoize from 'memoize';
2
2
  const MEASUREMENT_ELEMENT_ID = '__text_measurement_id';
3
3
  function _getStringWidth(str, style) {
4
4
  try {
@@ -24,7 +24,9 @@ function _getStringWidth(str, style) {
24
24
  return null;
25
25
  }
26
26
  }
27
- export const getStringWidth = memoize(_getStringWidth, (str, style) => `${str}_${JSON.stringify(style)}`);
27
+ export const getStringWidth = memoize(_getStringWidth, {
28
+ cacheKey: ([str, style]) => `${str}_${JSON.stringify(style)}`,
29
+ });
28
30
  export function rasterizeText(text, options = {}) {
29
31
  const fontSize = options.fontSize ?? '200px';
30
32
  const fontWeight = options.fontWeight ?? 600;
@@ -1,9 +1,20 @@
1
1
  import { type TimeInterval } from 'd3-time';
2
+ import { Duration, type FormatType, type FormatConfig } from '@layerstack/utils';
2
3
  import { type AnyScale } from './scales.svelte.js';
3
- export declare function getMajorTicks(start: Date, end: Date): TimeInterval | null;
4
- export declare function formatMajorTick(date: Date, rangeStart: Date, rangeEnd: Date): string;
5
- export declare function getMinorTicks(start: Date, end: Date): TimeInterval | null;
4
+ import type { AxisProps } from '../components/Axis.svelte';
5
+ export declare function getDurationFormat(duration: Duration, options?: {
6
+ multiline?: boolean;
7
+ placement?: AxisProps['placement'];
8
+ }): (date: Date, i: number) => string;
6
9
  export type TicksConfig = number | any[] | ((scale: AnyScale) => any[] | undefined) | {
7
10
  interval: TimeInterval | null;
8
11
  } | null;
9
- export declare function resolveTickVals(scale: AnyScale, ticks?: TicksConfig, placement?: 'radius' | 'top' | 'bottom' | 'left' | 'right' | 'angle'): any[];
12
+ export declare function autoTickVals(scale: AnyScale, ticks?: TicksConfig, count?: number): any[];
13
+ export declare function autoTickFormat(options: {
14
+ scale: AnyScale;
15
+ ticks?: TicksConfig;
16
+ count?: number;
17
+ formatType?: FormatType | FormatConfig;
18
+ multiline?: boolean;
19
+ placement?: AxisProps['placement'];
20
+ }): (date: Date, i: number) => string;
@@ -1,183 +1,164 @@
1
- import { timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond, } from 'd3-time';
2
- import { format } from 'date-fns';
3
- import { formatDate, PeriodType, getDuration, fail } from '@layerstack/utils';
4
- import { isScaleBand } from './scales.svelte.js';
5
- // TODO: Use PeriodType along with Duration to format (and possibly select intervals)
6
- const majorTicks = [
7
- {
8
- predicate: (duration) => duration == null, // Unknown
9
- interval: timeYear.every(1), // Better than rendering a lot of items
10
- format: (date) => date.toString(),
11
- },
12
- {
13
- predicate: (duration) => duration.years > 1,
14
- interval: timeYear.every(1),
15
- format: (date) => formatDate(date, PeriodType.CalendarYear, { variant: 'short' }),
16
- },
17
- {
18
- predicate: (duration) => duration.years,
19
- interval: timeMonth.every(1),
20
- format: (date) => formatDate(date, PeriodType.Month, { variant: 'short' }),
21
- },
22
- {
23
- predicate: (duration) => duration.days > 30,
24
- interval: timeMonth.every(1),
25
- format: (date) => formatDate(date, PeriodType.Month, { variant: 'short' }),
26
- },
27
- {
28
- predicate: (duration) => duration.days,
29
- interval: timeDay.every(1),
30
- format: (date) => formatDate(date, PeriodType.Day, { variant: 'short' }),
31
- },
32
- {
33
- predicate: (duration) => duration.hours,
34
- interval: timeHour.every(1),
35
- format: (date) => format(date, 'h:mm a'),
36
- },
37
- {
38
- predicate: (duration) => duration.minutes > 10,
39
- interval: timeMinute.every(10),
40
- format: (date) => format(date, 'h:mm a'),
41
- },
42
- {
43
- predicate: (duration) => duration.minutes,
44
- interval: timeMinute.every(1),
45
- format: (date) => format(date, 'h:mm a'),
46
- },
47
- {
48
- predicate: (duration) => duration.seconds > 10,
49
- interval: timeSecond.every(10),
50
- format: (date) => format(date, 'h:mm:ss'),
51
- },
52
- {
53
- predicate: (duration) => duration.seconds,
54
- interval: timeSecond.every(1),
55
- format: (date) => format(date, 'h:mm:ss'),
56
- },
57
- {
58
- predicate: (duration) => true, // 0 or more milliseconds
59
- interval: timeMillisecond.every(100),
60
- format: (date) => format(date, 'h:mm:ss.SSS'),
61
- },
62
- ];
63
- const minorTicks = [
64
- {
65
- predicate: (duration) => duration == null, // Unknown
66
- interval: timeYear.every(1), // Better than rendering a lot of items
67
- format: (date) => date.toString(),
68
- },
69
- {
70
- predicate: (duration) => duration.years,
71
- interval: timeMonth.every(1),
72
- format: (date) => formatDate(date, PeriodType.Month, { variant: 'short' }),
73
- },
74
- {
75
- predicate: (duration) => duration.days > 90,
76
- interval: timeMonth.every(1),
77
- format: (date) => formatDate(date, PeriodType.Month, { variant: 'short' }),
78
- },
79
- {
80
- predicate: (duration) => duration.days > 30,
81
- interval: timeWeek.every(1),
82
- format: (date) => formatDate(date, PeriodType.WeekSun, { variant: 'short' }),
83
- },
84
- {
85
- predicate: (duration) => duration.days > 7,
86
- interval: timeDay.every(1),
87
- format: (date) => formatDate(date, PeriodType.Day, { variant: 'short' }),
88
- },
89
- {
90
- predicate: (duration) => duration.days > 3,
91
- interval: timeHour.every(8),
92
- format: (date) => format(date, 'h:mm a'),
93
- },
94
- {
95
- predicate: (duration) => duration.days,
96
- interval: timeHour.every(1),
97
- format: (date) => format(date, 'h:mm a'),
98
- },
99
- {
100
- predicate: (duration) => duration.hours,
101
- interval: timeMinute.every(15),
102
- format: (date) => format(date, 'h:mm a'),
103
- },
104
- {
105
- predicate: (duration) => duration.minutes > 10,
106
- interval: timeMinute.every(10),
107
- format: (date) => format(date, 'h:mm a'),
108
- },
109
- {
110
- predicate: (duration) => duration.minutes > 2,
111
- interval: timeMinute.every(1),
112
- format: (date) => format(date, 'h:mm a'),
113
- },
114
- {
115
- predicate: (duration) => duration.minutes,
116
- interval: timeSecond.every(10),
117
- format: (date) => format(date, 'h:mm:ss'),
118
- },
119
- {
120
- predicate: (duration) => duration.seconds,
121
- interval: timeSecond.every(1),
122
- format: (date) => format(date, 'h:mm:ss'),
123
- },
124
- {
125
- predicate: (duration) => true, // 0 or more milliseconds
126
- interval: timeMillisecond.every(10),
127
- format: (date) => format(date, 'h:mm:ss.SSS'),
128
- },
129
- ];
130
- export function getMajorTicks(start, end) {
131
- const duration = getDuration(start, end);
132
- for (var t of majorTicks) {
133
- if (t.predicate(duration)) {
134
- return t.interval;
1
+ import { timeYear, timeMonth, timeDay, timeTicks } from 'd3-time';
2
+ import { format, Duration, isLiteralObject, DateToken, } from '@layerstack/utils';
3
+ import { isScaleBand, isScaleTime } from './scales.svelte.js';
4
+ export function getDurationFormat(duration, options = {
5
+ multiline: false,
6
+ }) {
7
+ const { multiline = false, placement = 'bottom' } = options;
8
+ return function (date, i) {
9
+ let result = '';
10
+ if (+duration >= +new Duration({ duration: { years: 1 } })) {
11
+ // Year
12
+ result = format(date, 'year');
135
13
  }
136
- }
137
- fail(`Unable to locate major ticks for duration: ${duration}`);
138
- }
139
- export function formatMajorTick(date, rangeStart, rangeEnd) {
140
- const duration = getDuration(rangeStart, rangeEnd);
141
- for (var t of majorTicks) {
142
- if (t.predicate(duration)) {
143
- return t.format(date);
14
+ else if (+duration >= +new Duration({ duration: { days: 28 } })) {
15
+ // Month
16
+ const isFirst = i === 0 || +timeYear.floor(date) === +date;
17
+ if (multiline) {
18
+ result = [format(date, 'month', { variant: 'short' }), isFirst && format(date, 'year')];
19
+ }
20
+ else {
21
+ result =
22
+ format(date, 'month', { variant: 'short' }) +
23
+ (isFirst ? ` '${format(date, 'year', { variant: 'short' })}` : '');
24
+ }
144
25
  }
145
- }
146
- fail(`Unable to format major ticks for duration: ${duration}`);
147
- }
148
- export function getMinorTicks(start, end) {
149
- const duration = getDuration(start, end);
150
- for (var t of minorTicks) {
151
- if (t.predicate(duration)) {
152
- return t.interval;
26
+ else if (+duration >= +new Duration({ duration: { days: 1 } })) {
27
+ // Day
28
+ const isFirst = i === 0 || date.getDate() <= duration.days;
29
+ if (multiline) {
30
+ result = [
31
+ format(date, 'custom', { custom: DateToken.DayOfMonth_numeric }),
32
+ isFirst && format(date, 'month', { variant: 'short' }),
33
+ ];
34
+ }
35
+ else {
36
+ result = format(date, 'day', { variant: 'short' });
37
+ }
153
38
  }
154
- }
155
- fail(`Unable to locate minor ticks for duration: ${duration}`);
39
+ else if (+duration >= +new Duration({ duration: { hours: 1 } })) {
40
+ // Hours
41
+ const isFirst = i === 0 || +timeDay.floor(date) === +date;
42
+ if (multiline) {
43
+ result = [
44
+ format(date, 'custom', { custom: DateToken.Hour_numeric }),
45
+ isFirst && format(date, 'day', { variant: 'short' }),
46
+ ];
47
+ }
48
+ else {
49
+ result = isFirst
50
+ ? format(date, 'day', { variant: 'short' })
51
+ : format(date, 'custom', { custom: DateToken.Hour_numeric });
52
+ }
53
+ }
54
+ else if (+duration >= +new Duration({ duration: { minutes: 1 } })) {
55
+ // Minutes
56
+ const isFirst = i === 0 || +timeDay.floor(date) === +date;
57
+ if (multiline) {
58
+ result = [
59
+ format(date, 'time', { variant: 'short' }),
60
+ isFirst && format(date, 'day', { variant: 'short' }),
61
+ ];
62
+ }
63
+ else {
64
+ result = format(date, 'time', { variant: 'short' });
65
+ }
66
+ }
67
+ else if (+duration >= +new Duration({ duration: { seconds: 1 } })) {
68
+ // Seconds
69
+ const isFirst = i === 0 || +timeDay.floor(date) === +date;
70
+ result = [
71
+ format(date, 'time'),
72
+ multiline && isFirst && format(date, 'day', { variant: 'short' }),
73
+ ];
74
+ }
75
+ else if (+duration >= +new Duration({ duration: { milliseconds: 1 } })) {
76
+ // Milliseconds
77
+ const isFirst = i === 0 || +timeDay.floor(date) === +date;
78
+ result = [
79
+ format(date, 'custom', {
80
+ custom: [
81
+ DateToken.Hour_2Digit,
82
+ DateToken.Minute_2Digit,
83
+ DateToken.Second_2Digit,
84
+ DateToken.MiliSecond_3,
85
+ DateToken.Hour_woAMPM,
86
+ ],
87
+ }),
88
+ multiline && isFirst && format(date, 'day', { variant: 'short' }),
89
+ ];
90
+ }
91
+ else {
92
+ result = date.toString();
93
+ }
94
+ if (Array.isArray(result)) {
95
+ switch (placement) {
96
+ case 'top':
97
+ return result.filter(Boolean).reverse().join('\n');
98
+ case 'bottom':
99
+ return result.filter(Boolean).join('\n');
100
+ case 'left':
101
+ return result.filter(Boolean).reverse().join(' ');
102
+ case 'right':
103
+ return result.filter(Boolean).join(' ');
104
+ default:
105
+ return result.filter(Boolean).join('\n');
106
+ }
107
+ }
108
+ else {
109
+ return result;
110
+ }
111
+ };
156
112
  }
157
- export function resolveTickVals(scale, ticks, placement) {
113
+ export function autoTickVals(scale, ticks, count) {
114
+ // Explicit ticks
158
115
  if (Array.isArray(ticks))
159
116
  return ticks;
117
+ // Function
160
118
  if (typeof ticks === 'function')
161
119
  return ticks(scale) ?? [];
120
+ // Interval
162
121
  if (isLiteralObject(ticks) && 'interval' in ticks) {
163
122
  if (ticks.interval === null || !('ticks' in scale) || typeof scale.ticks !== 'function') {
164
123
  return []; // Explicitly return empty array for null interval or invalid scale
165
124
  }
166
125
  return scale.ticks(ticks.interval);
167
126
  }
127
+ // Band (use domain)
168
128
  if (isScaleBand(scale)) {
169
129
  return ticks && typeof ticks === 'number'
170
130
  ? scale.domain().filter((_, i) => i % ticks === 0)
171
131
  : scale.domain();
172
132
  }
133
+ // Ticks from scale
173
134
  if (scale.ticks && typeof scale.ticks === 'function') {
174
- if (placement) {
175
- return scale.ticks(ticks ?? (placement === 'left' || placement === 'right' ? 4 : undefined));
176
- }
177
- return scale.ticks(ticks);
135
+ return scale.ticks(count ?? (typeof ticks === 'number' ? ticks : undefined));
178
136
  }
179
137
  return [];
180
138
  }
181
- function isLiteralObject(val) {
182
- return val !== null && typeof val === 'object' && !Array.isArray(val);
139
+ export function autoTickFormat(options) {
140
+ const { scale, ticks, count, formatType, multiline, placement } = options;
141
+ // Explicit format
142
+ if (formatType) {
143
+ // @ts-expect-error - improve types
144
+ return (tick) => format(tick, formatType);
145
+ }
146
+ // Time scale
147
+ if (isScaleTime(scale) && count) {
148
+ if (isLiteralObject(ticks) && 'interval' in ticks && ticks.interval != null) {
149
+ const start = ticks.interval.floor(new Date());
150
+ const end = ticks.interval.ceil(new Date());
151
+ return getDurationFormat(new Duration({ start, end }), { multiline, placement });
152
+ }
153
+ else {
154
+ // Compare first 2 ticks to determine duration between ticks for formatting
155
+ const [start, end] = timeTicks(scale.domain()[0], scale.domain()[1], count);
156
+ return getDurationFormat(new Duration({ start, end }), { multiline, placement });
157
+ }
158
+ }
159
+ // Format from scale
160
+ if (scale.tickFormat) {
161
+ return scale.tickFormat(count);
162
+ }
163
+ return (tick) => `${tick}`;
183
164
  }
@@ -1,67 +1,57 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import { resolveTickVals } from './ticks.js';
2
+ import { autoTickVals } from './ticks.js';
3
3
  // Mock helpers
4
4
  const mockTicksFn = vi.fn();
5
5
  const mockDomain = vi.fn(() => ['a', 'b', 'c', 'd', 'e']);
6
- describe('resolveTickVals', () => {
6
+ describe('autoTickVals', () => {
7
7
  it('returns array ticks directly', () => {
8
8
  const ticks = [1, 2, 3];
9
9
  const scale = { ticks: mockTicksFn };
10
- expect(resolveTickVals(scale, ticks)).toEqual([1, 2, 3]);
10
+ expect(autoTickVals(scale, ticks)).toEqual([1, 2, 3]);
11
11
  });
12
12
  it('calls function ticks with scale', () => {
13
13
  const fnTicks = vi.fn(() => [4, 5, 6]);
14
14
  const scale = { ticks: mockTicksFn };
15
- expect(resolveTickVals(scale, fnTicks)).toEqual([4, 5, 6]);
15
+ expect(autoTickVals(scale, fnTicks)).toEqual([4, 5, 6]);
16
16
  expect(fnTicks).toHaveBeenCalledWith(scale);
17
17
  });
18
18
  it('uses interval when provided', () => {
19
19
  const interval = { every: vi.fn() };
20
20
  const ticksConfig = { interval };
21
21
  const scale = { ticks: vi.fn(() => [7, 8, 9]) };
22
- expect(resolveTickVals(scale, ticksConfig)).toEqual([7, 8, 9]);
22
+ expect(autoTickVals(scale, ticksConfig)).toEqual([7, 8, 9]);
23
23
  expect(scale.ticks).toHaveBeenCalledWith(interval);
24
24
  });
25
25
  it('returns empty array if interval is null', () => {
26
26
  const ticksConfig = { interval: null };
27
27
  const scale = { ticks: mockTicksFn };
28
- expect(resolveTickVals(scale, ticksConfig)).toEqual([]);
28
+ expect(autoTickVals(scale, ticksConfig)).toEqual([]);
29
29
  });
30
30
  it('filters band scale domain with number ticks', () => {
31
31
  const scale = { domain: mockDomain, bandwidth: vi.fn() };
32
- expect(resolveTickVals(scale, 2)).toEqual(['a', 'c', 'e']);
32
+ expect(autoTickVals(scale, 2)).toEqual(['a', 'c', 'e']);
33
33
  });
34
34
  it('returns full domain for band scale without ticks', () => {
35
35
  const scale = { domain: mockDomain, bandwidth: vi.fn() };
36
- expect(resolveTickVals(scale)).toEqual(['a', 'b', 'c', 'd', 'e']);
37
- });
38
- it('uses default 4 ticks for left placement', () => {
39
- const scale = { ticks: vi.fn(() => [1, 2, 3, 4]) };
40
- expect(resolveTickVals(scale, undefined, 'left')).toEqual([1, 2, 3, 4]);
41
- expect(scale.ticks).toHaveBeenCalledWith(4);
42
- });
43
- it('uses default 4 ticks for right placement', () => {
44
- const scale = { ticks: vi.fn(() => [1, 2, 3, 4]) };
45
- expect(resolveTickVals(scale, undefined, 'right')).toEqual([1, 2, 3, 4]);
46
- expect(scale.ticks).toHaveBeenCalledWith(4);
36
+ expect(autoTickVals(scale)).toEqual(['a', 'b', 'c', 'd', 'e']);
47
37
  });
48
38
  it('uses undefined for non-left/right placement', () => {
49
- const scale = { ticks: vi.fn(() => [1, 2]) };
50
- expect(resolveTickVals(scale, undefined, 'top')).toEqual([1, 2]);
39
+ const scale = { domain: mockDomain, ticks: vi.fn(() => [1, 2]) };
40
+ expect(autoTickVals(scale, undefined, undefined)).toEqual([1, 2]);
51
41
  expect(scale.ticks).toHaveBeenCalledWith(undefined);
52
42
  });
53
43
  it('passes number ticks to scale.ticks', () => {
54
- const scale = { ticks: vi.fn(() => [10, 20]) };
55
- expect(resolveTickVals(scale, 5)).toEqual([10, 20]);
44
+ const scale = { domain: mockDomain, ticks: vi.fn(() => [10, 20]) };
45
+ expect(autoTickVals(scale, 5)).toEqual([10, 20]);
56
46
  expect(scale.ticks).toHaveBeenCalledWith(5);
57
47
  });
58
48
  it('returns empty array for scale without ticks', () => {
59
- const scale = {};
60
- expect(resolveTickVals(scale, 5)).toEqual([]);
49
+ const scale = { domain: mockDomain };
50
+ expect(autoTickVals(scale, 5)).toEqual([]);
61
51
  });
62
52
  it('handles null ticks with placement', () => {
63
- const scale = { ticks: vi.fn(() => [1, 2, 3]) };
64
- expect(resolveTickVals(scale, null, 'bottom')).toEqual([1, 2, 3]);
53
+ const scale = { domain: mockDomain, ticks: vi.fn(() => [1, 2, 3]) };
54
+ expect(autoTickVals(scale, null, undefined)).toEqual([1, 2, 3]);
65
55
  expect(scale.ticks).toHaveBeenCalledWith(undefined);
66
56
  });
67
57
  });
@@ -9,5 +9,5 @@ export declare function aspectTile(tile: TileFunc, width: number, height: number
9
9
  /**
10
10
  * Show if the node (a) is a child of the selected (b), or any parent above selected
11
11
  */
12
- export declare function isNodeVisible(a: HierarchyNode<any>, b: HierarchyNode<any> | null): boolean;
12
+ export declare function isNodeVisible(a: HierarchyNode<any>, b: HierarchyNode<any> | null | undefined): boolean;
13
13
  export {};
@@ -1,7 +1,8 @@
1
+ import type { MouseEventHandler, PointerEventHandler } from 'svelte/elements';
2
+ import type { TransitionConfig } from 'svelte/transition';
1
3
  import type { HierarchyNode } from 'd3-hierarchy';
2
- import type { AnyScale } from './scales.svelte.js';
3
4
  import type { SankeyGraph } from 'd3-sankey';
4
- import type { TransitionConfig } from 'svelte/transition';
5
+ import type { AnyScale } from './scales.svelte.js';
5
6
  /**
6
7
  * Useful to workaround Svelte 3/4 markup type issues
7
8
  * TODO: Remove usage after migrating to Svelte 5
@@ -79,6 +80,18 @@ export type CommonStyleProps = {
79
80
  */
80
81
  opacity?: number;
81
82
  };
83
+ /**
84
+ * Events for primatives which support `SVGRectElement` and `HTMLDivElement` elements based on render context
85
+ */
86
+ export type CommonEvents = {
87
+ onclick?: MouseEventHandler<Element> | null;
88
+ ondblclick?: MouseEventHandler<Element> | null;
89
+ onpointerenter?: PointerEventHandler<Element> | null;
90
+ onpointermove?: PointerEventHandler<Element> | null;
91
+ onpointerleave?: PointerEventHandler<Element> | null;
92
+ onpointerover?: PointerEventHandler<Element> | null;
93
+ onpointerout?: PointerEventHandler<Element> | null;
94
+ };
82
95
  export type OnlyObjects<T> = T extends object ? T : never;
83
96
  export type Getter<T> = () => T;
84
97
  export type GetterValues<T> = {
package/package.json CHANGED
@@ -4,19 +4,18 @@
4
4
  "author": "Sean Lynch <techniq35@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
- "version": "2.0.0-next.4",
7
+ "version": "2.0.0-next.40",
8
8
  "devDependencies": {
9
- "@changesets/cli": "^2.29.2",
10
- "@iconify-json/lucide": "^1.2.42",
11
- "@mdi/js": "^7.4.47",
9
+ "@changesets/cli": "^2.29.6",
10
+ "@iconify-json/lucide": "^1.2.62",
12
11
  "@rollup/plugin-dsv": "^3.0.5",
13
- "@sveltejs/adapter-cloudflare": "^4.9.0",
14
- "@sveltejs/kit": "^2.20.8",
15
- "@sveltejs/package": "^2.3.11",
16
- "@sveltejs/vite-plugin-svelte": "^5.0.3",
12
+ "@sveltejs/adapter-cloudflare": "^7.2.1",
13
+ "@sveltejs/kit": "^2.31.1",
14
+ "@sveltejs/package": "^2.4.1",
15
+ "@sveltejs/vite-plugin-svelte": "^6.1.2",
17
16
  "@svitejs/changesets-changelog-github-compact": "^1.2.0",
18
17
  "@tailwindcss/typography": "^0.5.16",
19
- "@tailwindcss/vite": "^4.1.5",
18
+ "@tailwindcss/vite": "^4.1.12",
20
19
  "@types/d3": "^7.4.3",
21
20
  "@types/d3-array": "^3.2.1",
22
21
  "@types/d3-color": "^3.1.3",
@@ -36,46 +35,43 @@
36
35
  "@types/d3-shape": "^3.1.7",
37
36
  "@types/d3-time": "^3.0.4",
38
37
  "@types/lodash-es": "^4.17.12",
39
- "@types/prismjs": "^1.26.5",
40
38
  "@types/shapefile": "^0.6.4",
41
39
  "@types/topojson-client": "^3.1.5",
42
40
  "@types/topojson-simplify": "^3.0.3",
43
41
  "@types/topojson-specification": "^1.0.5",
44
- "marked": "^15.0.11",
45
- "mdsvex": "0.12.3",
46
- "posthog-js": "^1.239.0",
47
- "prettier": "^3.5.3",
48
- "prettier-plugin-svelte": "^3.3.3",
49
- "prism-svelte": "^0.5.0",
50
- "prism-themes": "^1.9.0",
51
- "prismjs": "^1.30.0",
42
+ "mdsvex": "^0.12.3",
43
+ "posthog-js": "^1.260.1",
44
+ "prettier": "^3.6.2",
45
+ "prettier-plugin-svelte": "^3.4.0",
52
46
  "rehype-slug": "^6.0.0",
47
+ "rollup-plugin-visualizer": "^6.0.3",
53
48
  "shapefile": "^0.6.6",
49
+ "shiki": "^3.9.2",
54
50
  "solar-calculator": "^0.3.0",
55
- "svelte": "5.28.2",
56
- "svelte-check": "^4.1.6",
51
+ "svelte": "^5.38.2",
52
+ "svelte-check": "^4.3.1",
57
53
  "svelte-json-tree": "^2.2.0",
58
- "svelte-ux": "2.0.0-next.2",
59
- "svelte2tsx": "^0.7.36",
60
- "tailwindcss": "^4.1.5",
54
+ "svelte-ux": "2.0.0-next.17",
55
+ "svelte2tsx": "^0.7.42",
56
+ "tailwindcss": "^4.1.12",
61
57
  "topojson-client": "^3.1.0",
62
58
  "topojson-simplify": "^3.0.3",
63
59
  "tslib": "^2.8.1",
64
- "typescript": "^5.8.3",
60
+ "typescript": "^5.9.2",
65
61
  "unist-util-visit": "^5.0.0",
66
- "unplugin-icons": "^22.1.0",
62
+ "unplugin-icons": "^22.2.0",
67
63
  "us-atlas": "^3.0.1",
68
- "vite": "^6.3.4",
69
- "vitest": "^3.1.2"
64
+ "vite": "^7.1.2",
65
+ "vite-plugin-devtools-json": "^1.0.0",
66
+ "vitest": "^3.2.4"
70
67
  },
71
68
  "type": "module",
72
69
  "dependencies": {
73
- "@dagrejs/dagre": "^1.1.4",
74
- "@layerstack/svelte-actions": "1.0.1-next.0",
75
- "@layerstack/svelte-state": "0.1.0-next.1",
76
- "@layerstack/svelte-stores": "1.0.2-next.0",
77
- "@layerstack/tailwind": "2.0.0-next.2",
78
- "@layerstack/utils": "1.1.0-next.0",
70
+ "@dagrejs/dagre": "^1.1.5",
71
+ "@layerstack/svelte-actions": "1.0.1-next.14",
72
+ "@layerstack/svelte-state": "0.1.0-next.19",
73
+ "@layerstack/tailwind": "2.0.0-next.17",
74
+ "@layerstack/utils": "2.0.0-next.14",
79
75
  "d3-array": "^3.2.4",
80
76
  "d3-color": "^3.1.0",
81
77
  "d3-delaunay": "^6.0.4",
@@ -95,9 +91,9 @@
95
91
  "d3-shape": "^3.2.0",
96
92
  "d3-tile": "^1.0.0",
97
93
  "d3-time": "^3.1.0",
98
- "date-fns": "^4.1.0",
99
94
  "lodash-es": "^4.17.21",
100
- "runed": "^0.26.0"
95
+ "memoize": "^10.1.0",
96
+ "runed": "^0.31.1"
101
97
  },
102
98
  "peerDependencies": {
103
99
  "svelte": "^5.0.0"
@@ -113,6 +109,10 @@
113
109
  "types": "./dist/utils/*.d.ts",
114
110
  "svelte": "./dist/utils/*.js",
115
111
  "default": "./dist/utils/*.js"
112
+ },
113
+ "./*.css": {
114
+ "style": "./dist/styles/*.css",
115
+ "default": "./dist/styles/*.css"
116
116
  }
117
117
  },
118
118
  "files": [
@@ -1,2 +0,0 @@
1
- import { memoize } from 'lodash-es';
2
- export const memoizeObject = memoize((obj) => obj, (obj) => JSON.stringify(obj));