wiki-formant 0.44.1 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -770,10 +770,11 @@ needs installed.
770
770
  `TimeChart` (`wiki-formant/chart`) is every time-series chart on the four sites:
771
771
  token prices, ledger activity, a caper's price, visitors per day. One area
772
772
  series in the box's own `color`, its axis in `--chart-axis` if set, with range
773
- buttons — 24H, 7D, 30D, 90D, 1Y, All — and, on a range long enough, a day, week
774
- or month step. A step is offered once it makes four points, and the default is
775
- the finest that makes 200 or fewer, so a year opens weekly and five years
776
- monthly.
773
+ buttons — 24H, 7D, 30D, 90D, 1Y, All — then, after a rule, the day, week and
774
+ month steps. The steps show wherever a range is drawn by day, so the buttons
775
+ never shift; one is enabled once it makes four points (none under 24H and 7D,
776
+ which are drawn by the hour and the four hours), and the default is the finest
777
+ that makes 200 or fewer, so a year opens weekly and five years monthly.
777
778
 
778
779
  ```tsx
779
780
  // Daily points: the chart slices and steps them itself; 30D up.
@@ -799,7 +800,8 @@ straight between closes and a count's is curved.
799
800
  as a collapse. A single range draws no range buttons and shows every point.
800
801
  `bucketChart` and `chartSteps` are exported for a chart drawn elsewhere.
801
802
  `base.css` pins the buttons (`.chart-controls button[aria-pressed]`) to the
802
- canvas's top-left corner; the site's stylesheet gives them and the box a look.
803
+ canvas's top-left corner, rules a line between groups and dims a disabled step;
804
+ the site's stylesheet gives them and the box a look.
803
805
 
804
806
  ## Base stylesheet
805
807
 
package/dist/base.css CHANGED
@@ -190,11 +190,15 @@ pre:hover > .code-copy-btn,
190
190
  gap: 0.5rem;
191
191
  }
192
192
  .chart-controls > div { display: flex; gap: 2px; }
193
+ /* A rule between groups: ranges, then steps, then the candles switch. */
194
+ .chart-controls > * + * { border-inline-start: 1px solid color-mix(in srgb, currentColor 25%, transparent); padding-inline-start: 0.5rem; }
193
195
  .chart-controls :is(button, a) { font: inherit; color: inherit; text-decoration: none; background: none; cursor: pointer; opacity: 0.6; }
194
196
  /* An icon sits on the text's line, so an icon button is as tall as a labelled one. */
195
197
  .chart-icon { display: inline-block; width: 1em; height: 1em; vertical-align: -0.125em; }
196
198
  /* A button is pressed; a link (a stats page's window) is the page shown. */
197
199
  .chart-controls :is(button, a):is([aria-pressed='true'], [aria-current]) { opacity: 1; }
200
+ /* A step the range cannot make stays in its place, and dims. */
201
+ .chart-controls button:disabled { opacity: 0.3; cursor: default; pointer-events: none; }
198
202
 
199
203
  /* ---- Stats ----------------------------------------------------------------
200
204
  `--share` is a row's value over the largest in its list, 0 to 1. Bars take
package/dist/chart.js CHANGED
@@ -24,12 +24,13 @@ const STEP = {
24
24
  week: { label: 'W', span: 7 * DAY },
25
25
  month: { label: 'M', span: 30.44 * DAY },
26
26
  };
27
+ const STEPS = ['day', 'week', 'month'];
27
28
  /** Every range, shortest first. A chart fed daily points offers the ones from 30D up. */
28
29
  export const CHART_RANGES = ['24h', '7d', '30d', '90d', '1y', 'all'];
29
30
  const DAILY_RANGES = ['30d', '90d', '1y', 'all'];
30
31
  /** A step is offered once it makes four points, and the default is the finest that makes 200 or fewer. */
31
32
  export function chartSteps(span) {
32
- const steps = ['day', 'week', 'month'].filter(s => s === 'day' || span / STEP[s].span >= 4);
33
+ const steps = STEPS.filter(s => s === 'day' || span / STEP[s].span >= 4);
33
34
  return { steps, fallback: steps.find(s => span / STEP[s].span <= 200) ?? steps.at(-1) };
34
35
  }
35
36
  /** The UTC day, Monday or first of the month a time falls in. */
@@ -260,6 +261,9 @@ export function TimeChart({ series, label, ranges = typeof series === 'function'
260
261
  }));
261
262
  c.api.timeScale().fitContent();
262
263
  }, [ready, source, view, candles]);
264
+ // The steps always show where a range is drawn by day, so the buttons do not jump about; one
265
+ // the range cannot make (any, under 24H and 7D) is disabled.
266
+ const daily = ranges.some(r => RANGE[r].resolution === 'day');
263
267
  const status = source && 'error' in source ? source.error : points && !view?.shown.length ? 'No data in this range' : null;
264
- return (_jsxs("figure", { className: className ? `chart ${className}` : 'chart', children: [_jsx("div", { ref: box, className: "chart-canvas", role: "img", "aria-label": label, style: height ? { height } : undefined }), (!ready || (!points && !status)) && _jsx("div", { className: "chart-status skeleton", "aria-hidden": true }), status && _jsx("p", { className: "chart-status", children: status }), (controls || ranges.length > 1 || (view && (view.steps.length > 1 || view.ohlc))) && (_jsxs("div", { className: "chart-controls", children: [controls, ranges.length > 1 && (_jsx("div", { role: "group", "aria-label": "Range", children: ranges.map(r => (_jsx("button", { type: "button", "aria-pressed": r === range, onClick: () => { setRange(r); setStep(null); }, children: RANGE[r].label }, r))) })), view && view.steps.length > 1 && (_jsx("div", { role: "group", "aria-label": "Step", children: view.steps.map(s => (_jsx("button", { type: "button", "aria-pressed": s === view.step, onClick: () => setStep(s), title: `One point per ${s}`, children: STEP[s].label }, s))) })), view?.ohlc && (_jsx("div", { children: _jsx("button", { type: "button", "aria-pressed": candles, "aria-label": "Candles", title: "Candles", onClick: () => setCandles(c => !c), children: _jsxs("svg", { className: "chart-icon", viewBox: "0 0 12 12", "aria-hidden": true, children: [_jsx("path", { d: "M3.5 1v2M3.5 9v2M8.5 2v3M8.5 9v1", stroke: "currentColor" }), _jsx("rect", { x: "2", y: "3", width: "3", height: "6", rx: "0.5", fill: "currentColor" }), _jsx("rect", { x: "7", y: "5", width: "3", height: "4", rx: "0.5", fill: "currentColor" })] }) }) }))] }))] }));
268
+ return (_jsxs("figure", { className: className ? `chart ${className}` : 'chart', children: [_jsx("div", { ref: box, className: "chart-canvas", role: "img", "aria-label": label, style: height ? { height } : undefined }), (!ready || (!points && !status)) && _jsx("div", { className: "chart-status skeleton", "aria-hidden": true }), status && _jsx("p", { className: "chart-status", children: status }), (controls || ranges.length > 1 || daily || view?.ohlc) && (_jsxs("div", { className: "chart-controls", children: [controls, ranges.length > 1 && (_jsx("div", { role: "group", "aria-label": "Range", children: ranges.map(r => (_jsx("button", { type: "button", "aria-pressed": r === range, onClick: () => { setRange(r); setStep(null); }, children: RANGE[r].label }, r))) })), daily && (_jsx("div", { role: "group", "aria-label": "Step", children: STEPS.map(s => (_jsx("button", { type: "button", "aria-pressed": s === view?.step, disabled: !view?.steps.includes(s), onClick: () => setStep(s), title: `One point per ${s}`, children: STEP[s].label }, s))) })), view?.ohlc && (_jsx("div", { children: _jsx("button", { type: "button", "aria-pressed": candles, "aria-label": "Candles", title: "Candles", onClick: () => setCandles(c => !c), children: _jsxs("svg", { className: "chart-icon", viewBox: "0 0 12 12", "aria-hidden": true, children: [_jsx("path", { d: "M3.5 1v2M3.5 9v2M8.5 2v3M8.5 9v1", stroke: "currentColor" }), _jsx("rect", { x: "2", y: "3", width: "3", height: "6", rx: "0.5", fill: "currentColor" }), _jsx("rect", { x: "7", y: "5", width: "3", height: "4", rx: "0.5", fill: "currentColor" })] }) }) }))] }))] }));
265
269
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-formant",
3
- "version": "0.44.1",
3
+ "version": "0.45.0",
4
4
  "description": "The portable half of a wiki: derived taxonomy and facet controls, a version-negotiating MCP transport, markdown twins, block rendering, a rich-text editor engine, conditional-GET plumbing, and the headers and CSP every origin sends.",
5
5
  "type": "module",
6
6
  "license": "MIT",