@hashsome/ui 0.1.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/LICENSE +674 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/entities/action-button.d.ts +17 -0
- package/dist/entities/action-button.js +56 -0
- package/dist/entities/action-button.js.map +1 -0
- package/dist/entities/artwork-ring.d.ts +17 -0
- package/dist/entities/artwork-ring.js +89 -0
- package/dist/entities/artwork-ring.js.map +1 -0
- package/dist/entities/climate-tile.d.ts +20 -0
- package/dist/entities/climate-tile.js +98 -0
- package/dist/entities/climate-tile.js.map +1 -0
- package/dist/entities/light-color.d.ts +52 -0
- package/dist/entities/light-color.js +148 -0
- package/dist/entities/light-color.js.map +1 -0
- package/dist/entities/light-tile.d.ts +24 -0
- package/dist/entities/light-tile.js +139 -0
- package/dist/entities/light-tile.js.map +1 -0
- package/dist/entities/media-browser.d.ts +15 -0
- package/dist/entities/media-browser.js +67 -0
- package/dist/entities/media-browser.js.map +1 -0
- package/dist/entities/media-controls.d.ts +20 -0
- package/dist/entities/media-controls.js +53 -0
- package/dist/entities/media-controls.js.map +1 -0
- package/dist/entities/media-player-bar.d.ts +14 -0
- package/dist/entities/media-player-bar.js +78 -0
- package/dist/entities/media-player-bar.js.map +1 -0
- package/dist/entities/media-player-body.d.ts +16 -0
- package/dist/entities/media-player-body.js +18 -0
- package/dist/entities/media-player-body.js.map +1 -0
- package/dist/entities/media-player-column.d.ts +18 -0
- package/dist/entities/media-player-column.js +34 -0
- package/dist/entities/media-player-column.js.map +1 -0
- package/dist/entities/media-player-page.d.ts +12 -0
- package/dist/entities/media-player-page.js +13 -0
- package/dist/entities/media-player-page.js.map +1 -0
- package/dist/entities/media-progress.d.ts +7 -0
- package/dist/entities/media-progress.js +30 -0
- package/dist/entities/media-progress.js.map +1 -0
- package/dist/entities/media-seek.d.ts +9 -0
- package/dist/entities/media-seek.js +19 -0
- package/dist/entities/media-seek.js.map +1 -0
- package/dist/entities/nav-dock.d.ts +13 -0
- package/dist/entities/nav-dock.js +22 -0
- package/dist/entities/nav-dock.js.map +1 -0
- package/dist/entities/nav-rail.d.ts +19 -0
- package/dist/entities/nav-rail.js +18 -0
- package/dist/entities/nav-rail.js.map +1 -0
- package/dist/entities/now-playing.d.ts +20 -0
- package/dist/entities/now-playing.js +34 -0
- package/dist/entities/now-playing.js.map +1 -0
- package/dist/entities/scene-button.d.ts +13 -0
- package/dist/entities/scene-button.js +6 -0
- package/dist/entities/scene-button.js.map +1 -0
- package/dist/entities/seek-line.d.ts +9 -0
- package/dist/entities/seek-line.js +71 -0
- package/dist/entities/seek-line.js.map +1 -0
- package/dist/entities/sensor-readout.d.ts +28 -0
- package/dist/entities/sensor-readout.js +95 -0
- package/dist/entities/sensor-readout.js.map +1 -0
- package/dist/entities/top-bar.d.ts +68 -0
- package/dist/entities/top-bar.js +248 -0
- package/dist/entities/top-bar.js.map +1 -0
- package/dist/entity-handle.d.ts +21 -0
- package/dist/entity-handle.js +16 -0
- package/dist/entity-handle.js.map +1 -0
- package/dist/gallery/fixtures.d.ts +4 -0
- package/dist/gallery/fixtures.js +119 -0
- package/dist/gallery/fixtures.js.map +1 -0
- package/dist/gallery/gallery.d.ts +9 -0
- package/dist/gallery/gallery.js +355 -0
- package/dist/gallery/gallery.js.map +1 -0
- package/dist/gallery/index.d.ts +2 -0
- package/dist/gallery/index.js +2 -0
- package/dist/gallery/index.js.map +1 -0
- package/dist/gallery/props-data.d.ts +10 -0
- package/dist/gallery/props-data.js +718 -0
- package/dist/gallery/props-data.js.map +1 -0
- package/dist/hooks.d.ts +19 -0
- package/dist/hooks.js +53 -0
- package/dist/hooks.js.map +1 -0
- package/dist/icon-data.d.ts +6 -0
- package/dist/icon-data.js +59193 -0
- package/dist/icon-data.js.map +1 -0
- package/dist/icon.d.ts +9 -0
- package/dist/icon.js +28 -0
- package/dist/icon.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/cover.d.ts +5 -0
- package/dist/layout/cover.js +8 -0
- package/dist/layout/cover.js.map +1 -0
- package/dist/layout/date-time-field.d.ts +15 -0
- package/dist/layout/date-time-field.js +108 -0
- package/dist/layout/date-time-field.js.map +1 -0
- package/dist/layout/detail-provider.d.ts +22 -0
- package/dist/layout/detail-provider.js +26 -0
- package/dist/layout/detail-provider.js.map +1 -0
- package/dist/layout/drawer-controls.d.ts +46 -0
- package/dist/layout/drawer-controls.js +93 -0
- package/dist/layout/drawer-controls.js.map +1 -0
- package/dist/layout/energy-chart.d.ts +37 -0
- package/dist/layout/energy-chart.js +85 -0
- package/dist/layout/energy-chart.js.map +1 -0
- package/dist/layout/energy-usage.d.ts +6 -0
- package/dist/layout/energy-usage.js +18 -0
- package/dist/layout/energy-usage.js.map +1 -0
- package/dist/layout/entity-drawer.d.ts +15 -0
- package/dist/layout/entity-drawer.js +77 -0
- package/dist/layout/entity-drawer.js.map +1 -0
- package/dist/layout/fade-scroll.d.ts +14 -0
- package/dist/layout/fade-scroll.js +59 -0
- package/dist/layout/fade-scroll.js.map +1 -0
- package/dist/layout/grid.d.ts +9 -0
- package/dist/layout/grid.js +6 -0
- package/dist/layout/grid.js.map +1 -0
- package/dist/layout/history-section.d.ts +19 -0
- package/dist/layout/history-section.js +39 -0
- package/dist/layout/history-section.js.map +1 -0
- package/dist/layout/hold-progress.d.ts +2 -0
- package/dist/layout/hold-progress.js +9 -0
- package/dist/layout/hold-progress.js.map +1 -0
- package/dist/layout/icon-button-styles.d.ts +9 -0
- package/dist/layout/icon-button-styles.js +28 -0
- package/dist/layout/icon-button-styles.js.map +1 -0
- package/dist/layout/page.d.ts +17 -0
- package/dist/layout/page.js +29 -0
- package/dist/layout/page.js.map +1 -0
- package/dist/layout/plain-button.d.ts +11 -0
- package/dist/layout/plain-button.js +17 -0
- package/dist/layout/plain-button.js.map +1 -0
- package/dist/layout/room-header.d.ts +12 -0
- package/dist/layout/room-header.js +11 -0
- package/dist/layout/room-header.js.map +1 -0
- package/dist/layout/round-button.d.ts +13 -0
- package/dist/layout/round-button.js +19 -0
- package/dist/layout/round-button.js.map +1 -0
- package/dist/layout/sensor-history.d.ts +15 -0
- package/dist/layout/sensor-history.js +91 -0
- package/dist/layout/sensor-history.js.map +1 -0
- package/dist/layout/sensor-stats.d.ts +21 -0
- package/dist/layout/sensor-stats.js +79 -0
- package/dist/layout/sensor-stats.js.map +1 -0
- package/dist/layout/series-chart.d.ts +25 -0
- package/dist/layout/series-chart.js +46 -0
- package/dist/layout/series-chart.js.map +1 -0
- package/dist/layout/stepper.d.ts +10 -0
- package/dist/layout/stepper.js +12 -0
- package/dist/layout/stepper.js.map +1 -0
- package/dist/layout/swatch-row.d.ts +19 -0
- package/dist/layout/swatch-row.js +20 -0
- package/dist/layout/swatch-row.js.map +1 -0
- package/dist/layout/tile.d.ts +67 -0
- package/dist/layout/tile.js +207 -0
- package/dist/layout/tile.js.map +1 -0
- package/dist/layout/use-drawer.d.ts +33 -0
- package/dist/layout/use-drawer.js +34 -0
- package/dist/layout/use-drawer.js.map +1 -0
- package/dist/layout/use-hold.d.ts +21 -0
- package/dist/layout/use-hold.js +61 -0
- package/dist/layout/use-hold.js.map +1 -0
- package/dist/provider.d.ts +37 -0
- package/dist/provider.js +95 -0
- package/dist/provider.js.map +1 -0
- package/dist/status.d.ts +8 -0
- package/dist/status.js +27 -0
- package/dist/status.js.map +1 -0
- package/dist/theme/density.d.ts +16 -0
- package/dist/theme/density.js +7 -0
- package/dist/theme/density.js.map +1 -0
- package/dist/theme/global-styles.d.ts +5 -0
- package/dist/theme/global-styles.js +44 -0
- package/dist/theme/global-styles.js.map +1 -0
- package/dist/theme/index.d.ts +19 -0
- package/dist/theme/index.js +106 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/overrides.d.ts +28 -0
- package/dist/theme/overrides.js +24 -0
- package/dist/theme/overrides.js.map +1 -0
- package/dist/theme/tokens.d.ts +78 -0
- package/dist/theme/tokens.js +1 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/theme/use-typography.d.ts +4 -0
- package/dist/theme/use-typography.js +9 -0
- package/dist/theme/use-typography.js.map +1 -0
- package/dist/use-entity-history.d.ts +12 -0
- package/dist/use-entity-history.js +43 -0
- package/dist/use-entity-history.js.map +1 -0
- package/dist/use-media-browser.d.ts +31 -0
- package/dist/use-media-browser.js +87 -0
- package/dist/use-media-browser.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"energy-chart.js","sourceRoot":"","sources":["../../src/layout/energy-chart.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HistoryPoint } from '@hashsome/core';
|
|
2
|
+
import type { EnergyUsage } from './energy-chart.tsx';
|
|
3
|
+
/** Energy used per period from how much a counter grew each day (30 days of daily buckets).
|
|
4
|
+
* Today, this week (from Monday) and this month are calendar periods; the rolling 7 and 30 days
|
|
5
|
+
* include today. */
|
|
6
|
+
export declare function usageFromDaily(points: HistoryPoint[], now: Date): EnergyUsage;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const DAY = 24 * 60 * 60_000;
|
|
2
|
+
const startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
3
|
+
/** Energy used per period from how much a counter grew each day (30 days of daily buckets).
|
|
4
|
+
* Today, this week (from Monday) and this month are calendar periods; the rolling 7 and 30 days
|
|
5
|
+
* include today. */
|
|
6
|
+
export function usageFromDaily(points, now) {
|
|
7
|
+
const today = startOfDay(now).getTime();
|
|
8
|
+
const sumSince = (from) => points.reduce((total, point) => (Date.parse(point.timestamp) >= from ? total + point.value : total), 0);
|
|
9
|
+
const monday = today - ((now.getDay() + 6) % 7) * DAY;
|
|
10
|
+
const month = new Date(now.getFullYear(), now.getMonth(), 1).getTime();
|
|
11
|
+
return {
|
|
12
|
+
today: sumSince(today),
|
|
13
|
+
week: sumSince(monday),
|
|
14
|
+
month: sumSince(month),
|
|
15
|
+
last7d: sumSince(today - 6 * DAY),
|
|
16
|
+
last30d: sumSince(today - 29 * DAY),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"energy-usage.js","sourceRoot":"","sources":["../../src/layout/energy-usage.ts"],"names":[],"mappings":"AAGA,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;AAE7B,MAAM,UAAU,GAAG,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAEjG;;oBAEoB;AACpB,MAAM,UAAU,cAAc,CAAC,MAAsB,EAAE,GAAS;IAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAChC,MAAM,CAAC,MAAM,CACX,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EACrF,CAAC,CACF,CAAC;IAEJ,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACvE,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;QACtB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QACtB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;QACtB,MAAM,EAAE,QAAQ,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QACjC,OAAO,EAAE,QAAQ,CAAC,KAAK,GAAG,EAAE,GAAG,GAAG,CAAC;KACpC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single shared detail drawer, rendered once by `HashsomeProvider`. Floats `EDGE_INSET`px in
|
|
3
|
+
* from the viewport edges (not the triggering tile — it's opened via `Tile`'s `detail` prop and
|
|
4
|
+
* has to fit content far larger than a tile), and can expand to near-fullscreen.
|
|
5
|
+
*
|
|
6
|
+
* The drawer itself only ever sets `width` explicitly (animated) and otherwise stretches to fill
|
|
7
|
+
* its parent — a `position: fixed; inset: 0` wrapper with `padding: EDGE_INSET` and a flex layout
|
|
8
|
+
* that right-aligns it. Deliberately NOT `top`/`right`/`bottom` (or a computed `height`) on the
|
|
9
|
+
* drawer itself: browsers are unreliable at deriving a fixed element's height from opposing
|
|
10
|
+
* insets alone (it can lock to the full viewport height and overflow past the bottom edge,
|
|
11
|
+
* especially on kiosk/tablet WebViews) — `inset: 0` on the wrapper has no such ambiguity (all
|
|
12
|
+
* four sides pinned to 0), and flexbox stretch-sizing the child is a much better-supported path
|
|
13
|
+
* to "fill the available height" than any `top`/`bottom`/`height` arithmetic.
|
|
14
|
+
*/
|
|
15
|
+
export declare function EntityDrawer(): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource @emotion/react */
|
|
3
|
+
import { Flex } from 'e-prim';
|
|
4
|
+
import { AnimatePresence, motion } from 'motion/react';
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
import { Icon } from '../icon.js';
|
|
7
|
+
import { useDetail } from './detail-provider.js';
|
|
8
|
+
const COLLAPSED_WIDTH = 380;
|
|
9
|
+
const EDGE_INSET = 20;
|
|
10
|
+
/**
|
|
11
|
+
* The single shared detail drawer, rendered once by `HashsomeProvider`. Floats `EDGE_INSET`px in
|
|
12
|
+
* from the viewport edges (not the triggering tile — it's opened via `Tile`'s `detail` prop and
|
|
13
|
+
* has to fit content far larger than a tile), and can expand to near-fullscreen.
|
|
14
|
+
*
|
|
15
|
+
* The drawer itself only ever sets `width` explicitly (animated) and otherwise stretches to fill
|
|
16
|
+
* its parent — a `position: fixed; inset: 0` wrapper with `padding: EDGE_INSET` and a flex layout
|
|
17
|
+
* that right-aligns it. Deliberately NOT `top`/`right`/`bottom` (or a computed `height`) on the
|
|
18
|
+
* drawer itself: browsers are unreliable at deriving a fixed element's height from opposing
|
|
19
|
+
* insets alone (it can lock to the full viewport height and overflow past the bottom edge,
|
|
20
|
+
* especially on kiosk/tablet WebViews) — `inset: 0` on the wrapper has no such ambiguity (all
|
|
21
|
+
* four sides pinned to 0), and flexbox stretch-sizing the child is a much better-supported path
|
|
22
|
+
* to "fill the available height" than any `top`/`bottom`/`height` arithmetic.
|
|
23
|
+
*/
|
|
24
|
+
export function EntityDrawer() {
|
|
25
|
+
const { detail, closeDetail, toggleExpanded } = useDetail();
|
|
26
|
+
const [viewportWidth, setViewportWidth] = useState(() => typeof window === 'undefined' ? 0 : window.innerWidth);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!detail) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const onResize = () => setViewportWidth(window.innerWidth);
|
|
32
|
+
onResize();
|
|
33
|
+
window.addEventListener('resize', onResize);
|
|
34
|
+
return () => window.removeEventListener('resize', onResize);
|
|
35
|
+
}, [detail]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!detail) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const onKeyDown = (event) => {
|
|
41
|
+
if (event.key === 'Escape') {
|
|
42
|
+
closeDetail();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
window.addEventListener('keydown', onKeyDown);
|
|
46
|
+
return () => window.removeEventListener('keydown', onKeyDown);
|
|
47
|
+
}, [detail, closeDetail]);
|
|
48
|
+
const expanded = detail?.expanded ?? false;
|
|
49
|
+
const width = expanded
|
|
50
|
+
? Math.max(0, viewportWidth - EDGE_INSET * 2)
|
|
51
|
+
: Math.min(COLLAPSED_WIDTH, Math.max(0, viewportWidth - EDGE_INSET * 2));
|
|
52
|
+
return (_jsx(AnimatePresence, { children: detail ? (_jsxs(_Fragment, { children: [_jsx(Flex, { as: motion.div, onClick: closeDetail, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, zIndex: "scrim", css: { position: 'fixed', inset: 0, background: 'rgb(0 0 0 / 0.45)' } }, "hash-drawer-scrim"), _jsx(Flex, { justify: "flex-end", zIndex: "scrim", css: {
|
|
53
|
+
position: 'fixed',
|
|
54
|
+
inset: 0,
|
|
55
|
+
// `content-box` (the default) is the actual bug: with `inset: 0` and no explicit
|
|
56
|
+
// height, the browser resolves the auto height from the insets alone, THEN adds
|
|
57
|
+
// padding on top of that — overflowing past the viewport by exactly 2x the padding.
|
|
58
|
+
// `border-box` makes padding come out of that resolved height instead of adding to it.
|
|
59
|
+
boxSizing: 'border-box',
|
|
60
|
+
padding: EDGE_INSET,
|
|
61
|
+
pointerEvents: 'none',
|
|
62
|
+
}, children: _jsxs(Flex, { as: motion.div, direction: "column", role: "dialog", "aria-modal": "true", initial: { opacity: 0 }, animate: { opacity: 1, width }, exit: { opacity: 0 }, transition: {
|
|
63
|
+
width: { duration: 0.32, ease: [0.2, 0.8, 0.2, 1] },
|
|
64
|
+
opacity: { duration: 0.28 },
|
|
65
|
+
}, background: "surface", color: "text", radius: "drawer", shadow: "drawer", border: true, zIndex: "drawer",
|
|
66
|
+
// Explicit, not implicit flex stretch: a flex item that's also a scroll container
|
|
67
|
+
// (`overflow: auto`) doesn't reliably stay within its parent's cross-axis size —
|
|
68
|
+
// its default `min-height: auto` can win out and push it past the stretched height
|
|
69
|
+
// instead of scrolling internally. `height: '100%'` here is well-defined regardless
|
|
70
|
+
// (the wrapper's `inset: 0` gives it an unambiguous content-box size).
|
|
71
|
+
height: "100%", minHeight: 0, maxHeight: "100%", overflow: "auto", p: 5, css: { pointerEvents: 'auto' }, children: [_jsxs(Flex, { justify: "space-between", align: "center", gap: 2.5, mb: 4, children: [detail.header, _jsxs(Flex, { gap: 1.5, grow: 0, children: [_jsx(DrawerActionButton, { icon: expanded ? 'lu:minimize-2' : 'lu:maximize-2', label: expanded ? 'Collapse' : 'Expand', onClick: toggleExpanded }), _jsx(DrawerActionButton, { icon: "lu:x", label: "Close", onClick: closeDetail })] })] }), detail.body] }, "hash-drawer") })] })) : null }));
|
|
72
|
+
}
|
|
73
|
+
const ACTION_BACKGROUND = 'surfaceRaised';
|
|
74
|
+
const ACTION_COLOR = 'text';
|
|
75
|
+
function DrawerActionButton({ icon, label, onClick, }) {
|
|
76
|
+
return (_jsx(Flex, { as: "button", type: "button", "aria-label": label, title: label, onClick: onClick, background: ACTION_BACKGROUND, color: ACTION_COLOR, radius: "small", align: "center", justify: "center", cursor: "pointer", width: 30, height: 30, children: _jsx(Icon, { name: icon, size: 14 }) }));
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-drawer.js","sourceRoot":"","sources":["../../src/layout/entity-drawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import type { Interpolation, Theme } from '@emotion/react';
|
|
3
|
+
import { type FlexProps } from 'e-prim';
|
|
4
|
+
import { type ElementType } from 'react';
|
|
5
|
+
/**
|
|
6
|
+
* A row that scrolls sideways and fades out at an edge that has more content beyond it, so it
|
|
7
|
+
* reads as scrollable: the right edge while there is more to the right, the left once scrolled.
|
|
8
|
+
* It is a `Flex` (so `as`, `gap` and the rest apply) and sets `overflow-x: auto`; hide or style the
|
|
9
|
+
* scrollbar with its own `css`. Nothing fades when it all fits. `data-fade-start` and `data-fade-end`
|
|
10
|
+
* say which edges are fading.
|
|
11
|
+
*/
|
|
12
|
+
export declare function FadeScroll<E extends ElementType = 'div'>({ css, ...props }: FlexProps<E> & {
|
|
13
|
+
css?: Interpolation<Theme>;
|
|
14
|
+
}): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { Flex } from 'e-prim';
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
/** How wide the fade at a scrolled edge is. */
|
|
5
|
+
const FADE = 40;
|
|
6
|
+
const maskFor = (start, end) => `linear-gradient(to right, ${start ? 'transparent' : '#000'} 0, #000 ${start ? FADE : 0}px, #000 calc(100% - ${end ? FADE : 0}px), ${end ? 'transparent' : '#000'} 100%)`;
|
|
7
|
+
/**
|
|
8
|
+
* A row that scrolls sideways and fades out at an edge that has more content beyond it, so it
|
|
9
|
+
* reads as scrollable: the right edge while there is more to the right, the left once scrolled.
|
|
10
|
+
* It is a `Flex` (so `as`, `gap` and the rest apply) and sets `overflow-x: auto`; hide or style the
|
|
11
|
+
* scrollbar with its own `css`. Nothing fades when it all fits. `data-fade-start` and `data-fade-end`
|
|
12
|
+
* say which edges are fading.
|
|
13
|
+
*/
|
|
14
|
+
export function FadeScroll({ css, ...props }) {
|
|
15
|
+
const ref = useRef(null);
|
|
16
|
+
const [edges, setEdges] = useState({ start: false, end: false });
|
|
17
|
+
const measure = useCallback(() => {
|
|
18
|
+
const el = ref.current;
|
|
19
|
+
if (!el) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const start = el.scrollLeft > 1;
|
|
23
|
+
const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
24
|
+
setEdges((now) => (now.start === start && now.end === end ? now : { start, end }));
|
|
25
|
+
}, []);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const el = ref.current;
|
|
28
|
+
if (!el) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
measure();
|
|
32
|
+
el.addEventListener('scroll', measure, { passive: true });
|
|
33
|
+
// Its size, and what is in it (items arriving, artwork loading), both change how far it scrolls.
|
|
34
|
+
const resize = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(measure);
|
|
35
|
+
resize?.observe(el);
|
|
36
|
+
const mutation = typeof MutationObserver === 'undefined' ? undefined : new MutationObserver(measure);
|
|
37
|
+
mutation?.observe(el, { childList: true, subtree: true });
|
|
38
|
+
el.addEventListener('load', measure, true);
|
|
39
|
+
return () => {
|
|
40
|
+
el.removeEventListener('scroll', measure);
|
|
41
|
+
el.removeEventListener('load', measure, true);
|
|
42
|
+
resize?.disconnect();
|
|
43
|
+
mutation?.disconnect();
|
|
44
|
+
};
|
|
45
|
+
}, [measure]);
|
|
46
|
+
const mask = edges.start || edges.end ? maskFor(edges.start, edges.end) : undefined;
|
|
47
|
+
const own = {
|
|
48
|
+
ref,
|
|
49
|
+
'data-fade-start': edges.start,
|
|
50
|
+
'data-fade-end': edges.end,
|
|
51
|
+
css: [
|
|
52
|
+
{ overflowX: 'auto' },
|
|
53
|
+
mask ? { maskImage: mask, WebkitMaskImage: mask } : null,
|
|
54
|
+
css ?? null,
|
|
55
|
+
],
|
|
56
|
+
...props,
|
|
57
|
+
};
|
|
58
|
+
return _jsx(Flex, { ...own });
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fade-scroll.js","sourceRoot":"","sources":["../../src/layout/fade-scroll.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface GridProps {
|
|
3
|
+
/** Number of equal columns. Default 2. */
|
|
4
|
+
columns?: number;
|
|
5
|
+
/** Tiles (or any content) to lay out, one per cell. */
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** A grid of equal-width columns for tiles; cells share the width and never overflow it. */
|
|
9
|
+
export declare function Grid({ columns, children }: GridProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Grid as EPrimGrid } from 'e-prim';
|
|
3
|
+
/** A grid of equal-width columns for tiles; cells share the width and never overflow it. */
|
|
4
|
+
export function Grid({ columns = 2, children }) {
|
|
5
|
+
return (_jsx(EPrimGrid, { columns: [columns, 'minmax(0, 1fr)'], gap: 3, children: children }));
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/layout/grid.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,QAAQ,CAAC;AAW3C,4FAA4F;AAC5F,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,QAAQ,EAAa;IACvD,OAAO,CACL,KAAC,SAAS,IAAC,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,GAAG,EAAE,CAAC,YACpD,QAAQ,GACC,CACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface LogbookEntry {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Lowercase, no actor prefix, e.g. "turned on", "brightness set to 60%" — capitalized when
|
|
4
|
+
* there's no `actor` to lead with ("Turned on"), left lowercase after one ("Dan turned on"). */
|
|
5
|
+
message: string;
|
|
6
|
+
/** ISO 8601. */
|
|
7
|
+
timestamp: string;
|
|
8
|
+
/** Who or what triggered it, e.g. "Dan" or "automation.bedtime". Omit for the system. */
|
|
9
|
+
actor?: string;
|
|
10
|
+
/** Only matters when `actor` is set: a person gets an initials avatar, an automation a robot
|
|
11
|
+
* icon. Default `'person'`. */
|
|
12
|
+
actorKind?: 'person' | 'automation';
|
|
13
|
+
}
|
|
14
|
+
export interface HistorySectionProps {
|
|
15
|
+
/** Recent activity, newest first. An empty list renders nothing. */
|
|
16
|
+
entries: LogbookEntry[];
|
|
17
|
+
}
|
|
18
|
+
/** A short activity list for an entity's detail drawer. Generic — any entity type can supply it. */
|
|
19
|
+
export declare function HistorySection({ entries }: HistorySectionProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource @emotion/react */
|
|
3
|
+
import { Flex, Typography } from 'e-prim';
|
|
4
|
+
import { Icon } from '../icon.js';
|
|
5
|
+
import { capitalize } from '../status.js';
|
|
6
|
+
const MINUTE = 60_000;
|
|
7
|
+
const HOUR = 60 * MINUTE;
|
|
8
|
+
const DAY = 24 * HOUR;
|
|
9
|
+
function relativeTime(iso) {
|
|
10
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
11
|
+
if (diff < MINUTE) {
|
|
12
|
+
return 'Just now';
|
|
13
|
+
}
|
|
14
|
+
if (diff < HOUR) {
|
|
15
|
+
return `${Math.round(diff / MINUTE)}m ago`;
|
|
16
|
+
}
|
|
17
|
+
if (diff < DAY) {
|
|
18
|
+
return `${Math.round(diff / HOUR)}h ago`;
|
|
19
|
+
}
|
|
20
|
+
return `${Math.round(diff / DAY)}d ago`;
|
|
21
|
+
}
|
|
22
|
+
function initials(name) {
|
|
23
|
+
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
24
|
+
return words
|
|
25
|
+
.slice(0, 2)
|
|
26
|
+
.map((word) => word.charAt(0).toUpperCase())
|
|
27
|
+
.join('');
|
|
28
|
+
}
|
|
29
|
+
function Avatar({ actor, kind }) {
|
|
30
|
+
const automation = kind === 'automation';
|
|
31
|
+
return (_jsx(Flex, { align: "center", justify: "center", background: automation ? 'surfaceRaised' : 'accent', color: automation ? 'text' : 'accentText', radius: "full", width: 32, height: 32, css: { flex: 'none' }, children: automation ? (_jsx(Icon, { name: "lu:bot", size: 16 })) : (_jsx(Typography, { as: "span", variant: "eyebrow", children: initials(actor) })) }));
|
|
32
|
+
}
|
|
33
|
+
/** A short activity list for an entity's detail drawer. Generic — any entity type can supply it. */
|
|
34
|
+
export function HistorySection({ entries }) {
|
|
35
|
+
if (entries.length === 0) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return (_jsxs(Flex, { direction: "column", gap: 4, pt: 4, mt: "auto", children: [_jsx(Typography, { as: "span", variant: "eyebrow", uppercase: true, color: "textMuted", children: "History" }), _jsx(Flex, { direction: "column", children: entries.map((entry) => (_jsxs(Flex, { align: "center", gap: 3, py: 2, children: [entry.actor ? _jsx(Avatar, { actor: entry.actor, kind: entry.actorKind ?? 'person' }) : null, _jsxs(Flex, { direction: "column", minWidth: 0, children: [_jsxs(Typography, { as: "span", variant: "body", noWrap: true, textOverflow: "ellipsis", minWidth: 0, children: [entry.actor ? (_jsxs(Typography, { as: "span", variant: "bodyStrong", children: [entry.actor, ' '] })) : null, entry.actor ? entry.message : capitalize(entry.message)] }), _jsx(Typography, { as: "span", variant: "secondary", color: "textMuted", children: relativeTime(entry.timestamp) })] })] }, entry.id))) })] }));
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-section.js","sourceRoot":"","sources":["../../src/layout/history-section.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource @emotion/react */
|
|
3
|
+
import { Box } from 'e-prim';
|
|
4
|
+
import { motion } from 'motion/react';
|
|
5
|
+
import { HOLD_MS } from './use-hold.js';
|
|
6
|
+
/** The thin line along a card's top edge that fills while a press is being timed as a hold. */
|
|
7
|
+
export function HoldProgress() {
|
|
8
|
+
return (_jsx(Box, { as: motion.span, position: "absolute", height: 2, background: "textMuted", initial: { width: '0%' }, animate: { width: '100%' }, transition: { duration: HOLD_MS / 1000, ease: 'linear' }, css: { top: 0, left: 0, opacity: 0.5, pointerEvents: 'none' } }));
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hold-progress.js","sourceRoot":"","sources":["../../src/layout/hold-progress.tsx"],"names":[],"mappings":";AAAA,sCAAsC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,+FAA+F;AAC/F,MAAM,UAAU,YAAY;IAC1B,OAAO,CACL,KAAC,GAAG,IACF,EAAE,EAAE,MAAM,CAAC,IAAI,EACf,QAAQ,EAAC,UAAU,EACnB,MAAM,EAAE,CAAC,EACT,UAAU,EAAC,WAAW,EACtB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EACxB,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAC1B,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EACxD,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,GAC7D,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CSSObject, Theme } from '@emotion/react';
|
|
2
|
+
/** The round icon button every tile, drawer and stepper uses, without a size: give it `width` and
|
|
3
|
+
* `height` props, or `iconButtonSize` for the density's usual one. (A size in here would outrank
|
|
4
|
+
* the props, since `css` is applied after them.) State comes from data attributes (`data-active`,
|
|
5
|
+
* `data-feedback`, `data-primary`) so a component only sets props. Order matters: later rules win
|
|
6
|
+
* at equal specificity. */
|
|
7
|
+
export declare const iconButtonStyles: ({ palette, radius }: Theme) => CSSObject;
|
|
8
|
+
/** The density's usual diameter for an icon button, for one that is not given a size of its own. */
|
|
9
|
+
export declare const iconButtonSize: ({ density }: Theme) => CSSObject;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** The round icon button every tile, drawer and stepper uses, without a size: give it `width` and
|
|
2
|
+
* `height` props, or `iconButtonSize` for the density's usual one. (A size in here would outrank
|
|
3
|
+
* the props, since `css` is applied after them.) State comes from data attributes (`data-active`,
|
|
4
|
+
* `data-feedback`, `data-primary`) so a component only sets props. Order matters: later rules win
|
|
5
|
+
* at equal specificity. */
|
|
6
|
+
export const iconButtonStyles = ({ palette, radius }) => ({
|
|
7
|
+
display: 'grid',
|
|
8
|
+
placeItems: 'center',
|
|
9
|
+
// A circle stays a circle: in a row with long text it keeps its size instead of being squeezed.
|
|
10
|
+
flexShrink: 0,
|
|
11
|
+
padding: 0,
|
|
12
|
+
border: 0,
|
|
13
|
+
borderRadius: radius.full,
|
|
14
|
+
background: palette.surfaceRaised,
|
|
15
|
+
cursor: 'pointer',
|
|
16
|
+
transition: 'background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease',
|
|
17
|
+
'&:disabled': { cursor: 'default', opacity: 0.5 },
|
|
18
|
+
"&[data-active='true']": { color: palette.warm },
|
|
19
|
+
"&[data-feedback='pending']": { opacity: 0.6 },
|
|
20
|
+
"&[data-feedback='done']": { background: palette.accent, color: palette.accentText },
|
|
21
|
+
"&[data-feedback='error']": { color: palette.danger },
|
|
22
|
+
"&[data-primary='true']": { background: palette.accent, color: palette.accentText },
|
|
23
|
+
});
|
|
24
|
+
/** The density's usual diameter for an icon button, for one that is not given a size of its own. */
|
|
25
|
+
export const iconButtonSize = ({ density }) => ({
|
|
26
|
+
width: density.iconCircle,
|
|
27
|
+
height: density.iconCircle,
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon-button-styles.js","sourceRoot":"","sources":["../../src/layout/icon-button-styles.ts"],"names":[],"mappings":"AAEA;;;;2BAI2B;AAC3B,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAS,EAAa,EAAE,CAAC,CAAC;IAC1E,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,QAAQ;IACpB,gGAAgG;IAChG,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;IACT,YAAY,EAAE,MAAM,CAAC,IAAI;IACzB,UAAU,EAAE,OAAO,CAAC,aAAa;IACjC,MAAM,EAAE,SAAS;IACjB,UAAU,EAAE,gEAAgE;IAC5E,YAAY,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE;IACjD,uBAAuB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE;IAChD,4BAA4B,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE;IAC9C,yBAAyB,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;IACpF,0BAA0B,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;IACrD,wBAAwB,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;CACpF,CAAC,CAAC;AAEH,oGAAoG;AACpG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,OAAO,EAAS,EAAa,EAAE,CAAC,CAAC;IAChE,KAAK,EAAE,OAAO,CAAC,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC,UAAU;CAC3B,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
type Side = 'left' | 'bottom';
|
|
3
|
+
/** Reserves `size` px of the surrounding `Page`'s edge for something fixed over it (`NavRail`,
|
|
4
|
+
* `NavDock`), so content never sits under it. A no-op outside a `Page`. */
|
|
5
|
+
export declare function usePageInset(side: Side, size: number): void;
|
|
6
|
+
export interface PageProps {
|
|
7
|
+
/** The dashboard. */
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** Page height. Default `100dvh`: the whole viewport. Only embedding it somewhere smaller (a preview) needs another. */
|
|
10
|
+
height?: string | number;
|
|
11
|
+
}
|
|
12
|
+
/** The page every dashboard renders into: padded by the density's spacing, a column with gaps,
|
|
13
|
+
* exactly viewport height, and scrolling inside itself (the document never scrolls — the entity
|
|
14
|
+
* drawer is `position: fixed` and relies on that). It pads further for a `NavRail` or `NavDock`
|
|
15
|
+
* the dashboard includes. Render it once, in the app's root layout. */
|
|
16
|
+
export declare function Page({ children, height }: PageProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource @emotion/react */
|
|
3
|
+
import { Flex } from 'e-prim';
|
|
4
|
+
import { createContext, useCallback, useContext, useLayoutEffect, useMemo, useState, } from 'react';
|
|
5
|
+
const InsetContext = createContext(null);
|
|
6
|
+
/** Reserves `size` px of the surrounding `Page`'s edge for something fixed over it (`NavRail`,
|
|
7
|
+
* `NavDock`), so content never sits under it. A no-op outside a `Page`. */
|
|
8
|
+
export function usePageInset(side, size) {
|
|
9
|
+
const reserve = useContext(InsetContext);
|
|
10
|
+
useLayoutEffect(() => reserve?.(side, size), [reserve, side, size]);
|
|
11
|
+
}
|
|
12
|
+
/** The page every dashboard renders into: padded by the density's spacing, a column with gaps,
|
|
13
|
+
* exactly viewport height, and scrolling inside itself (the document never scrolls — the entity
|
|
14
|
+
* drawer is `position: fixed` and relies on that). It pads further for a `NavRail` or `NavDock`
|
|
15
|
+
* the dashboard includes. Render it once, in the app's root layout. */
|
|
16
|
+
export function Page({ children, height = '100dvh' }) {
|
|
17
|
+
const [insets, setInsets] = useState({ left: 0, bottom: 0 });
|
|
18
|
+
const reserve = useCallback((side, size) => {
|
|
19
|
+
setInsets((current) => ({ ...current, [side]: size }));
|
|
20
|
+
return () => setInsets((current) => ({ ...current, [side]: 0 }));
|
|
21
|
+
}, []);
|
|
22
|
+
const value = useMemo(() => reserve, [reserve]);
|
|
23
|
+
return (_jsx(InsetContext.Provider, { value: value, children: _jsx(Flex, { as: "main", direction: "column", height: height, overflow: "auto", gap: 3, p: 3, css: ({ spacing }) => ({
|
|
24
|
+
// The padding of one space, plus room for a nav that is fixed over the page.
|
|
25
|
+
paddingLeft: `calc(${spacing(3)} + ${insets.left}px)`,
|
|
26
|
+
paddingBottom: `calc(${spacing(3)} + ${insets.bottom}px)`,
|
|
27
|
+
boxSizing: 'border-box',
|
|
28
|
+
}), children: children }) }));
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/layout/page.tsx"],"names":[],"mappings":";AAAA,sCAAsC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,eAAe,EACf,OAAO,EACP,QAAQ,GAET,MAAM,OAAO,CAAC;AAIf,MAAM,YAAY,GAAG,aAAa,CAAoD,IAAI,CAAC,CAAC;AAE5F;2EAC2E;AAC3E,MAAM,UAAU,YAAY,CAAC,IAAU,EAAE,IAAY;IACnD,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACzC,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC;AAUD;;;uEAGuE;AACvE,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAa;IAC7D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAuB,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,IAAU,EAAE,IAAY,EAAE,EAAE;QACvD,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEhD,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACjC,KAAC,IAAI,IACH,EAAE,EAAC,MAAM,EACT,SAAS,EAAC,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAC,MAAM,EACf,GAAG,EAAE,CAAC,EACN,CAAC,EAAE,CAAC,EACJ,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;gBACrB,6EAA6E;gBAC7E,WAAW,EAAE,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,KAAK;gBACrD,aAAa,EAAE,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,KAAK;gBACzD,SAAS,EAAE,YAAY;aACxB,CAAC,YAED,QAAQ,GACJ,GACe,CACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import type { Interpolation, Theme } from '@emotion/react';
|
|
3
|
+
import { type FlexProps } from 'e-prim';
|
|
4
|
+
import type { ElementType } from 'react';
|
|
5
|
+
/** A button with the browser's look removed: no border, no background, no padding, text on the
|
|
6
|
+
* left, and a pointer. Everything else is the element's own and e-prim's props (it is a `Flex`), so a clickable row,
|
|
7
|
+
* card or chip is `<PlainButton gap={…} …>` with the look it wants. Renders a `button`, or what
|
|
8
|
+
* `as` says (`motion.button`). A `css` of its own is added to the reset, not instead of it. */
|
|
9
|
+
export declare function PlainButton<E extends ElementType = 'button'>({ css, ...props }: FlexProps<E> & {
|
|
10
|
+
css?: Interpolation<Theme>;
|
|
11
|
+
}): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { Flex } from 'e-prim';
|
|
3
|
+
/** A button with the browser's look removed: no border, no background, no padding, text on the
|
|
4
|
+
* left, and a pointer. Everything else is the element's own and e-prim's props (it is a `Flex`), so a clickable row,
|
|
5
|
+
* card or chip is `<PlainButton gap={…} …>` with the look it wants. Renders a `button`, or what
|
|
6
|
+
* `as` says (`motion.button`). A `css` of its own is added to the reset, not instead of it. */
|
|
7
|
+
export function PlainButton({ css, ...props }) {
|
|
8
|
+
const own = {
|
|
9
|
+
as: 'button',
|
|
10
|
+
type: 'button',
|
|
11
|
+
p: 0,
|
|
12
|
+
cursor: 'pointer',
|
|
13
|
+
css: [{ background: 'none', textAlign: 'left' }, css ?? null],
|
|
14
|
+
...props,
|
|
15
|
+
};
|
|
16
|
+
return _jsx(Flex, { ...own });
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain-button.js","sourceRoot":"","sources":["../../src/layout/plain-button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAkB,MAAM,QAAQ,CAAC;AAG9C;;;+FAG+F;AAC/F,MAAM,UAAU,WAAW,CAAmC,EAC5D,GAAG,EACH,GAAG,KAAK,EACsC;IAC9C,MAAM,GAAG,GAAG;QACV,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,CAAC,EAAE,CAAC;QACJ,MAAM,EAAE,SAAS;QACjB,GAAG,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,IAAI,CAAC;QAC7D,GAAG,KAAK;KACiB,CAAC;IAE5B,OAAO,KAAC,IAAI,OAAK,GAAG,GAAI,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { IconName } from '../icon-data.ts';
|
|
3
|
+
export interface RoomHeaderProps {
|
|
4
|
+
/** The room's name. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Icon id, e.g. `lu:sofa`. */
|
|
7
|
+
icon?: IconName;
|
|
8
|
+
/** Header readouts, typically `<SensorReadout />`s. */
|
|
9
|
+
readouts?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/** The header that starts a room: muted icon and title, a hairline, and readouts on the right. Put it above a `Grid` (or any tiles); it adds its own space above, so consecutive rooms read as groups. */
|
|
12
|
+
export declare function RoomHeader({ title, icon, readouts }: RoomHeaderProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
+
/** @jsxImportSource @emotion/react */
|
|
3
|
+
import { Box, Flex, Typography } from 'e-prim';
|
|
4
|
+
import { Icon } from '../icon.js';
|
|
5
|
+
/** The header that starts a room: muted icon and title, a hairline, and readouts on the right. Put it above a `Grid` (or any tiles); it adds its own space above, so consecutive rooms read as groups. */
|
|
6
|
+
export function RoomHeader({ title, icon, readouts }) {
|
|
7
|
+
return (_jsxs(Flex, { as: "header", align: "center", color: "textMuted", minHeight: 32, mt: 3, gap: 3,
|
|
8
|
+
// A header starts a new group: the extra space sits on top of the screen's own gap, so a
|
|
9
|
+
// room reads as header + its tiles rather than as evenly spaced rows.
|
|
10
|
+
css: { '&:first-child': { marginTop: 0 } }, children: [icon ? _jsx(Icon, { name: icon, size: 16 }) : null, _jsx(Typography, { as: "h2", variant: "roomTitle", color: "textMuted", css: { margin: 0 }, children: title }), _jsx(Box, { as: "span", background: "border", css: { flex: 1, height: 1 } }), readouts ? (_jsx(Flex, { align: "center", color: "textMuted", css: ({ density }) => ({ gap: density.space * 1.5 }), children: readouts })) : null] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-header.js","sourceRoot":"","sources":["../../src/layout/room-header.tsx"],"names":[],"mappings":";AAAA,sCAAsC;AACtC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAG/C,OAAO,EAAE,IAAI,EAAE,MAAM,YAAa,CAAC;AAanC,0MAA0M;AAC1M,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAmB;IACnE,OAAO,CACL,MAAC,IAAI,IACH,EAAE,EAAC,QAAQ,EACX,KAAK,EAAC,QAAQ,EACd,KAAK,EAAC,WAAW,EACjB,SAAS,EAAE,EAAE,EACb,EAAE,EAAE,CAAC,EACL,GAAG,EAAE,CAAC;QACN,yFAAyF;QACzF,sEAAsE;QACtE,GAAG,EAAE,EAAE,eAAe,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,aAEzC,IAAI,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,IAAI,EAC7C,KAAC,UAAU,IAAC,EAAE,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,KAAK,EAAC,WAAW,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YACzE,KAAK,GACK,EACb,KAAC,GAAG,IAAC,EAAE,EAAC,MAAM,EAAC,UAAU,EAAC,QAAQ,EAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAI,EACjE,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,IAAI,IACH,KAAK,EAAC,QAAQ,EACd,KAAK,EAAC,WAAW,EACjB,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,YAEnD,QAAQ,GACJ,CACR,CAAC,CAAC,CAAC,IAAI,IACH,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import type { Interpolation, Theme } from '@emotion/react';
|
|
3
|
+
import { type BoxProps } from 'e-prim';
|
|
4
|
+
import type { ElementType } from 'react';
|
|
5
|
+
/** The round button every tile, drawer, stepper and calendar uses: a circle in the surface color
|
|
6
|
+
* with the shared hover, disabled and state looks (`data-active`, `data-feedback`, `data-primary`).
|
|
7
|
+
* It is a `button`, or whatever `as` says (the tile's animated one passes `motion.button`), and
|
|
8
|
+
* takes that element's own props. A `css` of its own is added to the shared look, not instead of it. */
|
|
9
|
+
export declare function RoundButton<E extends ElementType = 'button'>({ size, css, ...props }: BoxProps<E> & {
|
|
10
|
+
/** The diameter in px. Defaults to the density's usual icon circle. */
|
|
11
|
+
size?: number;
|
|
12
|
+
css?: Interpolation<Theme>;
|
|
13
|
+
}): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { Box } from 'e-prim';
|
|
3
|
+
import { iconButtonSize, iconButtonStyles } from './icon-button-styles.js';
|
|
4
|
+
/** The round button every tile, drawer, stepper and calendar uses: a circle in the surface color
|
|
5
|
+
* with the shared hover, disabled and state looks (`data-active`, `data-feedback`, `data-primary`).
|
|
6
|
+
* It is a `button`, or whatever `as` says (the tile's animated one passes `motion.button`), and
|
|
7
|
+
* takes that element's own props. A `css` of its own is added to the shared look, not instead of it. */
|
|
8
|
+
export function RoundButton({ size, css, ...props }) {
|
|
9
|
+
const own = {
|
|
10
|
+
as: 'button',
|
|
11
|
+
type: 'button',
|
|
12
|
+
...(size !== undefined ? { width: size, height: size } : {}),
|
|
13
|
+
// A size in `css` would outrank the `width` and `height` props, so the default one is only
|
|
14
|
+
// added when there is no size of its own.
|
|
15
|
+
css: [iconButtonStyles, size === undefined ? iconButtonSize : null, css ?? null],
|
|
16
|
+
...props,
|
|
17
|
+
};
|
|
18
|
+
return _jsx(Box, { ...own });
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"round-button.js","sourceRoot":"","sources":["../../src/layout/round-button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAiB,MAAM,QAAQ,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3E;;;wGAGwG;AACxG,MAAM,UAAU,WAAW,CAAmC,EAC5D,IAAI,EACJ,GAAG,EACH,GAAG,KAAK,EAKT;IACC,MAAM,GAAG,GAAG;QACV,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,2FAA2F;QAC3F,0CAA0C;QAC1C,GAAG,EAAE,CAAC,gBAAgB,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC;QAChF,GAAG,KAAK;KACgB,CAAC;IAE3B,OAAO,KAAC,GAAG,OAAK,GAAG,GAAI,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EntityRef } from '@hashsome/core';
|
|
2
|
+
import { type SeriesSample } from './series-chart.tsx';
|
|
3
|
+
export type { SeriesSample as SensorSample } from './series-chart.tsx';
|
|
4
|
+
/**
|
|
5
|
+
* A sensor's history for its detail drawer: a bare sparkline while the drawer is at its normal
|
|
6
|
+
* width, and — once expanded — the full chart with a range switcher (including a custom from/to
|
|
7
|
+
* date and time range). Min / max tiles aggregate the supplied samples: today / this week / this month
|
|
8
|
+
* collapsed, today / last 7 / last 30 days expanded, plus the custom range when one is chosen.
|
|
9
|
+
*/
|
|
10
|
+
export declare function SensorHistory({ samples: given, entity, unit, }: {
|
|
11
|
+
/** Readings over time, oldest first; ideally covering at least the last 30 days. Left out, they come from `entity`'s history when the backend keeps one. */
|
|
12
|
+
samples?: SeriesSample[];
|
|
13
|
+
entity?: EntityRef;
|
|
14
|
+
unit: string;
|
|
15
|
+
}): import("@emotion/react/jsx-runtime").JSX.Element | null;
|