@carto/ps-react-ui 4.8.0 → 4.9.0

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 (75) hide show
  1. package/dist/range-l4fNHLEg.js +213 -0
  2. package/dist/range-l4fNHLEg.js.map +1 -0
  3. package/dist/resolve-theme-color-BdojIw0K.js +47 -0
  4. package/dist/resolve-theme-color-BdojIw0K.js.map +1 -0
  5. package/dist/table-CQCAnDLb.js +388 -0
  6. package/dist/table-CQCAnDLb.js.map +1 -0
  7. package/dist/types/widgets-v2/bar/types.d.ts +8 -3
  8. package/dist/types/widgets-v2/category/types.d.ts +8 -4
  9. package/dist/types/widgets-v2/formula/types.d.ts +10 -7
  10. package/dist/types/widgets-v2/histogram/types.d.ts +7 -3
  11. package/dist/types/widgets-v2/index.d.ts +1 -0
  12. package/dist/types/widgets-v2/pie/types.d.ts +10 -3
  13. package/dist/types/widgets-v2/range/range-ui.d.ts +12 -4
  14. package/dist/types/widgets-v2/range/range.d.ts +13 -8
  15. package/dist/types/widgets-v2/scatterplot/types.d.ts +7 -3
  16. package/dist/types/widgets-v2/table/style.d.ts +0 -4
  17. package/dist/types/widgets-v2/table/table-ui.d.ts +7 -1
  18. package/dist/types/widgets-v2/table/table.d.ts +1 -1
  19. package/dist/types/widgets-v2/table/types.d.ts +13 -2
  20. package/dist/types/widgets-v2/timeseries/types.d.ts +7 -3
  21. package/dist/types/widgets-v2/types.d.ts +25 -0
  22. package/dist/types/widgets-v2/utils/index.d.ts +1 -0
  23. package/dist/types/widgets-v2/utils/resolve-theme-color.d.ts +18 -0
  24. package/dist/types/widgets-v2/utils/resolve-theme-color.test.d.ts +1 -0
  25. package/dist/widgets-v2/bar.js +58 -55
  26. package/dist/widgets-v2/bar.js.map +1 -1
  27. package/dist/widgets-v2/histogram.js +65 -62
  28. package/dist/widgets-v2/histogram.js.map +1 -1
  29. package/dist/widgets-v2/pie.js +100 -94
  30. package/dist/widgets-v2/pie.js.map +1 -1
  31. package/dist/widgets-v2/range.js +1 -1
  32. package/dist/widgets-v2/scatterplot.js +107 -101
  33. package/dist/widgets-v2/scatterplot.js.map +1 -1
  34. package/dist/widgets-v2/table.js +2 -2
  35. package/dist/widgets-v2/timeseries.js +85 -79
  36. package/dist/widgets-v2/timeseries.js.map +1 -1
  37. package/dist/widgets-v2/utils.js +4 -3
  38. package/dist/widgets-v2.js +2 -2
  39. package/dist/widgets-v2.js.map +1 -1
  40. package/package.json +3 -3
  41. package/src/widgets-v2/bar/options.test.ts +19 -2
  42. package/src/widgets-v2/bar/options.ts +9 -3
  43. package/src/widgets-v2/bar/types.ts +8 -3
  44. package/src/widgets-v2/category/types.ts +9 -4
  45. package/src/widgets-v2/formula/types.ts +11 -7
  46. package/src/widgets-v2/histogram/options.test.ts +16 -2
  47. package/src/widgets-v2/histogram/options.ts +5 -4
  48. package/src/widgets-v2/histogram/types.ts +7 -3
  49. package/src/widgets-v2/index.ts +3 -0
  50. package/src/widgets-v2/pie/options.test.ts +20 -4
  51. package/src/widgets-v2/pie/options.ts +21 -17
  52. package/src/widgets-v2/pie/types.ts +10 -3
  53. package/src/widgets-v2/range/range-ui.test.tsx +8 -2
  54. package/src/widgets-v2/range/range-ui.tsx +81 -14
  55. package/src/widgets-v2/range/range.tsx +14 -8
  56. package/src/widgets-v2/scatterplot/options.test.ts +15 -3
  57. package/src/widgets-v2/scatterplot/options.ts +15 -11
  58. package/src/widgets-v2/scatterplot/types.ts +7 -3
  59. package/src/widgets-v2/table/style.ts +2 -5
  60. package/src/widgets-v2/table/table-ui.tsx +40 -7
  61. package/src/widgets-v2/table/table.tsx +6 -1
  62. package/src/widgets-v2/table/types.ts +13 -2
  63. package/src/widgets-v2/timeseries/options.test.ts +17 -2
  64. package/src/widgets-v2/timeseries/options.ts +10 -3
  65. package/src/widgets-v2/timeseries/types.ts +7 -3
  66. package/src/widgets-v2/types.ts +25 -0
  67. package/src/widgets-v2/utils/index.ts +1 -0
  68. package/src/widgets-v2/utils/resolve-theme-color.test.ts +43 -0
  69. package/src/widgets-v2/utils/resolve-theme-color.ts +34 -0
  70. package/dist/merge-options-DCkkHZIf.js +0 -34
  71. package/dist/merge-options-DCkkHZIf.js.map +0 -1
  72. package/dist/range-DsqTjSpg.js +0 -186
  73. package/dist/range-DsqTjSpg.js.map +0 -1
  74. package/dist/table-HIpXuq4G.js +0 -390
  75. package/dist/table-HIpXuq4G.js.map +0 -1
@@ -5,12 +5,9 @@ export const styles = {
5
5
  width: '100%',
6
6
  overflowX: 'auto',
7
7
  },
8
- /**
9
- * Minimum table width so columns don't collapse to unreadable widths on
10
- * narrow widget shells. Mirrors v1.
11
- */
8
+
12
9
  table: {
13
- minWidth: 650,
10
+ minWidth: 0,
14
11
  },
