@rojaostudio/ds 2.0.0-next.6 → 2.0.0-next.7

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.
@@ -10,7 +10,7 @@ interface ChartSeries {
10
10
  /** line only: which axis it reads on. right only when the two series have different units (volume and rate). */
11
11
  axis?: 'left' | 'right';
12
12
  }
13
- interface ChartProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
13
+ interface ChartProps extends Omit<HTMLAttributes<HTMLElement>, 'children' | 'onSelect'> {
14
14
  /** What the chart shows, with the period. It names the chart and captions its data table. */
15
15
  label: string;
16
16
  /** line: lines over time; bar: a ranking in horizontal bars; column: columns by category. */
@@ -32,8 +32,22 @@ interface ChartProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
32
32
  showLegend?: boolean;
33
33
  /** The values of the point under the pointer or the keyboard (Figma: `showTooltip`). */
34
34
  showTooltip?: boolean;
35
- /** Off: only the first, middle and last label (Figma: `showAllDates`). Use it under about 360 px. */
35
+ /**
36
+ * line and column: which x labels show (Figma: `dates`). edges, the default: the first, middle and last; all: every
37
+ * label, for short series only.
38
+ */
39
+ dates?: 'edges' | 'all';
40
+ /** line and column: one label every N points, with a tick on every point (Figma: `dates=every`). Wins over `dates`. */
41
+ dateEvery?: number;
42
+ /** @deprecated Use `dates="all"` (true) or `dates="edges"` (false). */
36
43
  showAllDates?: boolean;
44
+ /**
45
+ * bar and column: where each item leads, in the order of `labels`. In bar each bar becomes a link named
46
+ * "<label>: <value>"; in column a click or Enter on the plot follows the item's link.
47
+ */
48
+ hrefs?: Array<string | undefined>;
49
+ /** bar and column: called with the item's index when it is chosen (click, Enter). In bar each bar becomes a button. */
50
+ onSelect?: (index: number) => void;
37
51
  /** Show the data table under the chart. By default it is there only for screen readers. */
38
52
  showTable?: boolean;
39
53
  /** Height of the plot area, in px (Figma: 200). */
@@ -44,6 +58,6 @@ interface ChartProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
44
58
  * data (visually hidden unless `showTable`). In line and column the plot is a slider for screen readers and the
45
59
  * keyboard: the arrows move from point to point, and each point is read with its label and values. Styles: chart.css.
46
60
  */
47
- declare function Chart({ label, type, labels, series, formatLeft, formatRight, showRightAxis, showLegend, showTooltip, showAllDates, showTable, height, className, ...rest }: ChartProps): react.JSX.Element;
61
+ declare function Chart({ label, type, labels, series, formatLeft, formatRight, showRightAxis, showLegend, showTooltip, dates, dateEvery, showAllDates, hrefs, onSelect, showTable, height, className, ...rest }: ChartProps): react.JSX.Element;
48
62
 
49
63
  export { Chart, type ChartProps, type ChartSeries, type ChartType };
@@ -36,7 +36,11 @@ function Chart(_a) {
36
36
  showRightAxis = true,
37
37
  showLegend = true,
38
38
  showTooltip = true,
39
- showAllDates = true,
39
+ dates,
40
+ dateEvery,
41
+ showAllDates,
42
+ hrefs,
43
+ onSelect,
40
44
  showTable = false,
41
45
  height = 200,
42
46
  className
@@ -50,7 +54,11 @@ function Chart(_a) {
50
54
  "showRightAxis",
51
55
  "showLegend",
52
56
  "showTooltip",
57
+ "dates",
58
+ "dateEvery",
53
59
  "showAllDates",
60
+ "hrefs",
61
+ "onSelect",
54
62
  "showTable",
55
63
  "height",
56
64
  "className"
@@ -78,7 +86,14 @@ function Chart(_a) {
78
86
  return `${s.name} ${formatFor(s)((_a3 = s.data[index]) != null ? _a3 : 0)}`;
79
87
  }).join(", ");
80
88
  const legendName = (s) => dual ? `${s.name} (${onRight(s) ? "direita" : "esquerda"})` : s.name;
81
- const labelIndexes = showAllDates || count <= 3 ? labels.map((_, i) => i) : [0, Math.floor((count - 1) / 2), count - 1];
89
+ const every = dateEvery && dateEvery > 1 ? Math.floor(dateEvery) : null;
90
+ const allDates = (dates != null ? dates : showAllDates === void 0 ? "edges" : showAllDates ? "all" : "edges") === "all";
91
+ const labelIndexes = every ? labels.map((_, i) => i).filter((i) => i % every === 0) : allDates || count <= 3 ? labels.map((_, i) => i) : [0, Math.floor((count - 1) / 2), count - 1];
92
+ const linked = type !== "line" && Boolean(onSelect || (hrefs == null ? void 0 : hrefs.some(Boolean)));
93
+ const choose = (index) => {
94
+ if (onSelect) onSelect(index);
95
+ else if (hrefs == null ? void 0 : hrefs[index]) window.location.assign(hrefs[index]);
96
+ };
82
97
  const onPointerMove = (event) => {
83
98
  const box = event.currentTarget.getBoundingClientRect();
84
99
  const ratio = Math.min(1, Math.max(0, (event.clientX - box.left) / box.width));
@@ -94,6 +109,11 @@ function Chart(_a) {
94
109
  Home: 0,
95
110
  End: count - 1
96
111
  };
112
+ if (linked && event.key === "Enter" && active !== null) {
113
+ event.preventDefault();
114
+ choose(active);
115
+ return;
116
+ }
97
117
  if (!(event.key in keys)) return;
98
118
  event.preventDefault();
99
119
  setActive(keys[event.key]);
@@ -133,6 +153,7 @@ function Chart(_a) {
133
153
  onPointerLeave: (event) => {
134
154
  if (document.activeElement !== event.currentTarget) setActive(null);
135
155
  },
156
+ onClick: linked ? () => active !== null && choose(active) : void 0,
136
157
  onFocus: () => setActive((current) => current != null ? current : 0),
137
158
  onBlur: () => setActive(null),
138
159
  onKeyDown
@@ -142,19 +163,37 @@ function Chart(_a) {
142
163
  if (type === "bar") {
143
164
  const s = shown[0];
144
165
  const top = Math.max(0, ...(_a2 = s == null ? void 0 : s.data) != null ? _a2 : [0]);
145
- body = /* @__PURE__ */ jsx("div", { className: "rds-chart__bars", "aria-hidden": "true", children: labels.map((name, i) => {
166
+ body = /* @__PURE__ */ jsx("div", { className: "rds-chart__bars", "aria-hidden": linked ? void 0 : true, children: labels.map((name, i) => {
146
167
  var _a3, _b2;
147
- return /* @__PURE__ */ jsxs("div", { className: "rds-chart__bar-row", children: [
168
+ const value = s ? formatLeft((_a3 = s.data[i]) != null ? _a3 : 0) : "";
169
+ const parts = /* @__PURE__ */ jsxs(Fragment, { children: [
148
170
  /* @__PURE__ */ jsx("span", { className: "rds-chart__bar-label", children: name }),
149
171
  /* @__PURE__ */ jsx("span", { className: "rds-chart__track", children: /* @__PURE__ */ jsx(
150
172
  "span",
151
173
  {
152
174
  className: "rds-chart__bar",
153
- style: __spreadProps(__spreadValues({}, seriesStyle(i + 1)), { width: `${top ? ((_a3 = s == null ? void 0 : s.data[i]) != null ? _a3 : 0) / top * 100 : 0}%` })
175
+ style: __spreadProps(__spreadValues({}, seriesStyle(i + 1)), { width: `${top ? ((_b2 = s == null ? void 0 : s.data[i]) != null ? _b2 : 0) / top * 100 : 0}%` })
154
176
  }
155
177
  ) }),
156
- /* @__PURE__ */ jsx("span", { className: "rds-chart__bar-value", children: s ? formatLeft((_b2 = s.data[i]) != null ? _b2 : 0) : "" })
157
- ] }, name);
178
+ /* @__PURE__ */ jsx("span", { className: "rds-chart__bar-value", children: value })
179
+ ] });
180
+ const href = hrefs == null ? void 0 : hrefs[i];
181
+ const accessibleName = `${name}: ${value}`;
182
+ if (linked && href && !onSelect)
183
+ return /* @__PURE__ */ jsx("a", { href, className: "rds-chart__bar-row rds-chart__bar-row--link", "aria-label": accessibleName, children: parts }, name);
184
+ if (linked && onSelect)
185
+ return /* @__PURE__ */ jsx(
186
+ "button",
187
+ {
188
+ type: "button",
189
+ className: "rds-chart__bar-row rds-chart__bar-row--link",
190
+ "aria-label": accessibleName,
191
+ onClick: () => onSelect(i),
192
+ children: parts
193
+ },
194
+ name
195
+ );
196
+ return /* @__PURE__ */ jsx("div", { className: "rds-chart__bar-row", children: parts }, name);
158
197
  }) });
159
198
  } else {
160
199
  body = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -208,7 +247,10 @@ function Chart(_a) {
208
247
  ] })),
209
248
  rightScale && /* @__PURE__ */ jsx(Axis, { ticks: rightScale.ticks, format: formatRight, side: "right" })
210
249
  ] }),
211
- /* @__PURE__ */ jsx("div", { className: "rds-chart__labels", "aria-hidden": "true", children: /* @__PURE__ */ jsx("div", { className: `rds-chart__labels-track rds-chart__labels-track--${type}`, children: labelIndexes.map((i) => /* @__PURE__ */ jsx("span", { className: "rds-chart__label", style: { left: `${x(i)}%` }, children: labels[i] }, i)) }) })
250
+ /* @__PURE__ */ jsx("div", { className: "rds-chart__labels", "aria-hidden": "true", children: /* @__PURE__ */ jsxs("div", { className: `rds-chart__labels-track rds-chart__labels-track--${type}${every ? " rds-chart__labels-track--ticks" : ""}`, children: [
251
+ every && labels.map((_, i) => /* @__PURE__ */ jsx("i", { className: "rds-chart__tick", style: { left: `${x(i)}%` } }, `t${i}`)),
252
+ labelIndexes.map((i) => /* @__PURE__ */ jsx("span", { className: "rds-chart__label", style: { left: `${x(i)}%` }, children: labels[i] }, i))
253
+ ] }) })
212
254
  ] });
213
255
  }
