@gunkin/uiify 0.0.3-alpha → 0.0.5-alpha

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 (83) hide show
  1. package/dist/components/candle-chart/CandleChart.d.ts +10 -1
  2. package/dist/components/candle-chart/CandleChart.d.ts.map +1 -1
  3. package/dist/components/candle-chart/CandleChart.js +82 -42
  4. package/dist/components/candle-chart/CandleChart.js.map +1 -1
  5. package/dist/components/candle-chart/client/CandleChartClient.d.ts +2 -2
  6. package/dist/components/candle-chart/client/CandleChartClient.d.ts.map +1 -1
  7. package/dist/components/candle-chart/client/CandleChartClient.js +103 -14
  8. package/dist/components/candle-chart/client/CandleChartClient.js.map +1 -1
  9. package/dist/components/candle-chart/client/index.d.ts +1 -0
  10. package/dist/components/candle-chart/client/index.d.ts.map +1 -1
  11. package/dist/components/candle-chart/client/index.js.map +1 -1
  12. package/dist/components/candle-chart/types.d.ts +39 -0
  13. package/dist/components/candle-chart/types.d.ts.map +1 -1
  14. package/dist/components/color-picker/ColorPicker.d.ts +4 -34
  15. package/dist/components/color-picker/ColorPicker.d.ts.map +1 -1
  16. package/dist/components/color-picker/ColorPicker.js +96 -164
  17. package/dist/components/color-picker/ColorPicker.js.map +1 -1
  18. package/dist/components/color-picker/index.d.ts +2 -3
  19. package/dist/components/color-picker/index.d.ts.map +1 -1
  20. package/dist/components/color-picker/index.js +2 -40
  21. package/dist/components/color-picker/index.js.map +1 -1
  22. package/dist/components/color-picker/types.d.ts +13 -69
  23. package/dist/components/color-picker/types.d.ts.map +1 -1
  24. package/dist/components/context-menu/ContextMenu.d.ts.map +1 -1
  25. package/dist/components/context-menu/ContextMenu.js +13 -1
  26. package/dist/components/context-menu/ContextMenu.js.map +1 -1
  27. package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.d.ts +11 -0
  28. package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.d.ts.map +1 -0
  29. package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.js +21 -0
  30. package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.js.map +1 -0
  31. package/dist/components/internal/live-chart/types.d.ts +36 -0
  32. package/dist/components/internal/live-chart/types.d.ts.map +1 -0
  33. package/dist/components/internal/live-chart/types.js +1 -0
  34. package/dist/components/internal/live-chart/types.js.map +1 -0
  35. package/dist/components/internal/live-chart/use-live-chart-window.d.ts +18 -0
  36. package/dist/components/internal/live-chart/use-live-chart-window.d.ts.map +1 -0
  37. package/dist/components/internal/live-chart/use-live-chart-window.js +75 -0
  38. package/dist/components/internal/live-chart/use-live-chart-window.js.map +1 -0
  39. package/dist/components/line-chart/LineChart.d.ts +6 -1
  40. package/dist/components/line-chart/LineChart.d.ts.map +1 -1
  41. package/dist/components/line-chart/LineChart.js +82 -48
  42. package/dist/components/line-chart/LineChart.js.map +1 -1
  43. package/dist/components/line-chart/client/LineChartClient.d.ts +2 -2
  44. package/dist/components/line-chart/client/LineChartClient.d.ts.map +1 -1
  45. package/dist/components/line-chart/client/LineChartClient.js +106 -14
  46. package/dist/components/line-chart/client/LineChartClient.js.map +1 -1
  47. package/dist/components/line-chart/client/index.d.ts +1 -1
  48. package/dist/components/line-chart/client/index.d.ts.map +1 -1
  49. package/dist/components/line-chart/client/index.js.map +1 -1
  50. package/dist/components/line-chart/line-chart-geometry.d.ts +7 -0
  51. package/dist/components/line-chart/line-chart-geometry.d.ts.map +1 -1
  52. package/dist/components/line-chart/line-chart-geometry.js +14 -2
  53. package/dist/components/line-chart/line-chart-geometry.js.map +1 -1
  54. package/dist/components/line-chart/types.d.ts +42 -0
  55. package/dist/components/line-chart/types.d.ts.map +1 -1
  56. package/dist/components/number-field/NumberField.d.ts.map +1 -1
  57. package/dist/components/number-field/NumberField.js +5 -1
  58. package/dist/components/number-field/NumberField.js.map +1 -1
  59. package/dist/components/slider/Slider.d.ts.map +1 -1
  60. package/dist/components/slider/Slider.js +15 -0
  61. package/dist/components/slider/Slider.js.map +1 -1
  62. package/dist/components/slider/client/SliderClient.d.ts +7 -0
  63. package/dist/components/slider/client/SliderClient.d.ts.map +1 -0
  64. package/dist/components/slider/client/SliderClient.js +170 -0
  65. package/dist/components/slider/client/SliderClient.js.map +1 -0
  66. package/dist/components/slider/client/index.d.ts +3 -0
  67. package/dist/components/slider/client/index.d.ts.map +1 -0
  68. package/dist/components/slider/client/index.js +5 -0
  69. package/dist/components/slider/client/index.js.map +1 -0
  70. package/dist/components/slider/client.d.ts +1 -0
  71. package/dist/components/slider/client.js +1 -0
  72. package/dist/components/slider/slider-values.d.ts +4 -0
  73. package/dist/components/slider/slider-values.d.ts.map +1 -0
  74. package/dist/components/slider/slider-values.js +26 -0
  75. package/dist/components/slider/slider-values.js.map +1 -0
  76. package/dist/components/slider/types.d.ts +26 -1
  77. package/dist/components/slider/types.d.ts.map +1 -1
  78. package/dist/styles/index.css +1 -1
  79. package/package.json +1 -1
  80. package/dist/components/color-picker/color.d.ts +0 -15
  81. package/dist/components/color-picker/color.d.ts.map +0 -1
  82. package/dist/components/color-picker/color.js +0 -190
  83. package/dist/components/color-picker/color.js.map +0 -1
@@ -1,13 +1,23 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { useCallback, useState } from "react";
3
+ import { useCallback, useMemo, useState } from "react";
4
4
  import { useChartViewport } from "../../../hooks/use-chart-viewport.js";
5
5
  import { useMergedRefs } from "../../../hooks/use-merged-refs.js";
6
- import { LineChart } from "../LineChart.js";
6
+ import { useResizeObserver } from "../../../hooks/use-resize-observer.js";
7
+ import {
8
+ liveTimeAxis,
9
+ useLiveChartWindow
10
+ } from "../../internal/live-chart/use-live-chart-window.js";
11
+ import { useScrollbarReserve } from "../../internal/chart-scrollbar/use-scrollbar-reserve.js";
12
+ import { VirtualScroll } from "../../virtual-scroll/VirtualScroll.js";
13
+ import { LineChart, LineChartPoint } from "../LineChart.js";
14
+ import { getValueBounds } from "../line-chart-geometry.js";
7
15
  const Y_AXIS_COLUMN_WIDTH = 72 + 12;