15
12
  headerCell: {
16
13
  fontWeight: 600,
@@ -1,4 +1,4 @@
1
- import { useMemo } from 'react'
1
+ import { useCallback, useMemo } from 'react'
2
2
  import {
3
3
  Box,
4
4
  Checkbox,
@@ -38,6 +38,12 @@ export interface TableUIProps<T extends TableRow = TableRow> {
38
38
  pageSize: number
39
39
  pageSizeOptions?: readonly number[]
40
40
  sort?: TableSortState
41
+ /**
42
+ * Column name to use as the row identity. Drives selection lookup,
43
+ * React keys, and aria labels. Defaults to `'id'` — point it at
44
+ * another column when your rows don't carry an `id` field.
45
+ */
46
+ keyColumn?: string
41
47
  /** Selected row ids. Destination-owned. */
42
48
  selection?: readonly (string | number)[]
43
49
  selectable?: boolean
@@ -71,6 +77,7 @@ export function TableUI<T extends TableRow = TableRow>({
71
77
  pageSize,
72
78
  pageSizeOptions = DEFAULT_TABLE_PAGE_SIZE_OPTIONS,
73
79
  sort,
80
+ keyColumn = 'id',
74
81
  selection,
75
82
  selectable = false,
76
83
  onSortChange,
@@ -83,6 +90,20 @@ export function TableUI<T extends TableRow = TableRow>({
83
90
  emptyContent,
84
91
  size,
85
92
  }: TableUIProps<T>) {
93
+ if (process.env.NODE_ENV !== 'production') {
94
+ // Dev-time guard: a nullish identity collapses every row into the
95
+ // same selection-set entry, which manifests as "click one → all
96
+ // appear selected". Surface it loudly instead of silently degrading.
97
+ const missing = rows.some((r) => r[keyColumn] == null)
98
+ if (missing) {
99
+ // eslint-disable-next-line no-console
100
+ console.error(
101
+ `<TableUI>: rows are missing the identity column \`${keyColumn}\`. ` +
102
+ 'Set the `keyColumn` prop to a column present on every row, or ' +
103
+ 'add the column to the data.',
104
+ )
105
+ }
106
+ }
86
107
  const _labels = useMemo(
87
108
  () => ({ ...DEFAULT_TABLE_LABELS, ...labels }),
88
109
  [labels],
@@ -106,7 +127,18 @@ export function TableUI<T extends TableRow = TableRow>({
106
127
  () => new Set<string | number>(selection ?? []),
107
128
  [selection],
108
129
  )
109
- const pageRowIds = useMemo(() => rows.map((r) => r.id), [rows])
130
+ // Resolve each row's identity from `keyColumn`, falling back to the row's
131
+ // index when the cell is nullish. The dev-time guard above surfaces the
132
+ // misconfiguration loudly, but in production we must NOT collapse every
133
+ // nullish-keyed row into the same selection-set entry (that's the
134
+ // "click one → all selected" bug) — a per-index fallback keeps ids
135
+ // distinct and React keys stable for a given page.
136
+ const resolveRowId = useCallback(
137
+ (row: T, index: number): string | number =>
138
+ (row[keyColumn] ?? index) as string | number,
139
+ [keyColumn],
140
+ )
141
+ const pageRowIds = useMemo(() => rows.map(resolveRowId), [rows, resolveRowId])
110
142
  const allOnPageSelected =
111
143
  pageRowIds.length > 0 && pageRowIds.every((id) => selectionSet.has(id))
112
144
  const someOnPageSelected =
@@ -197,11 +229,12 @@ export function TableUI<T extends TableRow = TableRow>({
197
229
  </TableCell>
198
230
  </MuiTableRow>
199
231
  ) : (
200
- rows.map((row) => {
201
- const isSelected = selectionSet.has(row.id)
232
+ rows.map((row, index) => {
233
+ const rowId = resolveRowId(row, index)
234
+ const isSelected = selectionSet.has(rowId)
202
235
  return (
203
236
  <MuiTableRow
204
- key={row.id}
237
+ key={rowId}
205
238
  hover
206
239
  selected={isSelected}
207
240
  onClick={() => onRowClick?.(row)}
@@ -218,10 +251,10 @@ export function TableUI<T extends TableRow = TableRow>({
218
251
  checked={isSelected}
219
252
  onClick={(e) => {
220
253
  e.stopPropagation()
221
- handleSelectRow(row.id)
254
+ handleSelectRow(rowId)
222
255
  }}
223
256
  inputProps={{
224
- 'aria-label': _labels.selectRow(row.id),
257
+ 'aria-label': _labels.selectRow(rowId),
225
258
  }}
226
259
  />
227
260
  </TableCell>
@@ -17,7 +17,12 @@ import { deriveVisibleRows, resolveColumns } from './helpers'
17
17
 
18
18
  export interface TableProps<T extends TableRow = TableRow> extends Pick<
19
19
  TableUIProps<T>,
20
- 'pageSizeOptions' | 'selectable' | 'labels' | 'emptyContent' | 'size'
20
+ | 'pageSizeOptions'
21
+ | 'selectable'
22
+ | 'labels'
23
+ | 'emptyContent'
24
+ | 'size'
25
+ | 'keyColumn'
21
26
  > {
22
27
  /**
23
28
  * Column definitions. Order can be overridden by ChangeColumn via the
@@ -1,9 +1,20 @@
1
1
  import type { ReactNode } from 'react'
2
2
  import type { WidgetState } from '../stores'
3
3
 
4
- /** Single row of tabular data. Must have an `id` for selection / keying. */
4
+ /**
5
+ * Single row of tabular data.
6
+ *
7
+ * The default row-identity column is `id`. Consumers that don't have a
8
+ * literal `id` field can point `<Table>` / `<TableUI>` at a different
9
+ * column via the `keyColumn` prop; the library reads `row[keyColumn]`
10
+ * for selection lookup, React keys, and aria labels.
11
+ */
5
12
  export interface TableRow extends Record<string, unknown> {
6
- id: string | number
13
+ /**
14
+ * Default row identity. Required when no `keyColumn` is configured.
15
+ * Omit when wiring `keyColumn` to a different column.
16
+ */
17
+ id?: string | number
7
18
  }
8
19
 
9
20
  export type TableWidgetData = readonly TableRow[]
@@ -194,10 +194,10 @@ describe('createTimeseriesOptionFactory', () => {
194
194
  expect(multi.grid.bottom).toBe(56)
195
195
  })
196
196
 
197
- it('uses seriesNames for series.name when provided', () => {
197
+ it('uses series[i].name for series.name when provided', () => {
198
198
  const merge = createTimeseriesOptionFactory({
199
199
  theme,
200
- seriesNames: ['2024', '2025'],
200
+ series: [{ name: '2024' }, { name: '2025' }],
201
201
  })
202
202
  const out = merge({}, [
203
203
  [{ name: 'a', value: 1 }],
@@ -207,6 +207,21 @@ describe('createTimeseriesOptionFactory', () => {
207
207
  expect(out.series[1]?.name).toBe('2025')
208
208
  })
209
209
 
210
+ it('applies series[i].color as both root color and lineStyle.color', () => {
211
+ const merge = createTimeseriesOptionFactory({
212
+ theme,
213
+ series: [{ name: '2024', color: '#ff0000' }, { name: '2025' }],
214
+ })
215
+ const out = merge({}, [
216
+ [{ name: 'a', value: 1 }],
217
+ [{ name: 'a', value: 2 }],
218
+ ]) as { series: { color?: string; lineStyle?: { color?: string } }[] }
219
+ expect(out.series[0]?.color).toBe('#ff0000')
220
+ expect(out.series[0]?.lineStyle?.color).toBe('#ff0000')
221
+ expect(out.series[1]?.color).toBeUndefined()
222
+ expect(out.series[1]?.lineStyle?.color).toBeUndefined()
223
+ })
224
+
210
225
  it('returns empty dataset/series for empty data', () => {
211
226
  const merge = createTimeseriesOptionFactory({ theme })
212
227
  const out = merge({}, []) as { dataset: unknown[]; series: unknown[] }
@@ -10,7 +10,7 @@ import {
10
10
  } from '../../widgets/utils/chart-config'
11
11
  import { ZOOM_LAYOUT } from '../actions/zoom-toggle'
12
12
  import type { OptionFactory } from '../echart'
13
- import { mergeOptions } from '../utils'
13
+ import { mergeOptions, resolveThemeColor } from '../utils'
14
14
  import { positionDataZoomForLegend } from '../utils/data-zoom-layout'
15
15
  import type {
16
16
  TimeseriesEChartsOption,
@@ -152,7 +152,7 @@ export function createTimeseriesOptionFactory(
152
152
  options: TimeseriesOptionFactoryInput,
153
153
  ): OptionFactory {
154
154
  const { theme, formatter, labelFormatter, optionsOverride } = options
155
- const seriesNames = options.seriesNames
155
+ const series = options.series
156
156
  const smooth = options.smooth ?? true
157
157
  const area = options.area ?? false
158
158
  const selection = options.selection
@@ -250,11 +250,15 @@ export function createTimeseriesOptionFactory(
250
250
  const template =
251
251
  (seriesTemplates[i] as object | undefined) ??
252
252
  (broadcastTemplate as object)
253
+ // For line series, set BOTH `series[i].color` (legend swatch +
254
+ // markers) AND `series[i].lineStyle.color` (the line itself) so
255
+ // the override paints everywhere a series has a colour slot.
256
+ const overrideColor = resolveThemeColor(theme, series?.[i]?.color)
253
257
  return {
254
258
  ...(typeof template === 'object' ? template : {}),
255
259
  type: 'line' as const,
256
260
  datasetIndex: i,
257
- name: seriesNames?.[i] ?? `Series ${i + 1}`,
261
+ name: series?.[i]?.name ?? `Series ${i + 1}`,
258
262
  encode: { x: 'name', y: 'value' },
259
263
  smooth,
260
264
  // When a selection is active, surface markers so the per-point
@@ -264,6 +268,9 @@ export function createTimeseriesOptionFactory(
264
268
  ...(area ? { areaStyle: {} } : {}),
265
269
  emphasis: { focus: 'series' },
266
270
  itemStyle: dimItemStyle,
271
+ ...(overrideColor
272
+ ? { color: overrideColor, lineStyle: { color: overrideColor } }
273
+ : {}),
267
274
  }
268
275
  }),
269
276
  legend: { ...baseLegend, show: hasLegend },
@@ -1,5 +1,6 @@
1
1
  import type { Theme } from '@mui/material'
2
2
  import type { EChartsOption } from 'echarts'
3
+ import type { WidgetSeries } from '../types'
3
4
 
4
5
  /**
5
6
  * A single point on a time series. `name` is the time coordinate — accepts a
@@ -26,7 +27,7 @@ export interface TimeseriesOptionsInput {
26
27
  * Combined inputs for the timeseries option factory creator. Carries
27
28
  * everything the widget needs across BOTH phases — the structural-build
28
29
  * (`theme`, `formatter`, `labelFormatter`, `optionsOverride`) AND the
29
- * data merge (`seriesNames`, `smooth`, `area`, `selection`).
30
+ * data merge (`series`, `smooth`, `area`, `selection`).
30
31
  */
31
32
  export interface TimeseriesOptionFactoryInput {
32
33
  theme: Theme
@@ -38,8 +39,11 @@ export interface TimeseriesOptionFactoryInput {
38
39
  * RelativeData's reactive formatter swaps.
39
40
  */
40
41
  labelFormatter?: (value: Date) => string
41
- /** Series names — drives the legend and `series[i].name`. */
42
- seriesNames?: readonly string[]
42
+ /**
43
+ * Per-series metadata — drives the legend, `series[i].name`, and
44
+ * (when `color` is set) per-series line + marker colour overrides.
45
+ */
46
+ series?: readonly WidgetSeries[]
43
47
  /** Smooth lines (default `true`). */
44
48
  smooth?: boolean
45
49
  /** Filled area below each line (default `false`). */
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Canonical cross-widget series metadata.
3
+ *
4
+ * Every widget that can carry multiple series (Bar, Pie, Histogram,
5
+ * Scatterplot, Timeseries, Category, Formula, Spread) accepts a
6
+ * `series: readonly WidgetSeries[]` prop. The `name` drives legends,
7
+ * tooltips, and category-row avatars; the optional `color` overrides
8
+ * the default palette assignment.
9
+ *
10
+ * For backward compatibility, the widget-specific names
11
+ * (`FormulaSeries`, `CategorySeriesConfig`) are kept as type aliases of
12
+ * `WidgetSeries` — see `formula/types.ts` and `category/types.ts`.
13
+ *
14
+ * Colours accept MUI theme paths (e.g. `'primary.main'`) as well as raw
15
+ * CSS strings (`'#ff0000'`, `'rgb(…)'`). The echart-based widgets
16
+ * resolve them through `resolveThemeColor` (see
17
+ * `widgets-v2/utils/resolve-theme-color.ts`); Category and Formula/Spread
18
+ * resolve them implicitly via MUI's `sx` prop.
19
+ */
20
+ export interface WidgetSeries {
21
+ /** Display name — drives legend, tooltip, and avatar glyphs. */
22
+ name: string
23
+ /** Optional colour override. MUI theme path or raw CSS string. */
24
+ color?: string
25
+ }
@@ -1,2 +1,3 @@
1
1
  export { mergeOptions } from './merge-options'
2
2
  export { positionDataZoomForLegend } from './data-zoom-layout'
3
+ export { resolveThemeColor } from './resolve-theme-color'
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { createTheme } from '@mui/material'
3
+ import { resolveThemeColor } from './resolve-theme-color'
4
+
5
+ describe('resolveThemeColor', () => {
6
+ const theme = createTheme({
7
+ palette: {
8
+ primary: { main: '#1976d2', dark: '#0d47a1' },
9
+ secondary: { main: '#9c27b0' },
10
+ },
11
+ })
12
+
13
+ it('returns undefined when the input is undefined', () => {
14
+ expect(resolveThemeColor(theme, undefined)).toBeUndefined()
15
+ })
16
+
17
+ it('passes raw CSS colors through unchanged', () => {
18
+ expect(resolveThemeColor(theme, '#ff0000')).toBe('#ff0000')
19
+ expect(resolveThemeColor(theme, 'rgb(255, 0, 0)')).toBe('rgb(255, 0, 0)')
20
+ expect(resolveThemeColor(theme, 'red')).toBe('red')
21
+ })
22
+
23
+ it('resolves dotted MUI theme palette paths', () => {
24
+ expect(resolveThemeColor(theme, 'primary.main')).toBe('#1976d2')
25
+ expect(resolveThemeColor(theme, 'primary.dark')).toBe('#0d47a1')
26
+ expect(resolveThemeColor(theme, 'secondary.main')).toBe('#9c27b0')
27
+ })
28
+
29
+ it('returns the raw input when the theme path does not resolve', () => {
30
+ // Non-existent palette path → caller's responsibility to recover; we
31
+ // pass the string through so ECharts can at least attempt to parse it.
32
+ expect(resolveThemeColor(theme, 'primary.does-not-exist')).toBe(
33
+ 'primary.does-not-exist',
34
+ )
35
+ expect(resolveThemeColor(theme, 'nope.anywhere')).toBe('nope.anywhere')
36
+ })
37
+
38
+ it('handles a path that traverses but yields a non-string', () => {
39
+ // `primary` itself is an object, not a string — we return the raw
40
+ // input rather than `[object Object]`.
41
+ expect(resolveThemeColor(theme, 'primary')).toBe('primary')
42
+ })
43
+ })
@@ -0,0 +1,34 @@
1
+ import type { Theme } from '@mui/material'
2
+
3
+ /**
4
+ * Resolve a colour string against the MUI theme palette.
5
+ *
6
+ * - `'primary.main'`, `'secondary.dark'`, `'success.contrastText'`, … →
7
+ * walks `theme.palette` along the dot-separated path and returns the
8
+ * resolved string when traversal succeeds.
9
+ * - `'#ff0000'`, `'rgb(255, 0, 0)'`, `'red'` → returned as-is (assumed
10
+ * raw CSS; ECharts consumes them directly).
11
+ * - `undefined` → `undefined` (callers fall back to ECharts' palette).
12
+ *
13
+ * Used by the echart option factories (Bar, Pie, Histogram, Scatterplot,
14
+ * Timeseries) so per-series colours specified as theme paths in the
15
+ * unified `WidgetSeries` shape paint correctly. Category, Formula, and
16
+ * Spread render colours through MUI's `sx` resolver, which already
17
+ * handles theme paths — they don't need this helper.
18
+ */
19
+ export function resolveThemeColor(
20
+ theme: Theme,
21
+ raw: string | undefined,
22
+ ): string | undefined {
23
+ if (raw == null) return undefined
24
+ if (!raw.includes('.')) return raw
25
+ const parts = raw.split('.')
26
+ let cursor: unknown = theme.palette
27
+ for (const part of parts) {
28
+ if (cursor == null || typeof cursor !== 'object') {
29
+ return raw
30
+ }
31
+ cursor = (cursor as Record<string, unknown>)[part]
32
+ }
33
+ return typeof cursor === 'string' ? cursor : raw
34
+ }
@@ -1,34 +0,0 @@
1
- function u(t, n) {
2
- if (!n) return t;
3
- const c = {
4
- ...t
5
- };
6
- for (const r of Object.keys(n)) {
7
- const e = t[r], o = n[r];
8
- o !== void 0 && (c[r] = f(e, o));
9
- }
10
- return c;
11
- }
12
- function f(t, n) {
13
- if (Array.isArray(t) && Array.isArray(n)) {
14
- const c = Math.max(t.length, n.length), r = new Array(c);
15
- for (let e = 0; e < c; e++) {
16
- const o = t[e], i = n[e];
17
- i === void 0 ? r[e] = o : o === void 0 ? r[e] = i : r[e] = f(o, i);
18
- }
19
- return r;
20
- }
21
- return s(t) && s(n) ? {
22
- ...t,
23
- ...n
24
- } : n;
25
- }
26
- function s(t) {
27
- if (t === null || typeof t != "object") return !1;
28
- const n = Object.getPrototypeOf(t);
29
- return n === Object.prototype || n === null;
30
- }
31
- export {
32
- u as m
33
- };
34
- //# sourceMappingURL=merge-options-DCkkHZIf.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"merge-options-DCkkHZIf.js","sources":["../src/widgets-v2/utils/merge-options.ts"],"sourcesContent":["/**\n * Shallow-merges two ECharts option objects:\n * - Top-level keys from both are combined.\n * - Arrays are merged by index (element-wise shallow merge, primitive override).\n * - Plain objects are shallow-merged.\n * - Primitives are overridden by the override value.\n *\n * Designed for the two-stage memoization pattern: first build a base option\n * object from data + theme + formatters, then call `mergeOptions(base, override)`\n * inside a second `useMemo` keyed on `[base, override]`.\n */\nexport function mergeOptions<T extends Record<string, unknown>>(\n base: T,\n override?: Partial<T>,\n): T {\n if (!override) return base\n const out: Record<string, unknown> = { ...base }\n for (const key of Object.keys(override) as (keyof T)[]) {\n const a = base[key]\n const b = override[key]\n if (b === undefined) continue\n out[key as string] = mergeValue(a, b)\n }\n return out as T\n}\n\nfunction mergeValue(a: unknown, b: unknown): unknown {\n if (Array.isArray(a) && Array.isArray(b)) {\n const len = Math.max(a.length, b.length)\n const result = new Array<unknown>(len)\n for (let i = 0; i < len; i++) {\n const av: unknown = a[i]\n const bv: unknown = b[i]\n if (bv === undefined) result[i] = av\n else if (av === undefined) result[i] = bv\n else result[i] = mergeValue(av, bv)\n }\n return result\n }\n if (isPlainObject(a) && isPlainObject(b)) {\n return { ...a, ...b }\n }\n return b\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (v === null || typeof v !== 'object') return false\n const proto = Object.getPrototypeOf(v) as unknown\n return proto === Object.prototype || proto === null\n}\n"],"names":["mergeOptions","base","override","out","key","Object","keys","a","b","undefined","mergeValue","Array","isArray","len","Math","max","length","result","i","av","bv","isPlainObject","v","proto","getPrototypeOf","prototype"],"mappings":"AAWO,SAASA,EACdC,GACAC,GACG;AACH,MAAI,CAACA,EAAU,QAAOD;AACtB,QAAME,IAA+B;AAAA,IAAE,GAAGF;AAAAA,EAAAA;AAC1C,aAAWG,KAAOC,OAAOC,KAAKJ,CAAQ,GAAkB;AACtD,UAAMK,IAAIN,EAAKG,CAAG,GACZI,IAAIN,EAASE,CAAG;AACtB,IAAII,MAAMC,WACVN,EAAIC,CAAa,IAAIM,EAAWH,GAAGC,CAAC;AAAA,EACtC;AACA,SAAOL;AACT;AAEA,SAASO,EAAWH,GAAYC,GAAqB;AACnD,MAAIG,MAAMC,QAAQL,CAAC,KAAKI,MAAMC,QAAQJ,CAAC,GAAG;AACxC,UAAMK,IAAMC,KAAKC,IAAIR,EAAES,QAAQR,EAAEQ,MAAM,GACjCC,IAAS,IAAIN,MAAeE,CAAG;AACrC,aAASK,IAAI,GAAGA,IAAIL,GAAKK,KAAK;AAC5B,YAAMC,IAAcZ,EAAEW,CAAC,GACjBE,IAAcZ,EAAEU,CAAC;AACvB,MAAIE,MAAOX,SAAWQ,EAAOC,CAAC,IAAIC,IACzBA,MAAOV,SAAWQ,EAAOC,CAAC,IAAIE,IAClCH,EAAOC,CAAC,IAAIR,EAAWS,GAAIC,CAAE;AAAA,IACpC;AACA,WAAOH;AAAAA,EACT;AACA,SAAII,EAAcd,CAAC,KAAKc,EAAcb,CAAC,IAC9B;AAAA,IAAE,GAAGD;AAAAA,IAAG,GAAGC;AAAAA,EAAAA,IAEbA;AACT;AAEA,SAASa,EAAcC,GAA0C;AAC/D,MAAIA,MAAM,QAAQ,OAAOA,KAAM,SAAU,QAAO;AAChD,QAAMC,IAAQlB,OAAOmB,eAAeF,CAAC;AACrC,SAAOC,MAAUlB,OAAOoB,aAAaF,MAAU;AACjD;"}
@@ -1,186 +0,0 @@
1
- import { jsx as v, jsxs as N } from "react/jsx-runtime";
2
- import { c as _ } from "react/compiler-runtime";
3
- import { u as O } from "./widget-context-DTGO0Yta.js";
4
- import { u as P } from "./widget-store-registry-_W4Z4xp-.js";
5
- import { useState as z } from "react";
6
- import "zustand";
7
- import { Box as B, Slider as U, Typography as q, TextField as G } from "@mui/material";
8
- const $ = {
9
- root: {
10
- display: "flex",
11
- flexDirection: "column",
12
- gap: 3,
13
- py: 1
14
- },
15
- item: {
16
- display: "flex",
17
- flexDirection: "column",
18
- gap: 1.5
19
- },
20
- sliderContainer: {
21
- display: "flex",
22
- flexDirection: "column",
23
- gap: 1,
24
- px: 1
25
- },
26
- slider: {
27
- width: "100%",
28
- "&.Mui-disabled": {
29
- color: (a) => a.palette.text.disabled
30
- }
31
- },
32
- inputsRow: {
33
- display: "flex",
34
- gap: 2,
35
- alignItems: "center"
36
- },
37
- input: {
38
- flex: 1,
39
- "& .MuiInputBase-input": {
40
- textAlign: "center"
41
- }
42
- },
43
- note: {
44
- color: "text.secondary"
45
- }
46
- };
47
- function H(a) {
48
- const e = _(9), {
49
- items: i,
50
- onChange: t,
51
- formatter: l
52
- } = a, o = l ?? J;
53
- let s;
54
- if (e[0] !== o || e[1] !== i || e[2] !== t) {
55
- let r;
56
- e[4] !== o || e[5] !== t ? (r = (x, p) => /* @__PURE__ */ v(Q, { index: p, item: x, fmt: o, onChange: t }, `range-${x.min}-${x.max}-${p}`), e[4] = o, e[5] = t, e[6] = r) : r = e[6], s = i.map(r), e[0] = o, e[1] = i, e[2] = t, e[3] = s;
57
- } else
58
- s = e[3];
59
- let n;
60
- return e[7] !== s ? (n = /* @__PURE__ */ v(B, { sx: $.root, children: s }), e[7] = s, e[8] = n) : n = e[8], n;
61
- }
62
- function J(a) {
63
- return String(a);
64
- }
65
- function Q(a) {
66
- const e = _(54), {
67
- index: i,
68
- item: t,
69
- fmt: l,
70
- onChange: o
71
- } = a;
72
- let s;
73
- e[0] !== t.max || e[1] !== t.min || e[2] !== t.value ? (s = t.value ?? [t.min, t.max], e[0] = t.max, e[1] = t.min, e[2] = t.value, e[3] = s) : s = e[3];
74
- const n = s, [r, x] = z("");
75
- let p;
76
- e[4] !== i || e[5] !== t.max || e[6] !== t.min || e[7] !== o ? (p = (j) => {
77
- const [I, k] = j, L = Math.min(Math.max(I, t.min), t.max), T = Math.min(Math.max(k, t.min), t.max), K = L <= T ? [L, T] : [T, L];
78
- o?.(i, K);
79
- }, e[4] = i, e[5] = t.max, e[6] = t.min, e[7] = o, e[8] = p) : p = e[8];
80
- const m = p;
81
- let C;
82
- e[9] !== m || e[10] !== t.max || e[11] !== t.min ? (C = (j, I) => {
83
- if (!Array.isArray(I))
84
- return;
85
- const k = I[0] ?? t.min, L = I[1] ?? t.max;
86
- m([k, L]);
87
- }, e[9] = m, e[10] = t.max, e[11] = t.min, e[12] = C) : C = e[12];
88
- const y = C;
89
- let h;
90
- e[13] !== t.color ? (h = t.color ? {
91
- color: t.color
92
- } : null, e[13] = t.color, e[14] = h) : h = e[14];
93
- let d;
94
- e[15] !== h ? (d = {
95
- ...$.slider,
96
- ...h
97
- }, e[15] = h, e[16] = d) : d = e[16];
98
- let u;
99
- e[17] !== n ? (u = [...n], e[17] = n, e[18] = u) : u = e[18];
100
- const S = t.min, D = t.max, w = t.step ?? 1;
101
- let f;
102
- e[19] !== t.marks ? (f = V(t.marks), e[19] = t.marks, e[20] = f) : f = e[20];
103
- let g;
104
- e[21] !== l || e[22] !== y || e[23] !== t.disabled || e[24] !== t.max || e[25] !== t.min || e[26] !== f || e[27] !== d || e[28] !== u || e[29] !== w ? (g = /* @__PURE__ */ v(B, { sx: $.sliderContainer, children: /* @__PURE__ */ v(U, { sx: d, value: u, min: S, max: D, step: w, marks: f, disabled: t.disabled, valueLabelDisplay: "auto", valueLabelFormat: l, onChange: y }) }), e[21] = l, e[22] = y, e[23] = t.disabled, e[24] = t.max, e[25] = t.min, e[26] = f, e[27] = d, e[28] = u, e[29] = w, e[30] = g) : g = e[30];
105
- const R = `min-${n[0]}`;
106
- let c;
107
- e[31] !== m || e[32] !== n || e[33] !== r || e[34] !== l || e[35] !== t || e[36] !== R ? (c = /* @__PURE__ */ v(W, { name: "min", value: n[0], item: t, fmt: l, editing: r, setEditing: x, commit: m, current: n, ariaLabel: "Minimum value" }, R), e[31] = m, e[32] = n, e[33] = r, e[34] = l, e[35] = t, e[36] = R, e[37] = c) : c = e[37];
108
- const E = `max-${n[1]}`;
109
- let b;
110
- e[38] !== m || e[39] !== n || e[40] !== r || e[41] !== l || e[42] !== t || e[43] !== E ? (b = /* @__PURE__ */ v(W, { name: "max", value: n[1], item: t, fmt: l, editing: r, setEditing: x, commit: m, current: n, ariaLabel: "Maximum value" }, E), e[38] = m, e[39] = n, e[40] = r, e[41] = l, e[42] = t, e[43] = E, e[44] = b) : b = e[44];
111
- let M;
112
- e[45] !== c || e[46] !== b ? (M = /* @__PURE__ */ N(B, { sx: $.inputsRow, children: [
113
- c,
114
- b
115
- ] }), e[45] = c, e[46] = b, e[47] = M) : M = e[47];
116
- let F;
117
- e[48] !== t.note ? (F = t.note ? /* @__PURE__ */ v(q, { variant: "caption", sx: $.note, children: t.note }) : null, e[48] = t.note, e[49] = F) : F = e[49];
118
- let A;
119
- return e[50] !== g || e[51] !== M || e[52] !== F ? (A = /* @__PURE__ */ N(B, { sx: $.item, children: [
120
- g,
121
- M,
122
- F
123
- ] }), e[50] = g, e[51] = M, e[52] = F, e[53] = A) : A = e[53], A;
124
- }
125
- function W(a) {
126
- const e = _(26), {
127
- name: i,
128
- value: t,
129
- item: l,
130
- fmt: o,
131
- editing: s,
132
- setEditing: n,
133
- commit: r,
134
- current: x,
135
- ariaLabel: p
136
- } = a, [m, C] = z(String(t));
137
- let y;
138
- e[0] !== i || e[1] !== n ? (y = () => {
139
- n(i);
140
- }, e[0] = i, e[1] = n, e[2] = y) : y = e[2];
141
- const h = y;
142
- let d, u;
143
- if (e[3] !== r || e[4] !== x || e[5] !== i || e[6] !== n || e[7] !== t) {
144
- let R = function(c) {
145
- const E = parseFloat(c), b = Number.isFinite(E) ? E : t, M = i === "min" ? [b, x[1]] : [x[0], b];
146
- r(M);
147
- };
148
- u = (c) => {
149
- n(""), R(c.target.value);
150
- }, d = (c) => {
151
- c.key === "Enter" && (R(c.target.value), c.target.blur());
152
- }, e[3] = r, e[4] = x, e[5] = i, e[6] = n, e[7] = t, e[8] = d, e[9] = u;
153
- } else
154
- d = e[8], u = e[9];
155
- let S;
156
- e[10] !== s || e[11] !== o || e[12] !== i || e[13] !== m ? (S = s === i ? m : o(Number(m)), e[10] = s, e[11] = o, e[12] = i, e[13] = m, e[14] = S) : S = e[14];
157
- const D = S;
158
- let w;
159
- e[15] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (w = (R) => C(R.target.value), e[15] = w) : w = e[15];
160
- let f;
161
- e[16] !== p ? (f = {
162
- "aria-label": p
163
- }, e[16] = p, e[17] = f) : f = e[17];
164
- let g;
165
- return e[18] !== h || e[19] !== d || e[20] !== D || e[21] !== u || e[22] !== l.disabled || e[23] !== i || e[24] !== f ? (g = /* @__PURE__ */ v(G, { name: i, value: D, onChange: w, onFocus: h, onBlur: u, onKeyDown: d, disabled: l.disabled, size: "small", sx: $.input, inputProps: f }), e[18] = h, e[19] = d, e[20] = D, e[21] = u, e[22] = l.disabled, e[23] = i, e[24] = f, e[25] = g) : g = e[25], g;
166
- }
167
- function V(a) {
168
- if (a != null)
169
- return typeof a == "boolean" ? a : [...a];
170
- }
171
- const X = (a) => ({
172
- data: a.data ?? [],
173
- formatter: a.formatter
174
- });
175
- function ae(a) {
176
- const e = _(4), {
177
- onChange: i
178
- } = a, t = O(), l = P(t, X);
179
- let o;
180
- return e[0] !== i || e[1] !== l.data || e[2] !== l.formatter ? (o = /* @__PURE__ */ v(H, { items: l.data, formatter: l.formatter, onChange: i }), e[0] = i, e[1] = l.data, e[2] = l.formatter, e[3] = o) : o = e[3], o;
181
- }
182
- export {
183
- ae as R,
184
- H as a
185
- };
186
- //# sourceMappingURL=range-DsqTjSpg.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"range-DsqTjSpg.js","sources":["../src/widgets-v2/range/style.ts","../src/widgets-v2/range/range-ui.tsx","../src/widgets-v2/range/range.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material'\n\nexport const styles = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n py: 1,\n },\n item: {\n display: 'flex',\n flexDirection: 'column',\n gap: 1.5,\n },\n sliderContainer: {\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n px: 1,\n },\n slider: {\n width: '100%',\n '&.Mui-disabled': {\n color: (theme: Theme) => theme.palette.text.disabled,\n },\n },\n inputsRow: {\n display: 'flex',\n gap: 2,\n alignItems: 'center',\n },\n input: {\n flex: 1,\n '& .MuiInputBase-input': {\n textAlign: 'center',\n },\n },\n note: {\n color: 'text.secondary',\n },\n} satisfies Record<string, SxProps<Theme>>\n","import {\n useCallback,\n useState,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react'\nimport { Box, Slider, TextField, Typography } from '@mui/material'\nimport type { RangeDataItem, RangeItemValue } from './types'\nimport { styles } from './style'\n\nexport interface RangeUIProps {\n items: readonly RangeDataItem[]\n /**\n * Fires when the user drags a thumb or commits a new value via the text\n * inputs. Per the destination-owned principle, the consumer owns the\n * value — this widget surfaces changes but does not store them.\n */\n onChange?: (index: number, value: RangeItemValue) => void\n /** Number formatter for the slider tooltip and the text input display. */\n formatter?: (value: number) => string\n}\n\ntype Bound = 'min' | 'max'\n\n/**\n * Pure presentational component for the Range widget. Renders one MUI Slider\n * per item with editable min/max text inputs below — matching the Range v1\n * UX. Each item is always a two-thumb range; supply `value` to seed the\n * starting selection, otherwise it defaults to `[min, max]`.\n */\nexport function RangeUI({ items, onChange, formatter }: RangeUIProps) {\n const fmt = formatter ?? ((n: number) => String(n))\n return (\n <Box sx={styles.root}>\n {items.map((item, i) => (\n // Composite of the row's track bounds — stable across reorders for\n // any realistic widget configuration. Falls back to a literal +\n // index when bounds collide (degenerate same-min-same-max rows).\n <RangeRow\n key={`range-${item.min}-${item.max}-${i}`}\n index={i}\n item={item}\n fmt={fmt}\n onChange={onChange}\n />\n ))}\n </Box>\n )\n}\n\ninterface RangeRowProps {\n index: number\n item: RangeDataItem\n fmt: (n: number) => string\n onChange?: (index: number, value: RangeItemValue) => void\n}\n\nfunction RangeRow({ index, item, fmt, onChange }: RangeRowProps) {\n const current: readonly [number, number] = item.value ?? [item.min, item.max]\n const [editing, setEditing] = useState<'' | Bound>('')\n\n const commit = useCallback(\n (next: readonly [number, number]) => {\n // Clamp inside [min, max] and keep `low <= high`.\n const [lowRaw, highRaw] = next\n const low = Math.min(Math.max(lowRaw, item.min), item.max)\n const high = Math.min(Math.max(highRaw, item.min), item.max)\n const ordered: readonly [number, number] =\n low <= high ? [low, high] : [high, low]\n onChange?.(index, ordered)\n },\n [index, item.min, item.max, onChange],\n )\n\n const handleSlider = (_: Event, raw: number | number[]) => {\n if (!Array.isArray(raw)) return\n // Hoist defaults out of the destructure: react-compiler can't safely\n // reorder MemberExpression defaults inside an array pattern.\n const low = raw[0] ?? item.min\n const high = raw[1] ?? item.max\n commit([low, high])\n }\n\n return (\n <Box sx={styles.item}>\n <Box sx={styles.sliderContainer}>\n <Slider\n sx={{\n ...styles.slider,\n ...(item.color ? { color: item.color } : null),\n }}\n value={[...current]}\n min={item.min}\n max={item.max}\n step={item.step ?? 1}\n marks={resolveMarks(item.marks)}\n disabled={item.disabled}\n valueLabelDisplay='auto'\n valueLabelFormat={fmt}\n onChange={handleSlider}\n />\n </Box>\n <Box sx={styles.inputsRow}>\n <BoundInput\n // Bumping the key on a fresh external value resets the local\n // editing state — matches v1's RangeItem behaviour.\n key={`min-${current[0]}`}\n name='min'\n value={current[0]}\n item={item}\n fmt={fmt}\n editing={editing}\n setEditing={setEditing}\n commit={commit}\n current={current}\n ariaLabel='Minimum value'\n />\n <BoundInput\n key={`max-${current[1]}`}\n name='max'\n value={current[1]}\n item={item}\n fmt={fmt}\n editing={editing}\n setEditing={setEditing}\n commit={commit}\n current={current}\n ariaLabel='Maximum value'\n />\n </Box>\n {item.note ? (\n <Typography variant='caption' sx={styles.note}>\n {item.note}\n </Typography>\n ) : null}\n </Box>\n )\n}\n\ninterface BoundInputProps {\n name: Bound\n value: number\n item: RangeDataItem\n fmt: (n: number) => string\n editing: '' | Bound\n setEditing: (next: '' | Bound) => void\n commit: (next: readonly [number, number]) => void\n current: readonly [number, number]\n ariaLabel: string\n}\n\nfunction BoundInput({\n name,\n value,\n item,\n fmt,\n editing,\n setEditing,\n commit,\n current,\n ariaLabel,\n}: BoundInputProps) {\n const [raw, setRaw] = useState<string>(String(value))\n\n const beginEditing = () => {\n setEditing(name)\n }\n const finishEditingAndCommit = (e: FocusEvent<HTMLInputElement>) => {\n setEditing('')\n commitFromText(e.target.value)\n }\n const commitOnEnter = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n commitFromText((e.target as HTMLInputElement).value)\n ;(e.target as HTMLInputElement).blur()\n }\n }\n\n function commitFromText(input: string) {\n const parsed = parseFloat(input)\n const safe = Number.isFinite(parsed) ? parsed : value\n const next: readonly [number, number] =\n name === 'min' ? [safe, current[1]] : [current[0], safe]\n commit(next)\n }\n\n const display = editing === name ? raw : fmt(Number(raw))\n\n return (\n <TextField\n name={name}\n value={display}\n onChange={(e) => setRaw(e.target.value)}\n onFocus={beginEditing}\n onBlur={finishEditingAndCommit}\n onKeyDown={commitOnEnter}\n disabled={item.disabled}\n size='small'\n sx={styles.input}\n inputProps={{ 'aria-label': ariaLabel }}\n />\n )\n}\n\nfunction resolveMarks(\n marks: RangeDataItem['marks'],\n): boolean | { value: number; label?: string }[] | undefined {\n if (marks == null) return undefined\n if (typeof marks === 'boolean') return marks\n return [...marks]\n}\n","import { useWidgetId, useWidgetShallow } from '../stores'\nimport { RangeUI } from './range-ui'\nimport type { RangeItemValue, RangeWidgetData } from './types'\n\ninterface RangeSlice {\n data: RangeWidgetData\n formatter?: (value: number) => string\n}\n\nconst rangeSelector = (s: {\n data: unknown\n formatter?: (value: number) => string\n}): RangeSlice => ({\n data: (s.data ?? []) as RangeWidgetData,\n formatter: s.formatter,\n})\n\nexport interface RangeProps {\n /**\n * Fires when the user moves a slider thumb or commits a new value via the\n * text inputs. Receives the item index in `state.data` and the new\n * `[low, high]` tuple. The consumer owns the data state — the widget\n * surfaces changes but does not persist them.\n */\n onChange?: (index: number, value: RangeItemValue) => void\n}\n\n/**\n * Stateful Range bridge — reads `data` (post-pipeline) and `formatter` from\n * the per-widget store and forwards them to the pure {@link RangeUI}. Per\n * the destination-owned principle, value changes flow back through\n * `onChange` — the consumer is expected to update the data prop on\n * `<Provider>`. Use `disabled` on individual `RangeDataItem`s to disable\n * specific rows.\n */\nexport function Range({ onChange }: RangeProps) {\n const id = useWidgetId()\n const slice = useWidgetShallow(id, rangeSelector)\n return (\n <RangeUI\n items={slice.data}\n formatter={slice.formatter}\n onChange={onChange}\n />\n )\n}\n"],"names":["styles","root","display","flexDirection","gap","py","item","sliderContainer","px","slider","width","color","theme","palette","text","disabled","inputsRow","alignItems","input","flex","textAlign","note","RangeUI","t0","$","_c","items","onChange","formatter","fmt","_temp","t1","t2","i","jsx","RangeRow","min","max","map","Box","n","String","index","value","current","editing","setEditing","useState","next","lowRaw","highRaw","low","Math","high","ordered","commit","t3","_","raw","Array","isArray","low_0","high_0","handleSlider","t4","t5","t6","t7","t8","t9","step","t10","marks","resolveMarks","t11","Slider","t12","t13","BoundInput","t14","t15","t16","t17","Typography","t18","jsxs","name","ariaLabel","setRaw","beginEditing","commitOnEnter","finishEditingAndCommit","commitFromText","parsed","parseFloat","safe","Number","isFinite","e","target","e_0","key","blur","Symbol","for","e_1","TextField","rangeSelector","s","data","Range","id","useWidgetId","slice","useWidgetShallow"],"mappings":"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"}