214
256
  const firstColumn = type === "line" ? "Data" : "Categoria";
@@ -216,7 +258,7 @@ function Chart(_a) {
216
258
  "figure",
217
259
  __spreadProps(__spreadValues({}, rest), {
218
260
  "aria-label": label,
219
- className: ["rds-chart", `rds-chart--${type}`, dual && "rds-chart--dual", className].filter(Boolean).join(" "),
261
+ className: ["rds-chart", `rds-chart--${type}`, dual && "rds-chart--dual", linked && "rds-chart--linked", className].filter(Boolean).join(" "),
220
262
  children: [
221
263
  body,
222
264
  showLegend && type !== "bar" && /* @__PURE__ */ jsx("ul", { className: "rds-chart__legend", "aria-hidden": "true", children: shown.map((s, n) => /* @__PURE__ */ jsxs("li", { children: [
@@ -229,7 +271,7 @@ function Chart(_a) {
229
271
  shown.map((s) => /* @__PURE__ */ jsx(TableHead, { align: "end", children: legendName(s) }, s.name))
230
272
  ] }) }),
231
273
  /* @__PURE__ */ jsx(TableBody, { children: labels.map((name, i) => /* @__PURE__ */ jsxs(TableRow, { children: [
232
- /* @__PURE__ */ jsx(TableCell, { children: name }),
274
+ /* @__PURE__ */ jsx(TableCell, { children: linked && onSelect ? /* @__PURE__ */ jsx("button", { type: "button", className: "rds-chart__table-link", onClick: () => onSelect(i), children: name }) : linked && (hrefs == null ? void 0 : hrefs[i]) ? /* @__PURE__ */ jsx("a", { className: "rds-chart__table-link", href: hrefs[i], children: name }) : name }),
233
275
  shown.map((s) => {
234
276
  var _a3;
235
277
  return /* @__PURE__ */ jsx(TableCell, { align: "end", children: formatFor(s)((_a3 = s.data[i]) != null ? _a3 : 0) }, s.name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rojaostudio/ds",
3
- "version": "2.0.0-next.6",
3
+ "version": "2.0.0-next.7",
4
4
  "type": "module",
5
5
  "description": "Rojão Design System — componentes React, estilos e alvo React Native. O motor vive em @rojaostudio/ds-core.",
6
6
  "license": "MIT",
@@ -190,7 +190,7 @@
190
190
  "@radix-ui/react-toggle": "^1.1.18",
191
191
  "@radix-ui/react-toggle-group": "^1.1.19",
192
192
  "@radix-ui/react-tooltip": "^1.2.16",
193
- "@rojaostudio/ds-core": "1.1.0-next.2"
193
+ "@rojaostudio/ds-core": "1.1.0-next.3"
194
194
  },
195
195
  "scripts": {
196
196
  "build": "pnpm run build:tokens && pnpm run build:themes && pnpm run build:rds && pnpm run build:native && tsup",
@@ -2182,14 +2182,31 @@ button.rds-breadcrumb__link:focus-visible {
2182
2182
  white-space: nowrap;
2183
2183
  }
2184
2184
 
2185
- .rds-chart__labels-track--line .rds-chart__label:first-child {
2185
+ .rds-chart__labels-track--line .rds-chart__label:first-of-type {
2186
2186
  transform: none;
2187
2187
  }
2188
2188
 
2189
- .rds-chart__labels-track--line .rds-chart__label:last-child {
2189
+ .rds-chart__labels-track--line .rds-chart__label:last-of-type {
2190
2190
  transform: translateX(-100%);
2191
2191
  }
2192
2192
 
2193
+ /* dateEvery: a 1x4 tick on every point, the labels under them. */
2194
+ .rds-chart__labels-track--ticks {
2195
+ height: calc(var(--type-caption-line) + var(--space-4));
2196
+ }
2197
+
2198
+ .rds-chart__labels-track--ticks .rds-chart__label {
2199
+ top: var(--space-4);
2200
+ }
2201
+
2202
+ .rds-chart__tick {
2203
+ position: absolute;
2204
+ top: 0;
2205
+ width: 1px;
2206
+ height: var(--space-4);
2207
+ background: var(--chart-tick);
2208
+ }
2209
+
2193
2210
  /* Bars: label, track, value. */
2194
2211
  .rds-chart__bars {
2195
2212
  display: flex;
@@ -2220,6 +2237,50 @@ button.rds-breadcrumb__link:focus-visible {
2220
2237
  background: var(--_series);
2221
2238
  }
2222
2239
 
2240
+ /* A bar with a destination (hrefs or onSelect): the row is the link or button. */
2241
+ .rds-chart__bar-row--link {
2242
+ box-sizing: border-box;
2243
+ width: 100%;
2244
+ margin: 0;
2245
+ padding: 0;
2246
+ border: 0;
2247
+ border-radius: var(--radius-focus);
2248
+ background: none;
2249
+ color: inherit;
2250
+ font: inherit;
2251
+ text-align: start;
2252
+ text-decoration: none;
2253
+ cursor: pointer;
2254
+ }
2255
+
2256
+ .rds-chart__bar-row--link:hover .rds-chart__track {
2257
+ background: var(--chart-bar-hover);
2258
+ }
2259
+
2260
+ .rds-chart__bar-row--link:hover .rds-chart__bar-label {
2261
+ text-decoration: underline;
2262
+ }
2263
+
2264
+ .rds-chart__bar-row--link:focus-visible,
2265
+ .rds-chart__table-link:focus-visible {
2266
+ outline: var(--focus-ring-width) solid var(--chart-focus-ring);
2267
+ outline-offset: var(--focus-ring-width);
2268
+ }
2269
+
2270
+ .rds-chart--linked.rds-chart--column .rds-chart__plot {
2271
+ cursor: pointer;
2272
+ }
2273
+
2274
+ .rds-chart__table-link {
2275
+ padding: 0;
2276
+ border: 0;
2277
+ background: none;
2278
+ color: inherit;
2279
+ font: inherit;
2280
+ text-decoration: underline;
2281
+ cursor: pointer;
2282
+ }
2283
+
2223
2284
  .rds-chart__bar-value {
2224
2285
  color: var(--chart-axis);
2225
2286
  font-variant-numeric: tabular-nums;
@@ -2253,7 +2314,8 @@ button.rds-breadcrumb__link:focus-visible {
2253
2314
  background: CanvasText;
2254
2315
  }
2255
2316
 
2256
- .rds-chart__plot:focus-visible {
2317
+ .rds-chart__plot:focus-visible,
2318
+ .rds-chart__bar-row--link:focus-visible {
2257
2319
  outline-color: Highlight;
2258
2320
  }
2259
2321
  }
@@ -292,6 +292,9 @@
292
292
  --chart-tooltip-border: var(--border-default);
293
293
  --chart-label: var(--text-body);
294
294
  --chart-tooltip-title: var(--text-heading);
295
+ --chart-bar-hover: var(--surface-muted);
296
+ --chart-focus-ring: var(--focus-ring);
297
+ --chart-tick: var(--border-strong);
295
298
  --carousel-slide-background: var(--surface-muted);
296
299
  --carousel-dot: var(--border-strong);
297
300
  --carousel-dot-active: var(--colors-primary-default);