8
16
  function LineChartClient(props) {
9
17
  const {
10
18
  data,
19
+ visibleCount,
20
+ xAxis,
11
21
  ref: consumerRef,
12
22
  style: consumerStyle,
13
23
  onPointClick: consumerOnPointClick,
@@ -15,14 +25,27 @@ function LineChartClient(props) {
15
25
  onPointPointerMove: consumerOnPointPointerMove,
16
26
  ...consumerProps
17
27
  } = props;
18
- const viewport = useChartViewport({
19
- itemCount: data.length,
20
- measuredWidthOffset: Y_AXIS_COLUMN_WIDTH,
21
- minItemWidth: 24
28
+ const live = visibleCount !== void 0 && visibleCount > 0;
29
+ const viewport = useChartViewport(
30
+ live ? {
31
+ enabled: false,
32
+ initialScale: 1,
33
+ itemCount: visibleCount,
34
+ measuredWidthOffset: Y_AXIS_COLUMN_WIDTH
35
+ } : { itemCount: data.length, measuredWidthOffset: Y_AXIS_COLUMN_WIDTH, minItemWidth: 24 }
36
+ );
37
+ const figureSize = useResizeObserver(viewport.ref);
38
+ const liveWindow = useLiveChartWindow({
39
+ count: data.length,
40
+ visibleCount,
41
+ itemWidth: viewport.itemWidth,
42
+ figureHeight: figureSize?.height,
43
+ scrollVariable: "--line-scroll-x"
22
44
  });
45
+ useScrollbarReserve(liveWindow.chartRef, "--line-scrollbar-size");
23
46
  const [cursor, setCursor] = useState(null);
24
47
  const [selectedPointIndex, setSelectedPointIndex] = useState();
25
- const chartRef = useMergedRefs(viewport.ref, consumerRef);
48
+ const chartRef = useMergedRefs(viewport.ref, consumerRef, liveWindow.chartRef);
26
49
  const handlePointClick = useCallback(
27
50
  (index) => {
28
51
  setSelectedPointIndex(index);
@@ -41,22 +64,91 @@ function LineChartClient(props) {
41
64
  },
42
65
  [consumerOnPointPointerMove]
43
66
  );
67
+ const liveItems = useMemo(
68
+ () => live ? data.map((point, index) => ({ id: String(index), point })) : [],
69
+ [data, live]
70
+ );
44
71
  const style = {
45
72
  ...consumerStyle,
46
73
  "--line-scale": String(viewport.scale)
47
74
  };
75
+ if (!live) {
76
+ const chartProps2 = {
77
+ ...consumerProps,
78
+ ...xAxis ? { xAxis } : {},
79
+ data,
80
+ activePointIndex: cursor?.index,
81
+ cursorY: cursor?.offsetY,
82
+ interactive: true,
83
+ onPointClick: handlePointClick,
84
+ onPointPointerLeave: handlePointPointerLeave,
85
+ onPointPointerMove: handlePointPointerMove,
86
+ ref: chartRef,
87
+ selectedPointIndex,
88
+ style
89
+ };
90
+ return /* @__PURE__ */ jsx(LineChart, { ...chartProps2 });
91
+ }
92
+ const { sliceStart, sliceEnd, contentSize, plotHeight } = liveWindow;
93
+ const slice = data.slice(sliceStart, sliceEnd);
94
+ const { min, max } = getValueBounds(slice);
95
+ const toSliceIndex = (index) => index !== void 0 && index >= sliceStart && index < sliceEnd ? index - sliceStart : void 0;
96
+ const pointLayer = /* @__PURE__ */ jsx(
97
+ VirtualScroll,
98
+ {
99
+ height: plotHeight,
100
+ items: liveItems,
101
+ orientation: "horizontal",
102
+ overscan: 2,
103
+ rowHeight: viewport.itemWidth,
104
+ scrollRef: liveWindow.scrollRef,
105
+ onRangeChange: liveWindow.onRangeChange,
106
+ renderRow: ({ point }, index) => {
107
+ const inSlice = index >= sliceStart && index < sliceEnd;
108
+ const isActive = cursor?.index === index;
109
+ return /* @__PURE__ */ jsx(
110
+ LineChartPoint,
111
+ {
112
+ as: "div",
113
+ point,
114
+ previousPoint: data[index - 1],
115
+ index,
116
+ count: data.length,
117
+ min,
118
+ max,
119
+ interactive: inSlice,
120
+ isActive,
121
+ isSelected: selectedPointIndex === index,
122
+ cursorY: isActive ? cursor?.offsetY : void 0,
123
+ onPointClick: handlePointClick,
124
+ onPointPointerLeave: handlePointPointerLeave,
125
+ onPointPointerMove: handlePointPointerMove
126
+ }
127
+ );
128
+ }
129
+ }
130
+ );
131
+ const liveStyle = {
132
+ ...style,
133
+ "--line-content-size": `${contentSize}px`,
134
+ "--line-plot-height": `${plotHeight}px`,
135
+ // One virtual row: the viewport holds `visibleCount` of them.
136
+ "--line-run": String(100 / visibleCount)
137
+ };
48
138
  const chartProps = {
49
139
  ...consumerProps,
50
- data,
51
- activePointIndex: cursor?.index,
140
+ data: slice,
141
+ xAxis: xAxis ?? liveTimeAxis(data, sliceStart, sliceEnd, visibleCount),
142
+ activePointIndex: toSliceIndex(cursor?.index),
143
+ announceReadout: false,
144
+ pointLayer,
52
145
  cursorY: cursor?.offsetY,
53
146
  interactive: true,
54
- onPointClick: handlePointClick,
55
- onPointPointerLeave: handlePointPointerLeave,
56
- onPointPointerMove: handlePointPointerMove,
57
147
  ref: chartRef,
58
- selectedPointIndex,
59
- style
148
+ selectedPointIndex: toSliceIndex(selectedPointIndex),
149
+ slotCount: data.length,
150
+ slotOffset: sliceStart,
151
+ style: liveStyle
60
152
  };
61
153
  return /* @__PURE__ */ jsx(LineChart, { ...chartProps });
62
154
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/line-chart/client/LineChartClient.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useState } from \"react\";\nimport type { CSSProperties, ElementType, ReactElement, Ref } from \"react\";\nimport { useChartViewport } from \"../../../hooks/use-chart-viewport.js\";\nimport { useMergedRefs } from \"../../../hooks/use-merged-refs.js\";\nimport { LineChart } from \"../LineChart.js\";\nimport type { LineChartPointerPosition, LineChartProps } from \"../types.js\";\n\ninterface CursorState extends LineChartPointerPosition {}\n\ninterface InteractiveLineStyle extends CSSProperties {\n \"--line-scale\": string;\n}\n\n/**\n * `[data-part=\"plot\"]`'s fixed price-axis column (4.5rem) plus its grid gap\n * (0.75rem) — see line-chart.css. `useChartViewport` measures the whole\n * `<figure>`, but points only ever get the width left over after this\n * column, so it must be subtracted before sizing `minItemWidth`.\n */\nconst Y_AXIS_COLUMN_WIDTH = 72 + 12;\n\nexport function LineChartClient<TAs extends ElementType = \"figure\">(\n props: LineChartProps<TAs>,\n): ReactElement | null {\n const {\n data,\n ref: consumerRef,\n style: consumerStyle,\n onPointClick: consumerOnPointClick,\n onPointPointerLeave: consumerOnPointPointerLeave,\n onPointPointerMove: consumerOnPointPointerMove,\n ...consumerProps\n } = props as LineChartProps<\"figure\"> & {\n ref?: Ref<HTMLElement>;\n style?: CSSProperties;\n };\n const viewport = useChartViewport({\n itemCount: data.length,\n measuredWidthOffset: Y_AXIS_COLUMN_WIDTH,\n minItemWidth: 24,\n });\n const [cursor, setCursor] = useState<CursorState | null>(null);\n const [selectedPointIndex, setSelectedPointIndex] = useState<number | undefined>();\n const chartRef = useMergedRefs<HTMLElement>(viewport.ref, consumerRef);\n const handlePointClick = useCallback(\n (index: number) => {\n setSelectedPointIndex(index);\n consumerOnPointClick?.(index);\n },\n [consumerOnPointClick],\n );\n const handlePointPointerLeave = useCallback(() => {\n setCursor(null);\n consumerOnPointPointerLeave?.();\n }, [consumerOnPointPointerLeave]);\n const handlePointPointerMove = useCallback(\n (position: LineChartPointerPosition) => {\n setCursor(position);\n consumerOnPointPointerMove?.(position);\n },\n [consumerOnPointPointerMove],\n );\n\n const style: InteractiveLineStyle = {\n ...consumerStyle,\n \"--line-scale\": String(viewport.scale),\n };\n const chartProps = {\n ...consumerProps,\n data,\n activePointIndex: cursor?.index,\n cursorY: cursor?.offsetY,\n interactive: true,\n onPointClick: handlePointClick,\n onPointPointerLeave: handlePointPointerLeave,\n onPointPointerMove: handlePointPointerMove,\n ref: chartRef,\n selectedPointIndex,\n style,\n } as LineChartProps<\"figure\">;\n\n return <LineChart {...chartProps} />;\n}\nLineChartClient.displayName = \"LineChartClient\";\n"],"mappings":";AAmFS;AAjFT,SAAS,aAAa,gBAAgB;AAEtC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAe1B,MAAM,sBAAsB,KAAK;AAE1B,SAAS,gBACd,OACqB;AACrB,QAAM;AAAA,IACJ;AAAA,IACA,KAAK;AAAA,IACL,OAAO;AAAA,IACP,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,GAAG;AAAA,EACL,IAAI;AAIJ,QAAM,WAAW,iBAAiB;AAAA,IAChC,WAAW,KAAK;AAAA,IAChB,qBAAqB;AAAA,IACrB,cAAc;AAAA,EAChB,CAAC;AACD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA6B,IAAI;AAC7D,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAA6B;AACjF,QAAM,WAAW,cAA2B,SAAS,KAAK,WAAW;AACrE,QAAM,mBAAmB;AAAA,IACvB,CAAC,UAAkB;AACjB,4BAAsB,KAAK;AAC3B,6BAAuB,KAAK;AAAA,IAC9B;AAAA,IACA,CAAC,oBAAoB;AAAA,EACvB;AACA,QAAM,0BAA0B,YAAY,MAAM;AAChD,cAAU,IAAI;AACd,kCAA8B;AAAA,EAChC,GAAG,CAAC,2BAA2B,CAAC;AAChC,QAAM,yBAAyB;AAAA,IAC7B,CAAC,aAAuC;AACtC,gBAAU,QAAQ;AAClB,mCAA6B,QAAQ;AAAA,IACvC;AAAA,IACA,CAAC,0BAA0B;AAAA,EAC7B;AAEA,QAAM,QAA8B;AAAA,IAClC,GAAG;AAAA,IACH,gBAAgB,OAAO,SAAS,KAAK;AAAA,EACvC;AACA,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH;AAAA,IACA,kBAAkB,QAAQ;AAAA,IAC1B,SAAS,QAAQ;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,KAAK;AAAA,IACL;AAAA,IACA;AAAA,EACF;AAEA,SAAO,oBAAC,aAAW,GAAG,YAAY;AACpC;AACA,gBAAgB,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/line-chart/client/LineChartClient.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { CSSProperties, ElementType, ReactElement, Ref } from \"react\";\nimport { useChartViewport } from \"../../../hooks/use-chart-viewport.js\";\nimport { useMergedRefs } from \"../../../hooks/use-merged-refs.js\";\nimport { useResizeObserver } from \"../../../hooks/use-resize-observer.js\";\nimport {\n liveTimeAxis,\n useLiveChartWindow,\n} from \"../../internal/live-chart/use-live-chart-window.js\";\nimport { useScrollbarReserve } from \"../../internal/chart-scrollbar/use-scrollbar-reserve.js\";\nimport { VirtualScroll } from \"../../virtual-scroll/VirtualScroll.js\";\nimport { LineChart, LineChartPoint } from \"../LineChart.js\";\nimport { getValueBounds } from \"../line-chart-geometry.js\";\nimport type {\n LineChartClientProps,\n LineChartData,\n LineChartPointerPosition,\n LineChartProps,\n LineChartViewProps,\n} from \"../types.js\";\n\ninterface CursorState extends LineChartPointerPosition {}\n\ninterface InteractiveLineStyle extends CSSProperties {\n \"--line-scale\": string;\n \"--line-content-size\"?: string;\n \"--line-plot-height\"?: string;\n \"--line-run\"?: string;\n}\n\ninterface LivePoint {\n readonly id: string;\n readonly point: LineChartData;\n}\n\n/**\n * `[data-part=\"plot\"]`'s fixed price-axis column (4.5rem) plus its grid gap\n * (0.75rem) — see line-chart.css. `useChartViewport` measures the whole\n * `<figure>`, but points only ever get the width left over after this\n * column, so it must be subtracted before sizing `minItemWidth`.\n */\nconst Y_AXIS_COLUMN_WIDTH = 72 + 12;\n\nexport function LineChartClient<TAs extends ElementType = \"figure\">(\n props: LineChartClientProps<TAs>,\n): ReactElement | null {\n const {\n data,\n visibleCount,\n xAxis,\n ref: consumerRef,\n style: consumerStyle,\n onPointClick: consumerOnPointClick,\n onPointPointerLeave: consumerOnPointPointerLeave,\n onPointPointerMove: consumerOnPointPointerMove,\n ...consumerProps\n } = props as LineChartClientProps<\"figure\"> & {\n ref?: Ref<HTMLElement>;\n style?: CSSProperties;\n };\n const live = visibleCount !== undefined && visibleCount > 0;\n const viewport = useChartViewport(\n live\n ? {\n enabled: false,\n initialScale: 1,\n itemCount: visibleCount,\n measuredWidthOffset: Y_AXIS_COLUMN_WIDTH,\n }\n : { itemCount: data.length, measuredWidthOffset: Y_AXIS_COLUMN_WIDTH, minItemWidth: 24 },\n );\n const figureSize = useResizeObserver(viewport.ref);\n const liveWindow = useLiveChartWindow({\n count: data.length,\n visibleCount,\n itemWidth: viewport.itemWidth,\n figureHeight: figureSize?.height,\n scrollVariable: \"--line-scroll-x\",\n });\n useScrollbarReserve(liveWindow.chartRef, \"--line-scrollbar-size\");\n // Cursor and selection hold absolute indices so they survive scrolling and appends.\n const [cursor, setCursor] = useState<CursorState | null>(null);\n const [selectedPointIndex, setSelectedPointIndex] = useState<number | undefined>();\n const chartRef = useMergedRefs<HTMLElement>(viewport.ref, consumerRef, liveWindow.chartRef);\n const handlePointClick = useCallback(\n (index: number) => {\n setSelectedPointIndex(index);\n consumerOnPointClick?.(index);\n },\n [consumerOnPointClick],\n );\n const handlePointPointerLeave = useCallback(() => {\n setCursor(null);\n consumerOnPointPointerLeave?.();\n }, [consumerOnPointPointerLeave]);\n const handlePointPointerMove = useCallback(\n (position: LineChartPointerPosition) => {\n setCursor(position);\n consumerOnPointPointerMove?.(position);\n },\n [consumerOnPointPointerMove],\n );\n const liveItems = useMemo<readonly LivePoint[]>(\n () => (live ? data.map((point, index) => ({ id: String(index), point })) : []),\n [data, live],\n );\n\n const style: InteractiveLineStyle = {\n ...consumerStyle,\n \"--line-scale\": String(viewport.scale),\n };\n\n if (!live) {\n const chartProps = {\n ...consumerProps,\n ...(xAxis ? { xAxis } : {}),\n data,\n activePointIndex: cursor?.index,\n cursorY: cursor?.offsetY,\n interactive: true,\n onPointClick: handlePointClick,\n onPointPointerLeave: handlePointPointerLeave,\n onPointPointerMove: handlePointPointerMove,\n ref: chartRef,\n selectedPointIndex,\n style,\n } as LineChartProps<\"figure\">;\n return <LineChart {...chartProps} />;\n }\n\n const { sliceStart, sliceEnd, contentSize, plotHeight } = liveWindow;\n const slice = data.slice(sliceStart, sliceEnd);\n const { min, max } = getValueBounds(slice);\n const toSliceIndex = (index: number | undefined): number | undefined =>\n index !== undefined && index >= sliceStart && index < sliceEnd ? index - sliceStart : undefined;\n const pointLayer = (\n <VirtualScroll\n height={plotHeight}\n items={liveItems}\n orientation=\"horizontal\"\n overscan={2}\n rowHeight={viewport.itemWidth}\n scrollRef={liveWindow.scrollRef}\n onRangeChange={liveWindow.onRangeChange}\n renderRow={({ point }, index) => {\n // Overscan points stay inert, so focus never scrolls hidden points into view.\n const inSlice = index >= sliceStart && index < sliceEnd;\n const isActive = cursor?.index === index;\n return (\n <LineChartPoint\n as=\"div\"\n point={point}\n previousPoint={data[index - 1]}\n index={index}\n count={data.length}\n min={min}\n max={max}\n interactive={inSlice}\n isActive={isActive}\n isSelected={selectedPointIndex === index}\n cursorY={isActive ? cursor?.offsetY : undefined}\n onPointClick={handlePointClick}\n onPointPointerLeave={handlePointPointerLeave}\n onPointPointerMove={handlePointPointerMove}\n />\n );\n }}\n />\n );\n\n const liveStyle: InteractiveLineStyle = {\n ...style,\n \"--line-content-size\": `${contentSize}px`,\n \"--line-plot-height\": `${plotHeight}px`,\n // One virtual row: the viewport holds `visibleCount` of them.\n \"--line-run\": String(100 / visibleCount),\n };\n const chartProps = {\n ...consumerProps,\n data: slice,\n xAxis: xAxis ?? liveTimeAxis(data, sliceStart, sliceEnd, visibleCount),\n activePointIndex: toSliceIndex(cursor?.index),\n announceReadout: false,\n pointLayer,\n cursorY: cursor?.offsetY,\n interactive: true,\n ref: chartRef,\n selectedPointIndex: toSliceIndex(selectedPointIndex),\n slotCount: data.length,\n slotOffset: sliceStart,\n style: liveStyle,\n } as LineChartProps<\"figure\"> & LineChartViewProps;\n\n return <LineChart {...chartProps} />;\n}\nLineChartClient.displayName = \"LineChartClient\";\n"],"mappings":"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","names":["chartProps"]}
@@ -1,3 +1,3 @@
1
1
  export { LineChartClient } from "./LineChartClient.js";
2
- export type { LineChartAxisLabel, LineChartData, LineChartOwnProps, LineChartPointerPosition, LineChartProps, } from "../types.js";
2
+ export type { LineChartAxisLabel, LineChartClientOwnProps, LineChartClientProps, LineChartData, LineChartOwnProps, LineChartPointerPosition, LineChartProps, } from "../types.js";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/line-chart/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,GACf,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/line-chart/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,GACf,MAAM,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/line-chart/client/index.ts"],"sourcesContent":["export { LineChartClient } from \"./LineChartClient.js\";\nexport type {\n LineChartAxisLabel,\n LineChartData,\n LineChartOwnProps,\n LineChartPointerPosition,\n LineChartProps,\n} from \"../types.js\";\n"],"mappings":"AAAA,SAAS,uBAAuB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/line-chart/client/index.ts"],"sourcesContent":["export { LineChartClient } from \"./LineChartClient.js\";\nexport type {\n LineChartAxisLabel,\n LineChartClientOwnProps,\n LineChartClientProps,\n LineChartData,\n LineChartOwnProps,\n LineChartPointerPosition,\n LineChartProps,\n} from \"../types.js\";\n"],"mappings":"AAAA,SAAS,uBAAuB;","names":[]}
@@ -3,6 +3,7 @@ import type { LineChartAxisLabel, LineChartData } from "./types.js";
3
3
  export interface PointStyle extends CSSProperties {
4
4
  "--line-prev-x"?: string;
5
5
  "--line-prev-y"?: string;
6
+ "--line-rise"?: string;
6
7
  "--line-slot": string;
7
8
  "--line-x": string;
8
9
  "--line-y": string;
@@ -10,6 +11,8 @@ export interface PointStyle extends CSSProperties {
10
11
  }
11
12
  export interface PointsStyle extends CSSProperties {
12
13
  "--line-count": string;
14
+ /** One segment's width in percentage points of the viewport width, unitless. */
15
+ "--line-run": string;
13
16
  "--line-segment-slot": string;
14
17
  }
15
18
  export interface CrosshairStyle extends CSSProperties {
@@ -27,6 +30,8 @@ type LineTrend = "down" | "flat" | "up";
27
30
  interface LinePointGeometry {
28
31
  readonly previousX: string | undefined;
29
32
  readonly previousY: string | undefined;
33
+ /** `y − previousY` in percentage points of the point box height, unitless. */
34
+ readonly rise: string | undefined;
30
35
  readonly slot: string;
31
36
  readonly trend: LineTrend;
32
37
  readonly x: string;
@@ -47,6 +52,8 @@ export declare function geometryFor(point: LineChartData, previousPoint: LineCha
47
52
  export declare function pointStyle(geometry: LinePointGeometry, cursorY: number | undefined): PointStyle;
48
53
  export declare function pointsStyle(count: number): PointsStyle;
49
54
  export declare function crosshairStyle(index: number, count: number, cursorY: number | undefined): CrosshairStyle;
55
+ /** Crosshair at the center of slot `index` of `count` equal slots (live mode). */
56
+ export declare function slotCrosshairStyle(index: number, count: number, cursorY: number | undefined): CrosshairStyle;
50
57
  export declare function cursorStyle(cursorY: number | undefined): CursorStyle;
51
58
  export declare function axisStyle(axis: "x" | "y", position: number): AxisStyle;
52
59
  export declare function axisLabelsFor(overrides: readonly LineChartAxisLabel[] | undefined, fallback: readonly AxisLabel[]): readonly AxisLabel[];
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart-geometry.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/line-chart-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,SAAU,SAAQ,aAAa;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAExC,UAAU,iBAAiB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAW3F;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAkBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,EAAE,CAe1E;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAYpE;AAOD,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,EACpB,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,iBAAiB,CAanB;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAS/F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAKtD;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,cAAc,CAKhB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAEpE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAItE;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,EACpD,QAAQ,EAAE,SAAS,SAAS,EAAE,GAC7B,SAAS,SAAS,EAAE,CAEtB"}
1
+ {"version":3,"file":"line-chart-geometry.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/line-chart-geometry.ts"],"names":[],"mappings":"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"}
@@ -66,19 +66,23 @@ function trendFor(value, previousValue) {
66
66
  }
67
67
  function geometryFor(point, previousPoint, index, count, min, max) {
68
68
  const range = max - min;
69
+ const y = valueToPercent(point.value, min, range);
70
+ const previousY = previousPoint === void 0 ? void 0 : valueToPercent(previousPoint.value, min, range);
69
71
  return {
70
72
  previousX: previousPoint === void 0 ? void 0 : percent(pointPosition(index - 1, count)),
71
- previousY: previousPoint === void 0 ? void 0 : percent(valueToPercent(previousPoint.value, min, range)),
73
+ previousY: previousY === void 0 ? void 0 : percent(previousY),
74
+ rise: previousY === void 0 ? void 0 : String(Math.round((y - previousY) * 1e4) / 1e4),
72
75
  slot: percent(count > 1 ? 100 / (count - 1) : 100),
73
76
  trend: trendFor(point.value, previousPoint?.value),
74
77
  x: percent(pointPosition(index, count)),
75
- y: percent(valueToPercent(point.value, min, range))
78
+ y: percent(y)
76
79
  };
77
80
  }
78
81
  function pointStyle(geometry, cursorY) {
79
82
  return {
80
83
  ...geometry.previousX === void 0 ? {} : { "--line-prev-x": geometry.previousX },
81
84
  ...geometry.previousY === void 0 ? {} : { "--line-prev-y": geometry.previousY },
85
+ ...geometry.rise === void 0 ? {} : { "--line-rise": geometry.rise },
82
86
  "--line-slot": geometry.slot,
83
87
  "--line-x": geometry.x,
84
88
  "--line-y": geometry.y,
@@ -88,6 +92,7 @@ function pointStyle(geometry, cursorY) {
88
92
  function pointsStyle(count) {
89
93
  return {
90
94
  "--line-count": String(Math.max(count, 1)),
95
+ "--line-run": String(Math.round((count > 1 ? 100 / (count - 1) : 100) * 1e4) / 1e4),
91
96
  "--line-segment-slot": percent(count > 1 ? 100 / (count - 1) : 100)
92
97
  };
93
98
  }
@@ -97,6 +102,12 @@ function crosshairStyle(index, count, cursorY) {
97
102
  ...cursorY === void 0 ? {} : { "--line-cursor-y": `${Math.max(0, cursorY)}px` }
98
103
  };
99
104
  }
105
+ function slotCrosshairStyle(index, count, cursorY) {
106
+ return {
107
+ "--line-crosshair-x": percent((index + 0.5) / Math.max(count, 1) * 100),
108
+ ...cursorY === void 0 ? {} : { "--line-cursor-y": `${Math.max(0, cursorY)}px` }
109
+ };
110
+ }
100
111
  function cursorStyle(cursorY) {
101
112
  return cursorY === void 0 ? {} : { "--line-cursor-y": `${Math.max(0, cursorY)}px` };
102
113
  }
@@ -119,6 +130,7 @@ export {
119
130
  pointPosition,
120
131
  pointStyle,
121
132
  pointsStyle,
133
+ slotCrosshairStyle,
122
134
  valueLabelsFor
123
135
  };
124
136
  //# sourceMappingURL=line-chart-geometry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/line-chart/line-chart-geometry.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from \"react\";\nimport type { LineChartAxisLabel, LineChartData } from \"./types.js\";\n\nexport interface PointStyle extends CSSProperties {\n \"--line-prev-x\"?: string;\n \"--line-prev-y\"?: string;\n \"--line-slot\": string;\n \"--line-x\": string;\n \"--line-y\": string;\n \"--line-cursor-y\"?: string;\n}\n\nexport interface PointsStyle extends CSSProperties {\n \"--line-count\": string;\n \"--line-segment-slot\": string;\n}\n\nexport interface CrosshairStyle extends CSSProperties {\n \"--line-crosshair-x\": string;\n \"--line-cursor-y\"?: string;\n}\n\nexport interface CursorStyle extends CSSProperties {\n \"--line-cursor-y\"?: string;\n}\n\nexport interface AxisStyle extends CSSProperties {\n \"--line-axis-x\"?: string;\n \"--line-axis-y\"?: string;\n}\n\ntype LineTrend = \"down\" | \"flat\" | \"up\";\n\ninterface LinePointGeometry {\n readonly previousX: string | undefined;\n readonly previousY: string | undefined;\n readonly slot: string;\n readonly trend: LineTrend;\n readonly x: string;\n readonly y: string;\n}\n\nfunction percent(value: number): string {\n const rounded = Math.round(value * 10000) / 10000;\n return `${rounded}%`;\n}\n\nfunction valueToPercent(value: number, min: number, range: number): number {\n if (range === 0) return 50;\n return Math.min(100, Math.max(0, ((min + range - value) / range) * 100));\n}\n\nexport function getValueBounds(data: readonly LineChartData[]): { max: number; min: number } {\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n\n for (const point of data) {\n min = Math.min(min, point.value);\n max = Math.max(max, point.value);\n }\n\n if (data.length === 0) return { max: 1, min: 0 };\n return { max, min };\n}\n\nexport interface AxisLabel {\n readonly label: ReactNode;\n readonly position: number;\n}\n\nfunction monthKey(time: string | number): string {\n const date = new Date(time);\n if (Number.isNaN(date.getTime())) return String(time);\n return `${date.getUTCFullYear()}-${date.getUTCMonth()}`;\n}\n\nfunction monthLabel(time: string | number): string {\n const date = new Date(time);\n if (Number.isNaN(date.getTime())) return String(time);\n return new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n timeZone: \"UTC\",\n year: \"2-digit\",\n }).format(date);\n}\n\nexport function pointPosition(index: number, count: number): number {\n if (count <= 1) return 50;\n return (index / (count - 1)) * 100;\n}\n\nexport function monthLabelsFor(data: readonly LineChartData[]): AxisLabel[] {\n const labels: AxisLabel[] = [];\n const seen = new Set<string>();\n\n data.forEach((point, index) => {\n const key = monthKey(point.time);\n if (seen.has(key)) return;\n seen.add(key);\n labels.push({\n label: monthLabel(point.time),\n position: pointPosition(index, data.length),\n });\n });\n\n return labels;\n}\n\nexport function valueLabelsFor(min: number, max: number): AxisLabel[] {\n const tickCount = 6;\n const range = max - min;\n\n return Array.from({ length: tickCount }, (_, index) => {\n const ratio = index / (tickCount - 1);\n const value = max - range * ratio;\n return {\n label: new Intl.NumberFormat(\"en-US\", { maximumFractionDigits: 2 }).format(value),\n position: ratio * 100,\n };\n });\n}\n\nfunction trendFor(value: number, previousValue: number | undefined): LineTrend {\n if (previousValue === undefined || value === previousValue) return \"flat\";\n return value > previousValue ? \"up\" : \"down\";\n}\n\nexport function geometryFor(\n point: LineChartData,\n previousPoint: LineChartData | undefined,\n index: number,\n count: number,\n min: number,\n max: number,\n): LinePointGeometry {\n const range = max - min;\n return {\n previousX: previousPoint === undefined ? undefined : percent(pointPosition(index - 1, count)),\n previousY:\n previousPoint === undefined\n ? undefined\n : percent(valueToPercent(previousPoint.value, min, range)),\n slot: percent(count > 1 ? 100 / (count - 1) : 100),\n trend: trendFor(point.value, previousPoint?.value),\n x: percent(pointPosition(index, count)),\n y: percent(valueToPercent(point.value, min, range)),\n };\n}\n\nexport function pointStyle(geometry: LinePointGeometry, cursorY: number | undefined): PointStyle {\n return {\n ...(geometry.previousX === undefined ? {} : { \"--line-prev-x\": geometry.previousX }),\n ...(geometry.previousY === undefined ? {} : { \"--line-prev-y\": geometry.previousY }),\n \"--line-slot\": geometry.slot,\n \"--line-x\": geometry.x,\n \"--line-y\": geometry.y,\n ...(cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` }),\n };\n}\n\nexport function pointsStyle(count: number): PointsStyle {\n return {\n \"--line-count\": String(Math.max(count, 1)),\n \"--line-segment-slot\": percent(count > 1 ? 100 / (count - 1) : 100),\n };\n}\n\nexport function crosshairStyle(\n index: number,\n count: number,\n cursorY: number | undefined,\n): CrosshairStyle {\n return {\n \"--line-crosshair-x\": percent(pointPosition(index, count)),\n ...(cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` }),\n };\n}\n\nexport function cursorStyle(cursorY: number | undefined): CursorStyle {\n return cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` };\n}\n\nexport function axisStyle(axis: \"x\" | \"y\", position: number): AxisStyle {\n const value = percent(Math.min(100, Math.max(0, position)));\n if (axis === \"x\") return { \"--line-axis-x\": value };\n return { \"--line-axis-y\": value };\n}\n\nexport function axisLabelsFor(\n overrides: readonly LineChartAxisLabel[] | undefined,\n fallback: readonly AxisLabel[],\n): readonly AxisLabel[] {\n return overrides ?? fallback;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/line-chart/line-chart-geometry.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from \"react\";\nimport type { LineChartAxisLabel, LineChartData } from \"./types.js\";\n\nexport interface PointStyle extends CSSProperties {\n \"--line-prev-x\"?: string;\n \"--line-prev-y\"?: string;\n \"--line-rise\"?: string;\n \"--line-slot\": string;\n \"--line-x\": string;\n \"--line-y\": string;\n \"--line-cursor-y\"?: string;\n}\n\nexport interface PointsStyle extends CSSProperties {\n \"--line-count\": string;\n /** One segment's width in percentage points of the viewport width, unitless. */\n \"--line-run\": string;\n \"--line-segment-slot\": string;\n}\n\nexport interface CrosshairStyle extends CSSProperties {\n \"--line-crosshair-x\": string;\n \"--line-cursor-y\"?: string;\n}\n\nexport interface CursorStyle extends CSSProperties {\n \"--line-cursor-y\"?: string;\n}\n\nexport interface AxisStyle extends CSSProperties {\n \"--line-axis-x\"?: string;\n \"--line-axis-y\"?: string;\n}\n\ntype LineTrend = \"down\" | \"flat\" | \"up\";\n\ninterface LinePointGeometry {\n readonly previousX: string | undefined;\n readonly previousY: string | undefined;\n /** `y − previousY` in percentage points of the point box height, unitless. */\n readonly rise: string | undefined;\n readonly slot: string;\n readonly trend: LineTrend;\n readonly x: string;\n readonly y: string;\n}\n\nfunction percent(value: number): string {\n const rounded = Math.round(value * 10000) / 10000;\n return `${rounded}%`;\n}\n\nfunction valueToPercent(value: number, min: number, range: number): number {\n if (range === 0) return 50;\n return Math.min(100, Math.max(0, ((min + range - value) / range) * 100));\n}\n\nexport function getValueBounds(data: readonly LineChartData[]): { max: number; min: number } {\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n\n for (const point of data) {\n min = Math.min(min, point.value);\n max = Math.max(max, point.value);\n }\n\n if (data.length === 0) return { max: 1, min: 0 };\n return { max, min };\n}\n\nexport interface AxisLabel {\n readonly label: ReactNode;\n readonly position: number;\n}\n\nfunction monthKey(time: string | number): string {\n const date = new Date(time);\n if (Number.isNaN(date.getTime())) return String(time);\n return `${date.getUTCFullYear()}-${date.getUTCMonth()}`;\n}\n\nfunction monthLabel(time: string | number): string {\n const date = new Date(time);\n if (Number.isNaN(date.getTime())) return String(time);\n return new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n timeZone: \"UTC\",\n year: \"2-digit\",\n }).format(date);\n}\n\nexport function pointPosition(index: number, count: number): number {\n if (count <= 1) return 50;\n return (index / (count - 1)) * 100;\n}\n\nexport function monthLabelsFor(data: readonly LineChartData[]): AxisLabel[] {\n const labels: AxisLabel[] = [];\n const seen = new Set<string>();\n\n data.forEach((point, index) => {\n const key = monthKey(point.time);\n if (seen.has(key)) return;\n seen.add(key);\n labels.push({\n label: monthLabel(point.time),\n position: pointPosition(index, data.length),\n });\n });\n\n return labels;\n}\n\nexport function valueLabelsFor(min: number, max: number): AxisLabel[] {\n const tickCount = 6;\n const range = max - min;\n\n return Array.from({ length: tickCount }, (_, index) => {\n const ratio = index / (tickCount - 1);\n const value = max - range * ratio;\n return {\n label: new Intl.NumberFormat(\"en-US\", { maximumFractionDigits: 2 }).format(value),\n position: ratio * 100,\n };\n });\n}\n\nfunction trendFor(value: number, previousValue: number | undefined): LineTrend {\n if (previousValue === undefined || value === previousValue) return \"flat\";\n return value > previousValue ? \"up\" : \"down\";\n}\n\nexport function geometryFor(\n point: LineChartData,\n previousPoint: LineChartData | undefined,\n index: number,\n count: number,\n min: number,\n max: number,\n): LinePointGeometry {\n const range = max - min;\n const y = valueToPercent(point.value, min, range);\n const previousY =\n previousPoint === undefined ? undefined : valueToPercent(previousPoint.value, min, range);\n return {\n previousX: previousPoint === undefined ? undefined : percent(pointPosition(index - 1, count)),\n previousY: previousY === undefined ? undefined : percent(previousY),\n rise: previousY === undefined ? undefined : String(Math.round((y - previousY) * 10000) / 10000),\n slot: percent(count > 1 ? 100 / (count - 1) : 100),\n trend: trendFor(point.value, previousPoint?.value),\n x: percent(pointPosition(index, count)),\n y: percent(y),\n };\n}\n\nexport function pointStyle(geometry: LinePointGeometry, cursorY: number | undefined): PointStyle {\n return {\n ...(geometry.previousX === undefined ? {} : { \"--line-prev-x\": geometry.previousX }),\n ...(geometry.previousY === undefined ? {} : { \"--line-prev-y\": geometry.previousY }),\n ...(geometry.rise === undefined ? {} : { \"--line-rise\": geometry.rise }),\n \"--line-slot\": geometry.slot,\n \"--line-x\": geometry.x,\n \"--line-y\": geometry.y,\n ...(cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` }),\n };\n}\n\nexport function pointsStyle(count: number): PointsStyle {\n return {\n \"--line-count\": String(Math.max(count, 1)),\n \"--line-run\": String(Math.round((count > 1 ? 100 / (count - 1) : 100) * 10000) / 10000),\n \"--line-segment-slot\": percent(count > 1 ? 100 / (count - 1) : 100),\n };\n}\n\nexport function crosshairStyle(\n index: number,\n count: number,\n cursorY: number | undefined,\n): CrosshairStyle {\n return {\n \"--line-crosshair-x\": percent(pointPosition(index, count)),\n ...(cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` }),\n };\n}\n\n/** Crosshair at the center of slot `index` of `count` equal slots (live mode). */\nexport function slotCrosshairStyle(\n index: number,\n count: number,\n cursorY: number | undefined,\n): CrosshairStyle {\n return {\n \"--line-crosshair-x\": percent(((index + 0.5) / Math.max(count, 1)) * 100),\n ...(cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` }),\n };\n}\n\nexport function cursorStyle(cursorY: number | undefined): CursorStyle {\n return cursorY === undefined ? {} : { \"--line-cursor-y\": `${Math.max(0, cursorY)}px` };\n}\n\nexport function axisStyle(axis: \"x\" | \"y\", position: number): AxisStyle {\n const value = percent(Math.min(100, Math.max(0, position)));\n if (axis === \"x\") return { \"--line-axis-x\": value };\n return { \"--line-axis-y\": value };\n}\n\nexport function axisLabelsFor(\n overrides: readonly LineChartAxisLabel[] | undefined,\n fallback: readonly AxisLabel[],\n): readonly AxisLabel[] {\n return overrides ?? fallback;\n}\n"],"mappings":"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","names":[]}
@@ -28,4 +28,46 @@ export interface LineChartOwnProps {
28
28
  readonly yAxis?: readonly LineChartAxisLabel[];
29
29
  }
30
30
  export type LineChartProps<TAs extends ElementType = "figure"> = RenderableProps<TAs, LineChartOwnProps, Record<string, never>, HTMLElement>;
31
+ export interface LineChartClientOwnProps extends LineChartOwnProps {
32
+ /**
33
+ * Live mode: sizes point slots so `visibleCount` fill the viewport and
34
+ * virtualizes the full history with a horizontal VirtualScroll. The chart
35
+ * follows new points while the reader is at the newest one; the value scale,
36
+ * axes, readout, and data table follow the visible points. Zoom is disabled.
37
+ */
38
+ readonly visibleCount?: number;
39
+ }
40
+ export type LineChartClientProps<TAs extends ElementType = "figure"> = RenderableProps<TAs, LineChartClientOwnProps, Record<string, never>, HTMLElement>;
41
+ /** Internal props the client entry passes to `LineChart`; not part of the public API. */
42
+ export interface LineChartViewProps extends LineChartOwnProps {
43
+ /** Replaces the static point list (e.g. with a virtualized layer). */
44
+ readonly pointLayer?: ReactNode;
45
+ /** Announce readout changes; off for streaming data. Defaults to `true`. */
46
+ readonly announceReadout?: boolean;
47
+ /**
48
+ * Point slots across the content. When set, the crosshair sits at slot
49
+ * centers — `(slotOffset + index + 0.5) / slotCount` — instead of spreading
50
+ * `data` edge to edge.
51
+ */
52
+ readonly slotCount?: number;
53
+ /** Slot of `data[0]` when `data` is a slice. Defaults to `0`. */
54
+ readonly slotOffset?: number;
55
+ }
56
+ export interface LineChartPointProps {
57
+ readonly as: "div" | "li";
58
+ readonly point: LineChartData;
59
+ readonly previousPoint: LineChartData | undefined;
60
+ /** Index reported to the pointer and click callbacks, and used for x in the static list. */
61
+ readonly index: number;
62
+ readonly count: number;
63
+ readonly min: number;
64
+ readonly max: number;
65
+ readonly interactive: boolean;
66
+ readonly isActive: boolean;
67
+ readonly isSelected: boolean;
68
+ readonly cursorY?: number | undefined;
69
+ readonly onPointClick?: ((index: number) => void) | undefined;
70
+ readonly onPointPointerLeave?: (() => void) | undefined;
71
+ readonly onPointPointerMove?: ((position: LineChartPointerPosition) => void) | undefined;
72
+ }
31
73
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,IAAI,eAAe,CAC9E,GAAG,EACH,iBAAiB,EACjB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACrB,WAAW,CACZ,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../src/components/number-field/NumberField.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,WAAW,EAGhB,KAAK,YAAY,EAGlB,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAEV,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,eAAe,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC7D,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAC/B,YAAY,GAAG,IAAI,CAgIrB;yBAlIe,eAAe;;;AAqI/B,wBAAgB,gBAAgB,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC9D,KAAK,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAChC,YAAY,GAAG,IAAI,CAWrB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,SAAS,WAAW,GAAG,OAAO,EAChE,KAAK,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAChC,YAAY,GAAG,IAAI,CAsFrB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EACrE,KAAK,EAAE,yBAAyB,CAAC,GAAG,CAAC,GACpC,YAAY,GAAG,IAAI,CAiCrB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EACrE,KAAK,EAAE,yBAAyB,CAAC,GAAG,CAAC,GACpC,YAAY,GAAG,IAAI,CAiCrB;AAED,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAC"}
1
+ {"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../src/components/number-field/NumberField.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,WAAW,EAGhB,KAAK,YAAY,EAGlB,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAEV,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,eAAe,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC7D,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAC/B,YAAY,GAAG,IAAI,CAoIrB;yBAtIe,eAAe;;;AAyI/B,wBAAgB,gBAAgB,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC9D,KAAK,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAChC,YAAY,GAAG,IAAI,CAWrB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,SAAS,WAAW,GAAG,OAAO,EAChE,KAAK,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAChC,YAAY,GAAG,IAAI,CAsFrB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EACrE,KAAK,EAAE,yBAAyB,CAAC,GAAG,CAAC,GACpC,YAAY,GAAG,IAAI,CAiCrB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EACrE,KAAK,EAAE,yBAAyB,CAAC,GAAG,CAAC,GACpC,YAAY,GAAG,IAAI,CAiCrB;AAED,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAC"}
@@ -122,7 +122,11 @@ function NumberFieldRoot(props) {
122
122
  const element = useRenderElement({
123
123
  as,
124
124
  defaultTag: "div",
125
- props: { ...consumerProps, "data-disabled": disabled ? "" : void 0 },
125
+ props: {
126
+ ...consumerProps,
127
+ "data-disabled": disabled ? "" : void 0,
128
+ "data-uiify-number-field": ""
129
+ },
126
130
  render,
127
131
  state: { disabled, readOnly, required }
128
132
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/number-field/NumberField.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ElementType,\n type FocusEvent,\n type KeyboardEvent,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from \"react\";\nimport { useControllableState, useId } from \"@gunkin/uiify/hooks\";\nimport { createPartContext } from \"@gunkin/uiify/core\";\nimport { composeEventHandlers } from \"@gunkin/uiify/core/compose-event-handlers\";\nimport { useRenderElement, type PolymorphicProps } from \"@gunkin/uiify/core/render\";\nimport { clampNumber, createFormatter, formatNumber, parseNumber, stepNumber } from \"./format.js\";\nimport { usePressRepeat } from \"./use-press-repeat.js\";\nimport type {\n NumberFieldContextValue,\n NumberFieldRootProps,\n NumberFieldGroupProps,\n NumberFieldInputProps,\n NumberFieldIncrementProps,\n NumberFieldDecrementProps,\n} from \"./types.js\";\n\nexport type {\n NumberFieldDecrementProps,\n NumberFieldGroupProps,\n NumberFieldIncrementProps,\n NumberFieldInputProps,\n NumberFieldRootOwnProps,\n NumberFieldRootProps,\n} from \"./types.js\";\n\nconst [NumberFieldProvider, useNumberFieldContext] =\n createPartContext<NumberFieldContextValue>(\"NumberField\");\n\nexport function NumberFieldRoot<TAs extends ElementType = \"div\">(\n props: NumberFieldRootProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n value: controlledValue,\n defaultValue,\n onChange,\n min,\n max,\n step = 1,\n formatOptions,\n clampValueOnBlur = true,\n disabled = false,\n readOnly = false,\n required = false,\n ...consumerProps\n } = props as NumberFieldRootProps<ElementType>;\n\n const inputId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const formatter = useMemo(() => createFormatter(formatOptions), [formatOptions]);\n const [value, setValue] = useControllableState<number | undefined>({\n value: controlledValue,\n defaultValue,\n onChange,\n });\n const [editing, setEditing] = useState(false);\n const [displayValue, setDisplayValue] = useState(() =>\n value === undefined ? \"\" : formatNumber(value, formatter),\n );\n\n const syncDisplay = useCallback(\n (next: number | undefined) => {\n setDisplayValue(next === undefined ? \"\" : formatNumber(next, formatter));\n },\n [formatter],\n );\n\n const applyValue = useCallback(\n (next: number | undefined) => {\n const clamped =\n next === undefined ? undefined : clampValueOnBlur ? clampNumber(next, min, max) : next;\n setValue(clamped);\n syncDisplay(clamped);\n },\n [clampValueOnBlur, max, min, setValue, syncDisplay],\n );\n\n const increment = useCallback(\n (multiplier = 1) => {\n if (disabled || readOnly) return;\n const base = value ?? min ?? 0;\n applyValue(stepNumber(base, multiplier, step, min, max));\n },\n [applyValue, disabled, max, min, readOnly, step, value],\n );\n\n const decrement = useCallback(\n (multiplier = 1) => {\n increment(-multiplier);\n },\n [increment],\n );\n\n const commitInput = useCallback(\n (raw: string) => {\n const parsed = parseNumber(raw, formatter);\n if (parsed === undefined) {\n syncDisplay(value);\n return;\n }\n applyValue(parsed);\n },\n [applyValue, formatter, syncDisplay, value],\n );\n\n const contextValue = useMemo<NumberFieldContextValue>(\n () => ({\n clampValueOnBlur,\n commitInput,\n decrement,\n disabled,\n displayValue: editing\n ? displayValue\n : value === undefined\n ? \"\"\n : formatNumber(value, formatter),\n formatter,\n increment,\n inputId,\n inputRef,\n max,\n min,\n numericValue: value,\n readOnly,\n required,\n setDisplayValue,\n setEditing,\n step,\n }),\n [\n clampValueOnBlur,\n commitInput,\n decrement,\n disabled,\n displayValue,\n editing,\n formatter,\n increment,\n inputId,\n max,\n min,\n readOnly,\n required,\n step,\n value,\n ],\n );\n\n const element = useRenderElement({\n as,\n defaultTag: \"div\",\n props: { ...consumerProps, \"data-disabled\": disabled ? \"\" : undefined },\n render,\n state: { disabled, readOnly, required },\n });\n\n return <NumberFieldProvider value={contextValue}>{element}</NumberFieldProvider>;\n}\nNumberFieldRoot.displayName = \"NumberFieldRoot\";\n\nexport function NumberFieldGroup<TAs extends ElementType = \"div\">(\n props: NumberFieldGroupProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as NumberFieldGroupProps<ElementType>;\n const { disabled } = useNumberFieldContext(\"Group\");\n\n return useRenderElement({\n as,\n defaultTag: \"div\",\n props: { ...consumerProps, \"data-disabled\": disabled ? \"\" : undefined },\n render,\n state: { disabled },\n });\n}\n\nexport function NumberFieldInput<TAs extends ElementType = \"input\">(\n props: NumberFieldInputProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as NumberFieldInputProps<\"input\">;\n const {\n commitInput,\n decrement,\n disabled,\n displayValue,\n increment,\n inputId,\n inputRef,\n max,\n min,\n numericValue,\n readOnly,\n required,\n setDisplayValue,\n setEditing,\n } = useNumberFieldContext(\"Input\");\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (disabled || readOnly) return;\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n increment();\n break;\n case \"ArrowDown\":\n event.preventDefault();\n decrement();\n break;\n case \"PageUp\":\n event.preventDefault();\n increment(10);\n break;\n case \"PageDown\":\n event.preventDefault();\n decrement(10);\n break;\n case \"Home\":\n event.preventDefault();\n if (min !== undefined) commitInput(String(min));\n break;\n case \"End\":\n event.preventDefault();\n if (max !== undefined) commitInput(String(max));\n break;\n default:\n break;\n }\n };\n\n return useRenderElement({\n as,\n defaultTag: \"input\",\n props: {\n ...consumerProps,\n id: inputId,\n ref: inputRef,\n role: \"spinbutton\",\n inputMode: \"decimal\",\n \"aria-valuenow\": numericValue,\n \"aria-valuemin\": min,\n \"aria-valuemax\": max,\n \"aria-required\": required || undefined,\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-readonly\": readOnly ? \"\" : undefined,\n disabled: disabled || undefined,\n readOnly: readOnly || undefined,\n required: required || undefined,\n value: displayValue,\n onFocus: composeEventHandlers(consumerProps.onFocus, () => setEditing(true)),\n onBlur: composeEventHandlers(consumerProps.onBlur, (event: FocusEvent<HTMLInputElement>) => {\n setEditing(false);\n commitInput(event.currentTarget.value);\n }),\n onChange: composeEventHandlers(\n consumerProps.onChange,\n (event: SyntheticEvent<HTMLInputElement>) => {\n setDisplayValue(event.currentTarget.value);\n },\n ),\n onKeyDown: composeEventHandlers(consumerProps.onKeyDown, onKeyDown),\n },\n render,\n state: { disabled, readOnly, required },\n });\n}\n\nexport function NumberFieldIncrement<TAs extends ElementType = \"button\">(\n props: NumberFieldIncrementProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as PolymorphicProps<\n \"button\",\n { readonly children?: ReactNode }\n >;\n const { disabled, increment, readOnly } = useNumberFieldContext(\"Increment\");\n const inactive = disabled || readOnly;\n const repeatProps = usePressRepeat(() => increment(), inactive);\n\n return useRenderElement({\n as,\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n type: \"button\",\n tabIndex: -1,\n \"data-disabled\": inactive ? \"\" : undefined,\n disabled: inactive || undefined,\n onClick: composeEventHandlers(consumerProps.onClick, () => increment()),\n onPointerDown: composeEventHandlers(consumerProps.onPointerDown, repeatProps.onPointerDown),\n onPointerUp: composeEventHandlers(consumerProps.onPointerUp, repeatProps.onPointerUp),\n onPointerLeave: composeEventHandlers(\n consumerProps.onPointerLeave,\n repeatProps.onPointerLeave,\n ),\n onPointerCancel: composeEventHandlers(\n consumerProps.onPointerCancel,\n repeatProps.onPointerCancel,\n ),\n },\n render,\n state: { disabled: inactive },\n });\n}\n\nexport function NumberFieldDecrement<TAs extends ElementType = \"button\">(\n props: NumberFieldDecrementProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as PolymorphicProps<\n \"button\",\n { readonly children?: ReactNode }\n >;\n const { decrement, disabled, readOnly } = useNumberFieldContext(\"Decrement\");\n const inactive = disabled || readOnly;\n const repeatProps = usePressRepeat(() => decrement(), inactive);\n\n return useRenderElement({\n as,\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n type: \"button\",\n tabIndex: -1,\n \"data-disabled\": inactive ? \"\" : undefined,\n disabled: inactive || undefined,\n onClick: composeEventHandlers(consumerProps.onClick, () => decrement()),\n onPointerDown: composeEventHandlers(consumerProps.onPointerDown, repeatProps.onPointerDown),\n onPointerUp: composeEventHandlers(consumerProps.onPointerUp, repeatProps.onPointerUp),\n onPointerLeave: composeEventHandlers(\n consumerProps.onPointerLeave,\n repeatProps.onPointerLeave,\n ),\n onPointerCancel: composeEventHandlers(\n consumerProps.onPointerCancel,\n repeatProps.onPointerCancel,\n ),\n },\n render,\n state: { disabled: inactive },\n });\n}\n\nexport const NumberField = {\n Root: NumberFieldRoot,\n Group: NumberFieldGroup,\n Input: NumberFieldInput,\n Increment: NumberFieldIncrement,\n Decrement: NumberFieldDecrement,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/number-field/NumberField.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ElementType,\n type FocusEvent,\n type KeyboardEvent,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from \"react\";\nimport { useControllableState, useId } from \"@gunkin/uiify/hooks\";\nimport { createPartContext } from \"@gunkin/uiify/core\";\nimport { composeEventHandlers } from \"@gunkin/uiify/core/compose-event-handlers\";\nimport { useRenderElement, type PolymorphicProps } from \"@gunkin/uiify/core/render\";\nimport { clampNumber, createFormatter, formatNumber, parseNumber, stepNumber } from \"./format.js\";\nimport { usePressRepeat } from \"./use-press-repeat.js\";\nimport type {\n NumberFieldContextValue,\n NumberFieldRootProps,\n NumberFieldGroupProps,\n NumberFieldInputProps,\n NumberFieldIncrementProps,\n NumberFieldDecrementProps,\n} from \"./types.js\";\n\nexport type {\n NumberFieldDecrementProps,\n NumberFieldGroupProps,\n NumberFieldIncrementProps,\n NumberFieldInputProps,\n NumberFieldRootOwnProps,\n NumberFieldRootProps,\n} from \"./types.js\";\n\nconst [NumberFieldProvider, useNumberFieldContext] =\n createPartContext<NumberFieldContextValue>(\"NumberField\");\n\nexport function NumberFieldRoot<TAs extends ElementType = \"div\">(\n props: NumberFieldRootProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n value: controlledValue,\n defaultValue,\n onChange,\n min,\n max,\n step = 1,\n formatOptions,\n clampValueOnBlur = true,\n disabled = false,\n readOnly = false,\n required = false,\n ...consumerProps\n } = props as NumberFieldRootProps<ElementType>;\n\n const inputId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const formatter = useMemo(() => createFormatter(formatOptions), [formatOptions]);\n const [value, setValue] = useControllableState<number | undefined>({\n value: controlledValue,\n defaultValue,\n onChange,\n });\n const [editing, setEditing] = useState(false);\n const [displayValue, setDisplayValue] = useState(() =>\n value === undefined ? \"\" : formatNumber(value, formatter),\n );\n\n const syncDisplay = useCallback(\n (next: number | undefined) => {\n setDisplayValue(next === undefined ? \"\" : formatNumber(next, formatter));\n },\n [formatter],\n );\n\n const applyValue = useCallback(\n (next: number | undefined) => {\n const clamped =\n next === undefined ? undefined : clampValueOnBlur ? clampNumber(next, min, max) : next;\n setValue(clamped);\n syncDisplay(clamped);\n },\n [clampValueOnBlur, max, min, setValue, syncDisplay],\n );\n\n const increment = useCallback(\n (multiplier = 1) => {\n if (disabled || readOnly) return;\n const base = value ?? min ?? 0;\n applyValue(stepNumber(base, multiplier, step, min, max));\n },\n [applyValue, disabled, max, min, readOnly, step, value],\n );\n\n const decrement = useCallback(\n (multiplier = 1) => {\n increment(-multiplier);\n },\n [increment],\n );\n\n const commitInput = useCallback(\n (raw: string) => {\n const parsed = parseNumber(raw, formatter);\n if (parsed === undefined) {\n syncDisplay(value);\n return;\n }\n applyValue(parsed);\n },\n [applyValue, formatter, syncDisplay, value],\n );\n\n const contextValue = useMemo<NumberFieldContextValue>(\n () => ({\n clampValueOnBlur,\n commitInput,\n decrement,\n disabled,\n displayValue: editing\n ? displayValue\n : value === undefined\n ? \"\"\n : formatNumber(value, formatter),\n formatter,\n increment,\n inputId,\n inputRef,\n max,\n min,\n numericValue: value,\n readOnly,\n required,\n setDisplayValue,\n setEditing,\n step,\n }),\n [\n clampValueOnBlur,\n commitInput,\n decrement,\n disabled,\n displayValue,\n editing,\n formatter,\n increment,\n inputId,\n max,\n min,\n readOnly,\n required,\n step,\n value,\n ],\n );\n\n const element = useRenderElement({\n as,\n defaultTag: \"div\",\n props: {\n ...consumerProps,\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-uiify-number-field\": \"\",\n },\n render,\n state: { disabled, readOnly, required },\n });\n\n return <NumberFieldProvider value={contextValue}>{element}</NumberFieldProvider>;\n}\nNumberFieldRoot.displayName = \"NumberFieldRoot\";\n\nexport function NumberFieldGroup<TAs extends ElementType = \"div\">(\n props: NumberFieldGroupProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as NumberFieldGroupProps<ElementType>;\n const { disabled } = useNumberFieldContext(\"Group\");\n\n return useRenderElement({\n as,\n defaultTag: \"div\",\n props: { ...consumerProps, \"data-disabled\": disabled ? \"\" : undefined },\n render,\n state: { disabled },\n });\n}\n\nexport function NumberFieldInput<TAs extends ElementType = \"input\">(\n props: NumberFieldInputProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as NumberFieldInputProps<\"input\">;\n const {\n commitInput,\n decrement,\n disabled,\n displayValue,\n increment,\n inputId,\n inputRef,\n max,\n min,\n numericValue,\n readOnly,\n required,\n setDisplayValue,\n setEditing,\n } = useNumberFieldContext(\"Input\");\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (disabled || readOnly) return;\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n increment();\n break;\n case \"ArrowDown\":\n event.preventDefault();\n decrement();\n break;\n case \"PageUp\":\n event.preventDefault();\n increment(10);\n break;\n case \"PageDown\":\n event.preventDefault();\n decrement(10);\n break;\n case \"Home\":\n event.preventDefault();\n if (min !== undefined) commitInput(String(min));\n break;\n case \"End\":\n event.preventDefault();\n if (max !== undefined) commitInput(String(max));\n break;\n default:\n break;\n }\n };\n\n return useRenderElement({\n as,\n defaultTag: \"input\",\n props: {\n ...consumerProps,\n id: inputId,\n ref: inputRef,\n role: \"spinbutton\",\n inputMode: \"decimal\",\n \"aria-valuenow\": numericValue,\n \"aria-valuemin\": min,\n \"aria-valuemax\": max,\n \"aria-required\": required || undefined,\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-readonly\": readOnly ? \"\" : undefined,\n disabled: disabled || undefined,\n readOnly: readOnly || undefined,\n required: required || undefined,\n value: displayValue,\n onFocus: composeEventHandlers(consumerProps.onFocus, () => setEditing(true)),\n onBlur: composeEventHandlers(consumerProps.onBlur, (event: FocusEvent<HTMLInputElement>) => {\n setEditing(false);\n commitInput(event.currentTarget.value);\n }),\n onChange: composeEventHandlers(\n consumerProps.onChange,\n (event: SyntheticEvent<HTMLInputElement>) => {\n setDisplayValue(event.currentTarget.value);\n },\n ),\n onKeyDown: composeEventHandlers(consumerProps.onKeyDown, onKeyDown),\n },\n render,\n state: { disabled, readOnly, required },\n });\n}\n\nexport function NumberFieldIncrement<TAs extends ElementType = \"button\">(\n props: NumberFieldIncrementProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as PolymorphicProps<\n \"button\",\n { readonly children?: ReactNode }\n >;\n const { disabled, increment, readOnly } = useNumberFieldContext(\"Increment\");\n const inactive = disabled || readOnly;\n const repeatProps = usePressRepeat(() => increment(), inactive);\n\n return useRenderElement({\n as,\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n type: \"button\",\n tabIndex: -1,\n \"data-disabled\": inactive ? \"\" : undefined,\n disabled: inactive || undefined,\n onClick: composeEventHandlers(consumerProps.onClick, () => increment()),\n onPointerDown: composeEventHandlers(consumerProps.onPointerDown, repeatProps.onPointerDown),\n onPointerUp: composeEventHandlers(consumerProps.onPointerUp, repeatProps.onPointerUp),\n onPointerLeave: composeEventHandlers(\n consumerProps.onPointerLeave,\n repeatProps.onPointerLeave,\n ),\n onPointerCancel: composeEventHandlers(\n consumerProps.onPointerCancel,\n repeatProps.onPointerCancel,\n ),\n },\n render,\n state: { disabled: inactive },\n });\n}\n\nexport function NumberFieldDecrement<TAs extends ElementType = \"button\">(\n props: NumberFieldDecrementProps<TAs>,\n): ReactElement | null {\n const { as, render, ...consumerProps } = props as PolymorphicProps<\n \"button\",\n { readonly children?: ReactNode }\n >;\n const { decrement, disabled, readOnly } = useNumberFieldContext(\"Decrement\");\n const inactive = disabled || readOnly;\n const repeatProps = usePressRepeat(() => decrement(), inactive);\n\n return useRenderElement({\n as,\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n type: \"button\",\n tabIndex: -1,\n \"data-disabled\": inactive ? \"\" : undefined,\n disabled: inactive || undefined,\n onClick: composeEventHandlers(consumerProps.onClick, () => decrement()),\n onPointerDown: composeEventHandlers(consumerProps.onPointerDown, repeatProps.onPointerDown),\n onPointerUp: composeEventHandlers(consumerProps.onPointerUp, repeatProps.onPointerUp),\n onPointerLeave: composeEventHandlers(\n consumerProps.onPointerLeave,\n repeatProps.onPointerLeave,\n ),\n onPointerCancel: composeEventHandlers(\n consumerProps.onPointerCancel,\n repeatProps.onPointerCancel,\n ),\n },\n render,\n state: { disabled: inactive },\n });\n}\n\nexport const NumberField = {\n Root: NumberFieldRoot,\n Group: NumberFieldGroup,\n Input: NumberFieldInput,\n Increment: NumberFieldIncrement,\n Decrement: NumberFieldDecrement,\n};\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../src/components/slider/Slider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,OAAO,CAAC;AAGvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,MAAM,CAAC,GAAG,SAAS,WAAW,GAAG,OAAO,EACtD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,GACtB,YAAY,GAAG,IAAI,CA6CrB"}
1
+ {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../src/components/slider/Slider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAkB,MAAM,OAAO,CAAC;AAGtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO9C,wBAAgB,MAAM,CAAC,GAAG,SAAS,WAAW,GAAG,OAAO,EACtD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,GACtB,YAAY,GAAG,IAAI,CAwDrB"}
@@ -1,5 +1,9 @@
1
1
  import { composeEventHandlers } from "@gunkin/uiify/core/compose-event-handlers";
2
2
  import { useRenderElement } from "@gunkin/uiify/core/render";
3
+ function getProgressPercentage(value, min, max) {
4
+ if (max <= min) return 0;
5
+ return Number(Math.min(100, Math.max(0, (value - min) / (max - min) * 100)).toFixed(4));
6
+ }
3
7
  function Slider(props) {
4
8
  const {
5
9
  as,
@@ -14,7 +18,17 @@ function Slider(props) {
14
18
  ...consumerProps
15
19
  } = props;
16
20
  const isControlled = value !== void 0;
21
+ const progressValue = value ?? defaultValue ?? min + (max - min) / 2;
22
+ const progress = getProgressPercentage(progressValue, min, max);
23
+ const style = {
24
+ ...consumerProps.style,
25
+ "--uiify-slider-progress": `${progress}%`
26
+ };
17
27
  const handleChange = (event) => {
28
+ if (!isControlled) {
29
+ const nextProgress = getProgressPercentage(event.currentTarget.valueAsNumber, min, max);
30
+ event.currentTarget.style.setProperty("--uiify-slider-progress", `${nextProgress}%`);
31
+ }
18
32
  onValueChange?.(event.currentTarget.valueAsNumber);
19
33
  };
20
34
  const consumerOnChange = consumerProps.onChange;
@@ -23,6 +37,7 @@ function Slider(props) {
23
37
  defaultTag: "input",
24
38
  props: {
25
39
  ...consumerProps,
40
+ style,
26
41
  type: "range",
27
42
  "data-uiify-slider": "",
28
43
  min,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/slider/Slider.tsx"],"sourcesContent":["import type { ElementType, ReactElement, SyntheticEvent } from \"react\";\nimport { composeEventHandlers } from \"@gunkin/uiify/core/compose-event-handlers\";\nimport { useRenderElement } from \"@gunkin/uiify/core/render\";\nimport type { SliderProps } from \"./types.js\";\n\nexport function Slider<TAs extends ElementType = \"input\">(\n props: SliderProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n value,\n defaultValue,\n onValueChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n ...consumerProps\n } = props as SliderProps<\"input\">;\n\n const isControlled = value !== undefined;\n\n const handleChange = (event: SyntheticEvent<HTMLInputElement>): void => {\n onValueChange?.(event.currentTarget.valueAsNumber);\n };\n\n const consumerOnChange = (\n consumerProps as Record<string, unknown> & {\n onChange?: (event: SyntheticEvent<HTMLInputElement>) => void;\n }\n ).onChange;\n\n return useRenderElement({\n as,\n defaultTag: \"input\",\n props: {\n ...consumerProps,\n type: \"range\",\n \"data-uiify-slider\": \"\",\n min,\n max,\n step,\n disabled: disabled || undefined,\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-state\": isControlled ? String(value) : undefined,\n onChange: composeEventHandlers(consumerOnChange, handleChange),\n ...(isControlled ? { value } : defaultValue !== undefined ? { defaultValue } : {}),\n },\n render,\n state: { min, max, step, disabled },\n });\n}\n"],"mappings":"AACA,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAG1B,SAAS,OACd,OACqB;AACrB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,eAAe,UAAU;AAE/B,QAAM,eAAe,CAAC,UAAkD;AACtE,oBAAgB,MAAM,cAAc,aAAa;AAAA,EACnD;AAEA,QAAM,mBACJ,cAGA;AAEF,SAAO,iBAAiB;AAAA,IACtB;AAAA,IACA,YAAY;AAAA,IACZ,OAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN,qBAAqB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,YAAY;AAAA,MACtB,iBAAiB,WAAW,KAAK;AAAA,MACjC,cAAc,eAAe,OAAO,KAAK,IAAI;AAAA,MAC7C,UAAU,qBAAqB,kBAAkB,YAAY;AAAA,MAC7D,GAAI,eAAe,EAAE,MAAM,IAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IAClF;AAAA,IACA;AAAA,IACA,OAAO,EAAE,KAAK,KAAK,MAAM,SAAS;AAAA,EACpC,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/slider/Slider.tsx"],"sourcesContent":["import type { CSSProperties, ElementType, ReactElement, SyntheticEvent } from \"react\";\nimport { composeEventHandlers } from \"@gunkin/uiify/core/compose-event-handlers\";\nimport { useRenderElement } from \"@gunkin/uiify/core/render\";\nimport type { SliderProps } from \"./types.js\";\n\nfunction getProgressPercentage(value: number, min: number, max: number): number {\n if (max <= min) return 0;\n return Number(Math.min(100, Math.max(0, ((value - min) / (max - min)) * 100)).toFixed(4));\n}\n\nexport function Slider<TAs extends ElementType = \"input\">(\n props: SliderProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n value,\n defaultValue,\n onValueChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n ...consumerProps\n } = props as SliderProps<\"input\">;\n\n const isControlled = value !== undefined;\n const progressValue = value ?? defaultValue ?? min + (max - min) / 2;\n const progress = getProgressPercentage(progressValue, min, max);\n const style = {\n ...(consumerProps as { style?: CSSProperties }).style,\n \"--uiify-slider-progress\": `${progress}%`,\n } as CSSProperties;\n\n const handleChange = (event: SyntheticEvent<HTMLInputElement>): void => {\n if (!isControlled) {\n const nextProgress = getProgressPercentage(event.currentTarget.valueAsNumber, min, max);\n event.currentTarget.style.setProperty(\"--uiify-slider-progress\", `${nextProgress}%`);\n }\n onValueChange?.(event.currentTarget.valueAsNumber);\n };\n\n const consumerOnChange = (\n consumerProps as Record<string, unknown> & {\n onChange?: (event: SyntheticEvent<HTMLInputElement>) => void;\n }\n ).onChange;\n\n return useRenderElement({\n as,\n defaultTag: \"input\",\n props: {\n ...consumerProps,\n style,\n type: \"range\",\n \"data-uiify-slider\": \"\",\n min,\n max,\n step,\n disabled: disabled || undefined,\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-state\": isControlled ? String(value) : undefined,\n onChange: composeEventHandlers(consumerOnChange, handleChange),\n ...(isControlled ? { value } : defaultValue !== undefined ? { defaultValue } : {}),\n },\n render,\n state: { min, max, step, disabled },\n });\n}\n"],"mappings":"AACA,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB,OAAe,KAAa,KAAqB;AAC9E,MAAI,OAAO,IAAK,QAAO;AACvB,SAAO,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,IAAK,QAAQ,QAAQ,MAAM,OAAQ,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC1F;AAEO,SAAS,OACd,OACqB;AACrB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,eAAe,UAAU;AAC/B,QAAM,gBAAgB,SAAS,gBAAgB,OAAO,MAAM,OAAO;AACnE,QAAM,WAAW,sBAAsB,eAAe,KAAK,GAAG;AAC9D,QAAM,QAAQ;AAAA,IACZ,GAAI,cAA4C;AAAA,IAChD,2BAA2B,GAAG,QAAQ;AAAA,EACxC;AAEA,QAAM,eAAe,CAAC,UAAkD;AACtE,QAAI,CAAC,cAAc;AACjB,YAAM,eAAe,sBAAsB,MAAM,cAAc,eAAe,KAAK,GAAG;AACtF,YAAM,cAAc,MAAM,YAAY,2BAA2B,GAAG,YAAY,GAAG;AAAA,IACrF;AACA,oBAAgB,MAAM,cAAc,aAAa;AAAA,EACnD;AAEA,QAAM,mBACJ,cAGA;AAEF,SAAO,iBAAiB;AAAA,IACtB;AAAA,IACA,YAAY;AAAA,IACZ,OAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,MAAM;AAAA,MACN,qBAAqB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,YAAY;AAAA,MACtB,iBAAiB,WAAW,KAAK;AAAA,MACjC,cAAc,eAAe,OAAO,KAAK,IAAI;AAAA,MAC7C,UAAU,qBAAqB,kBAAkB,YAAY;AAAA,MAC7D,GAAI,eAAe,EAAE,MAAM,IAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IAClF;AAAA,IACA;AAAA,IACA,OAAO,EAAE,KAAK,KAAK,MAAM,SAAS;AAAA,EACpC,CAAC;AACH;","names":[]}
@@ -0,0 +1,7 @@
1
+ import type { ElementType, ReactElement } from "react";
2
+ import type { SliderClientProps } from "../types.js";
3
+ export declare function SliderClient<TAs extends ElementType = "div">(props: SliderClientProps<TAs>): ReactElement | null;
4
+ export declare namespace SliderClient {
5
+ var displayName: string;
6
+ }
7
+ //# sourceMappingURL=SliderClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliderClient.d.ts","sourceRoot":"","sources":["../../../../src/components/slider/client/SliderClient.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,WAAW,EAEX,YAAY,EAEb,MAAM,OAAO,CAAC;AAMf,OAAO,KAAK,EAAE,iBAAiB,EAAiC,MAAM,aAAa,CAAC;AA+CpF,wBAAgB,YAAY,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC1D,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAC5B,YAAY,GAAG,IAAI,CA4KrB;yBA9Ke,YAAY"}