@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.
Files changed (192) hide show
  1. package/LICENSE +674 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/entities/action-button.d.ts +17 -0
  4. package/dist/entities/action-button.js +56 -0
  5. package/dist/entities/action-button.js.map +1 -0
  6. package/dist/entities/artwork-ring.d.ts +17 -0
  7. package/dist/entities/artwork-ring.js +89 -0
  8. package/dist/entities/artwork-ring.js.map +1 -0
  9. package/dist/entities/climate-tile.d.ts +20 -0
  10. package/dist/entities/climate-tile.js +98 -0
  11. package/dist/entities/climate-tile.js.map +1 -0
  12. package/dist/entities/light-color.d.ts +52 -0
  13. package/dist/entities/light-color.js +148 -0
  14. package/dist/entities/light-color.js.map +1 -0
  15. package/dist/entities/light-tile.d.ts +24 -0
  16. package/dist/entities/light-tile.js +139 -0
  17. package/dist/entities/light-tile.js.map +1 -0
  18. package/dist/entities/media-browser.d.ts +15 -0
  19. package/dist/entities/media-browser.js +67 -0
  20. package/dist/entities/media-browser.js.map +1 -0
  21. package/dist/entities/media-controls.d.ts +20 -0
  22. package/dist/entities/media-controls.js +53 -0
  23. package/dist/entities/media-controls.js.map +1 -0
  24. package/dist/entities/media-player-bar.d.ts +14 -0
  25. package/dist/entities/media-player-bar.js +78 -0
  26. package/dist/entities/media-player-bar.js.map +1 -0
  27. package/dist/entities/media-player-body.d.ts +16 -0
  28. package/dist/entities/media-player-body.js +18 -0
  29. package/dist/entities/media-player-body.js.map +1 -0
  30. package/dist/entities/media-player-column.d.ts +18 -0
  31. package/dist/entities/media-player-column.js +34 -0
  32. package/dist/entities/media-player-column.js.map +1 -0
  33. package/dist/entities/media-player-page.d.ts +12 -0
  34. package/dist/entities/media-player-page.js +13 -0
  35. package/dist/entities/media-player-page.js.map +1 -0
  36. package/dist/entities/media-progress.d.ts +7 -0
  37. package/dist/entities/media-progress.js +30 -0
  38. package/dist/entities/media-progress.js.map +1 -0
  39. package/dist/entities/media-seek.d.ts +9 -0
  40. package/dist/entities/media-seek.js +19 -0
  41. package/dist/entities/media-seek.js.map +1 -0
  42. package/dist/entities/nav-dock.d.ts +13 -0
  43. package/dist/entities/nav-dock.js +22 -0
  44. package/dist/entities/nav-dock.js.map +1 -0
  45. package/dist/entities/nav-rail.d.ts +19 -0
  46. package/dist/entities/nav-rail.js +18 -0
  47. package/dist/entities/nav-rail.js.map +1 -0
  48. package/dist/entities/now-playing.d.ts +20 -0
  49. package/dist/entities/now-playing.js +34 -0
  50. package/dist/entities/now-playing.js.map +1 -0
  51. package/dist/entities/scene-button.d.ts +13 -0
  52. package/dist/entities/scene-button.js +6 -0
  53. package/dist/entities/scene-button.js.map +1 -0
  54. package/dist/entities/seek-line.d.ts +9 -0
  55. package/dist/entities/seek-line.js +71 -0
  56. package/dist/entities/seek-line.js.map +1 -0
  57. package/dist/entities/sensor-readout.d.ts +28 -0
  58. package/dist/entities/sensor-readout.js +95 -0
  59. package/dist/entities/sensor-readout.js.map +1 -0
  60. package/dist/entities/top-bar.d.ts +68 -0
  61. package/dist/entities/top-bar.js +248 -0
  62. package/dist/entities/top-bar.js.map +1 -0
  63. package/dist/entity-handle.d.ts +21 -0
  64. package/dist/entity-handle.js +16 -0
  65. package/dist/entity-handle.js.map +1 -0
  66. package/dist/gallery/fixtures.d.ts +4 -0
  67. package/dist/gallery/fixtures.js +119 -0
  68. package/dist/gallery/fixtures.js.map +1 -0
  69. package/dist/gallery/gallery.d.ts +9 -0
  70. package/dist/gallery/gallery.js +355 -0
  71. package/dist/gallery/gallery.js.map +1 -0
  72. package/dist/gallery/index.d.ts +2 -0
  73. package/dist/gallery/index.js +2 -0
  74. package/dist/gallery/index.js.map +1 -0
  75. package/dist/gallery/props-data.d.ts +10 -0
  76. package/dist/gallery/props-data.js +718 -0
  77. package/dist/gallery/props-data.js.map +1 -0
  78. package/dist/hooks.d.ts +19 -0
  79. package/dist/hooks.js +53 -0
  80. package/dist/hooks.js.map +1 -0
  81. package/dist/icon-data.d.ts +6 -0
  82. package/dist/icon-data.js +59193 -0
  83. package/dist/icon-data.js.map +1 -0
  84. package/dist/icon.d.ts +9 -0
  85. package/dist/icon.js +28 -0
  86. package/dist/icon.js.map +1 -0
  87. package/dist/index.d.ts +30 -0
  88. package/dist/index.js +24 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/layout/cover.d.ts +5 -0
  91. package/dist/layout/cover.js +8 -0
  92. package/dist/layout/cover.js.map +1 -0
  93. package/dist/layout/date-time-field.d.ts +15 -0
  94. package/dist/layout/date-time-field.js +108 -0
  95. package/dist/layout/date-time-field.js.map +1 -0
  96. package/dist/layout/detail-provider.d.ts +22 -0
  97. package/dist/layout/detail-provider.js +26 -0
  98. package/dist/layout/detail-provider.js.map +1 -0
  99. package/dist/layout/drawer-controls.d.ts +46 -0
  100. package/dist/layout/drawer-controls.js +93 -0
  101. package/dist/layout/drawer-controls.js.map +1 -0
  102. package/dist/layout/energy-chart.d.ts +37 -0
  103. package/dist/layout/energy-chart.js +85 -0
  104. package/dist/layout/energy-chart.js.map +1 -0
  105. package/dist/layout/energy-usage.d.ts +6 -0
  106. package/dist/layout/energy-usage.js +18 -0
  107. package/dist/layout/energy-usage.js.map +1 -0
  108. package/dist/layout/entity-drawer.d.ts +15 -0
  109. package/dist/layout/entity-drawer.js +77 -0
  110. package/dist/layout/entity-drawer.js.map +1 -0
  111. package/dist/layout/fade-scroll.d.ts +14 -0
  112. package/dist/layout/fade-scroll.js +59 -0
  113. package/dist/layout/fade-scroll.js.map +1 -0
  114. package/dist/layout/grid.d.ts +9 -0
  115. package/dist/layout/grid.js +6 -0
  116. package/dist/layout/grid.js.map +1 -0
  117. package/dist/layout/history-section.d.ts +19 -0
  118. package/dist/layout/history-section.js +39 -0
  119. package/dist/layout/history-section.js.map +1 -0
  120. package/dist/layout/hold-progress.d.ts +2 -0
  121. package/dist/layout/hold-progress.js +9 -0
  122. package/dist/layout/hold-progress.js.map +1 -0
  123. package/dist/layout/icon-button-styles.d.ts +9 -0
  124. package/dist/layout/icon-button-styles.js +28 -0
  125. package/dist/layout/icon-button-styles.js.map +1 -0
  126. package/dist/layout/page.d.ts +17 -0
  127. package/dist/layout/page.js +29 -0
  128. package/dist/layout/page.js.map +1 -0
  129. package/dist/layout/plain-button.d.ts +11 -0
  130. package/dist/layout/plain-button.js +17 -0
  131. package/dist/layout/plain-button.js.map +1 -0
  132. package/dist/layout/room-header.d.ts +12 -0
  133. package/dist/layout/room-header.js +11 -0
  134. package/dist/layout/room-header.js.map +1 -0
  135. package/dist/layout/round-button.d.ts +13 -0
  136. package/dist/layout/round-button.js +19 -0
  137. package/dist/layout/round-button.js.map +1 -0
  138. package/dist/layout/sensor-history.d.ts +15 -0
  139. package/dist/layout/sensor-history.js +91 -0
  140. package/dist/layout/sensor-history.js.map +1 -0
  141. package/dist/layout/sensor-stats.d.ts +21 -0
  142. package/dist/layout/sensor-stats.js +79 -0
  143. package/dist/layout/sensor-stats.js.map +1 -0
  144. package/dist/layout/series-chart.d.ts +25 -0
  145. package/dist/layout/series-chart.js +46 -0
  146. package/dist/layout/series-chart.js.map +1 -0
  147. package/dist/layout/stepper.d.ts +10 -0
  148. package/dist/layout/stepper.js +12 -0
  149. package/dist/layout/stepper.js.map +1 -0
  150. package/dist/layout/swatch-row.d.ts +19 -0
  151. package/dist/layout/swatch-row.js +20 -0
  152. package/dist/layout/swatch-row.js.map +1 -0
  153. package/dist/layout/tile.d.ts +67 -0
  154. package/dist/layout/tile.js +207 -0
  155. package/dist/layout/tile.js.map +1 -0
  156. package/dist/layout/use-drawer.d.ts +33 -0
  157. package/dist/layout/use-drawer.js +34 -0
  158. package/dist/layout/use-drawer.js.map +1 -0
  159. package/dist/layout/use-hold.d.ts +21 -0
  160. package/dist/layout/use-hold.js +61 -0
  161. package/dist/layout/use-hold.js.map +1 -0
  162. package/dist/provider.d.ts +37 -0
  163. package/dist/provider.js +95 -0
  164. package/dist/provider.js.map +1 -0
  165. package/dist/status.d.ts +8 -0
  166. package/dist/status.js +27 -0
  167. package/dist/status.js.map +1 -0
  168. package/dist/theme/density.d.ts +16 -0
  169. package/dist/theme/density.js +7 -0
  170. package/dist/theme/density.js.map +1 -0
  171. package/dist/theme/global-styles.d.ts +5 -0
  172. package/dist/theme/global-styles.js +44 -0
  173. package/dist/theme/global-styles.js.map +1 -0
  174. package/dist/theme/index.d.ts +19 -0
  175. package/dist/theme/index.js +106 -0
  176. package/dist/theme/index.js.map +1 -0
  177. package/dist/theme/overrides.d.ts +28 -0
  178. package/dist/theme/overrides.js +24 -0
  179. package/dist/theme/overrides.js.map +1 -0
  180. package/dist/theme/tokens.d.ts +78 -0
  181. package/dist/theme/tokens.js +1 -0
  182. package/dist/theme/tokens.js.map +1 -0
  183. package/dist/theme/use-typography.d.ts +4 -0
  184. package/dist/theme/use-typography.js +9 -0
  185. package/dist/theme/use-typography.js.map +1 -0
  186. package/dist/use-entity-history.d.ts +12 -0
  187. package/dist/use-entity-history.js +43 -0
  188. package/dist/use-entity-history.js.map +1 -0
  189. package/dist/use-media-browser.d.ts +31 -0
  190. package/dist/use-media-browser.js +87 -0
  191. package/dist/use-media-browser.js.map +1 -0
  192. package/package.json +57 -0
@@ -0,0 +1,718 @@
1
+ // Generated by `pnpm generate:catalog` from the components' own prop interfaces and doc comments.
2
+ // Do not edit by hand. The gallery renders this as each component's props table.
3
+ export const COMPONENT_PROPS = {
4
+ Grid: {
5
+ doc: 'A grid of equal-width columns for tiles; cells share the width and never overflow it.',
6
+ props: [
7
+ {
8
+ doc: 'Number of equal columns. Default 2.',
9
+ name: 'columns',
10
+ optional: true,
11
+ type: 'number',
12
+ },
13
+ {
14
+ doc: 'Tiles (or any content) to lay out, one per cell.',
15
+ name: 'children',
16
+ optional: false,
17
+ type: 'ReactNode',
18
+ },
19
+ ],
20
+ },
21
+ Page: {
22
+ doc: "The page every dashboard renders into: padded by the density's spacing, a column with gaps, exactly viewport height, and scrolling inside itself (the document never scrolls — the entity drawer is `position: fixed` and relies on that). It pads further for a `NavRail` or `NavDock` the dashboard includes. Render it once, in the app's root layout.",
23
+ props: [
24
+ {
25
+ doc: 'The dashboard.',
26
+ name: 'children',
27
+ optional: false,
28
+ type: 'ReactNode',
29
+ },
30
+ {
31
+ doc: 'Page height. Default `100dvh`: the whole viewport. Only embedding it somewhere smaller (a preview) needs another.',
32
+ name: 'height',
33
+ optional: true,
34
+ type: 'string | number',
35
+ },
36
+ ],
37
+ },
38
+ RoomHeader: {
39
+ doc: '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.',
40
+ props: [
41
+ {
42
+ doc: "The room's name.",
43
+ name: 'title',
44
+ optional: false,
45
+ type: 'string',
46
+ },
47
+ {
48
+ doc: 'Icon id, e.g. `lu:sofa`.',
49
+ name: 'icon',
50
+ optional: true,
51
+ type: 'IconName',
52
+ },
53
+ {
54
+ doc: 'Header readouts, typically `<SensorReadout />`s.',
55
+ name: 'readouts',
56
+ optional: true,
57
+ type: 'ReactNode',
58
+ },
59
+ ],
60
+ },
61
+ Tile: {
62
+ doc: 'Base pill used by all entity tiles. Tap to press; hold (with `detail` set) to open the drawer.',
63
+ props: [
64
+ {
65
+ doc: "The tile's name.",
66
+ name: 'label',
67
+ optional: false,
68
+ type: 'string',
69
+ },
70
+ {
71
+ doc: 'Icon id, e.g. `lu:lightbulb`.',
72
+ name: 'icon',
73
+ optional: true,
74
+ type: 'IconName',
75
+ },
76
+ {
77
+ doc: 'Second line. Replaced by the status label when the entity is not ready.',
78
+ name: 'secondary',
79
+ optional: true,
80
+ type: 'ReactNode',
81
+ },
82
+ {
83
+ doc: 'Status of what the tile shows; anything but `ready` disables it and shows why (Loading, Unavailable, Not found).',
84
+ name: 'status',
85
+ optional: true,
86
+ type: 'EntityStatus',
87
+ },
88
+ {
89
+ doc: 'Whether the thing it controls is on: lights the icon (and the whole card for an on/off tile) with the accent color.',
90
+ name: 'active',
91
+ optional: true,
92
+ type: 'boolean',
93
+ },
94
+ {
95
+ doc: 'Highlights the tile as pending / done / failed after an action.',
96
+ name: 'feedback',
97
+ optional: true,
98
+ type: "'pending' | 'done' | 'error' | undefined",
99
+ },
100
+ {
101
+ doc: 'Called on a tap — not after a drag or a hold.',
102
+ name: 'onPress',
103
+ optional: true,
104
+ type: '(() => void) | undefined',
105
+ },
106
+ {
107
+ doc: '0..1. Renders a fill bar; enables drag and arrow keys to change it.',
108
+ name: 'fill',
109
+ optional: true,
110
+ type: 'number',
111
+ },
112
+ {
113
+ doc: 'Called once when a drag ends or an arrow key is pressed.',
114
+ name: 'onFillChange',
115
+ optional: true,
116
+ type: '(fill: number) => void',
117
+ },
118
+ {
119
+ doc: 'Controls shown on the right (steppers, icon buttons).',
120
+ name: 'trailing',
121
+ optional: true,
122
+ type: 'ReactNode',
123
+ },
124
+ {
125
+ doc: 'Replaces the label and status with custom content (e.g. color swatches) while set; the tile stops being one big button. `openDetail` opens the drawer.',
126
+ name: 'overlay',
127
+ optional: true,
128
+ type: '(controls: { openDetail: () => void }) => ReactNode',
129
+ },
130
+ {
131
+ doc: 'Native tooltip text.',
132
+ name: 'title',
133
+ optional: true,
134
+ type: 'string',
135
+ },
136
+ {
137
+ doc: 'Rendered in the shared detail drawer on a long-press (~500ms). Adds the hold gesture.',
138
+ name: 'detail',
139
+ optional: true,
140
+ type: 'ReactNode',
141
+ },
142
+ {
143
+ doc: 'Subtitle under the drawer header\'s name, e.g. "Light". Only used when `detail` is set.',
144
+ name: 'kind',
145
+ optional: true,
146
+ type: 'string',
147
+ },
148
+ {
149
+ doc: "A power-draw chart, shown in the drawer above `history` (e.g. from a Shelly's energy monitoring). Generic across every entity type.",
150
+ name: 'energy',
151
+ optional: true,
152
+ type: 'EnergyChartProps',
153
+ },
154
+ {
155
+ doc: 'Recent activity, shown in the drawer below `detail`/`energy`. Generic across every entity type — whichever component has a way to fetch it just passes it through.',
156
+ name: 'history',
157
+ optional: true,
158
+ type: 'LogbookEntry[]',
159
+ },
160
+ ],
161
+ },
162
+ IconButton: {
163
+ doc: '',
164
+ props: [],
165
+ },
166
+ EnergyChart: {
167
+ doc: "A power-draw chart for an entity's detail drawer, e.g. from a Shelly's energy monitoring. Generic — any entity type can supply it. Deliberately two-tier: a bare sparkline while the drawer is at its normal (side) width, and the full interactive chart — axes, tooltip, a selectable time range — only once it's expanded to fullscreen, where there's room for it.",
168
+ props: [
169
+ {
170
+ doc: "Live power sensor (current draw, e.g. a Shelly's `sensor.*_power`). Its reading is the headline and updates as it changes; without it the headline falls back to the last chart sample.",
171
+ name: 'power',
172
+ optional: true,
173
+ type: 'EntityRef',
174
+ },
175
+ {
176
+ doc: 'Lifetime energy counter (kWh, e.g. `sensor.*_energy`). Shown as a quiet "Lifetime" line when expanded — per-period usage can\'t be derived from a counter without history, so pass `usage` for that.',
177
+ name: 'energy',
178
+ optional: true,
179
+ type: 'EntityRef',
180
+ },
181
+ {
182
+ doc: "Usage per period in kWh. Left out, it is worked out from `energy`'s history when the backend keeps one (Home Assistant's long-term statistics); pass it to use your own.",
183
+ name: 'usage',
184
+ optional: true,
185
+ type: 'EnergyUsage',
186
+ },
187
+ {
188
+ doc: "Samples for each range the person can pick; `onRangeChange` fires on pick. Left out, they are loaded from `power`'s history when the backend keeps one, for the selected range; pass them to use your own.",
189
+ name: 'seriesByRange',
190
+ optional: true,
191
+ type: 'Partial<Record<EnergyRange, EnergySample[]>>',
192
+ },
193
+ {
194
+ doc: 'Called when the person picks another range, so a real data source can load it.',
195
+ name: 'onRangeChange',
196
+ optional: true,
197
+ type: '(range: EnergyRange) => void',
198
+ },
199
+ {
200
+ doc: "Default `'W'`.",
201
+ name: 'unit',
202
+ optional: true,
203
+ type: 'string',
204
+ },
205
+ ],
206
+ },
207
+ HistorySection: {
208
+ doc: "A short activity list for an entity's detail drawer. Generic — any entity type can supply it.",
209
+ props: [
210
+ {
211
+ doc: 'Recent activity, newest first. An empty list renders nothing.',
212
+ name: 'entries',
213
+ optional: false,
214
+ type: 'LogbookEntry[]',
215
+ },
216
+ ],
217
+ },
218
+ Icon: {
219
+ doc: 'An inline SVG icon, from a plain prefixed id (`lu:` Lucide, `tb:` Tabler outline). Takes the surrounding text color.',
220
+ props: [
221
+ {
222
+ doc: 'Prefixed icon id, e.g. `lu:lightbulb`, `tb:vacuum-cleaner`.',
223
+ name: 'name',
224
+ optional: false,
225
+ type: 'IconName',
226
+ },
227
+ {
228
+ doc: "Overrides the density's icon size, in px.",
229
+ name: 'size',
230
+ optional: true,
231
+ type: 'number',
232
+ },
233
+ ],
234
+ },
235
+ LightTile: {
236
+ doc: 'Toggle, drag-to-dim (if dimmable) and a color overlay + drawer picker (if color capable).',
237
+ props: [
238
+ {
239
+ doc: 'A light, as a ref like `ha:light.kitchen_ceiling` or a handle (a custom source).',
240
+ name: 'entity',
241
+ optional: false,
242
+ type: "EntityRef | EntityHandle<'light'>",
243
+ },
244
+ {
245
+ doc: "Defaults to the light's name.",
246
+ name: 'name',
247
+ optional: true,
248
+ type: 'string',
249
+ },
250
+ {
251
+ doc: 'Icon id. Defaults to a bulb.',
252
+ name: 'icon',
253
+ optional: true,
254
+ type: 'IconName',
255
+ },
256
+ {
257
+ doc: "Power-draw chart (e.g. a Shelly's energy monitoring), shown in the drawer above `history`. No default source yet — pass explicitly.",
258
+ name: 'energy',
259
+ optional: true,
260
+ type: 'EnergyChartProps',
261
+ },
262
+ {
263
+ doc: 'Recent activity, shown in the drawer. No default source yet — pass explicitly.',
264
+ name: 'history',
265
+ optional: true,
266
+ type: 'LogbookEntry[]',
267
+ },
268
+ {
269
+ doc: "Swatches shown when the palette button is opened. Default: four white temperatures. Each takes `kelvin` (color-temp lights) and/or `hs` (color lights) and is skipped if the light can't apply it.",
270
+ name: 'colors',
271
+ optional: true,
272
+ type: 'LightColorPreset[]',
273
+ },
274
+ ],
275
+ },
276
+ ClimateTile: {
277
+ doc: 'Heater / thermostat: a mode button that opens mode swatches in the card, a target temperature stepper, and (on hold) a drawer with modes, a target bar, presets, energy and history.',
278
+ props: [
279
+ {
280
+ doc: 'A thermostat or heater, as a ref like `ha:climate.living_room` or a handle (a custom source).',
281
+ name: 'entity',
282
+ optional: false,
283
+ type: "EntityRef | EntityHandle<'climate'>",
284
+ },
285
+ {
286
+ doc: "Defaults to the device's name.",
287
+ name: 'name',
288
+ optional: true,
289
+ type: 'string',
290
+ },
291
+ {
292
+ doc: 'Icon id. Defaults to a thermometer.',
293
+ name: 'icon',
294
+ optional: true,
295
+ type: 'IconName',
296
+ },
297
+ {
298
+ doc: 'Power-draw chart for the drawer, above `history`. No default source yet — pass explicitly.',
299
+ name: 'energy',
300
+ optional: true,
301
+ type: 'EnergyChartProps',
302
+ },
303
+ {
304
+ doc: 'Recent activity, shown in the drawer. No default source yet — pass explicitly.',
305
+ name: 'history',
306
+ optional: true,
307
+ type: 'LogbookEntry[]',
308
+ },
309
+ ],
310
+ },
311
+ SensorReadout: {
312
+ doc: 'Inline value with icon and unit. Shows "Unavailable" / "Unknown" instead of a reading, and a warning when the value leaves its safe range. Tapping a numeric reading opens a drawer.',
313
+ props: [
314
+ {
315
+ doc: 'A sensor, as a ref like `ha:sensor.living_room_humidity` or a handle (a custom source).',
316
+ name: 'entity',
317
+ optional: false,
318
+ type: "EntityRef | EntityHandle<'sensor'>",
319
+ },
320
+ {
321
+ doc: 'Icon id. Defaults by device class (temperature, humidity).',
322
+ name: 'icon',
323
+ optional: true,
324
+ type: 'IconName',
325
+ },
326
+ {
327
+ doc: "Drawer title. Defaults to the sensor's name.",
328
+ name: 'name',
329
+ optional: true,
330
+ type: 'string',
331
+ },
332
+ {
333
+ doc: "The sensor's battery level, as a sensor ref like `ha:sensor.kitchen_t_h_sensor_battery` (a percentage). Shown in the drawer, in red when low.",
334
+ name: 'battery',
335
+ optional: true,
336
+ type: 'EntityRef',
337
+ },
338
+ {
339
+ doc: "Readings over time (oldest first). Adds a chart and min/max for today / this week / this month to the drawer, plus a custom date and time range when expanded. Left out, they come from the backend's own history when it keeps one (Home Assistant's long-term statistics).",
340
+ name: 'history',
341
+ optional: true,
342
+ type: 'SensorSample[]',
343
+ },
344
+ {
345
+ doc: 'Flags readings outside `{ min, max }` with a warning. Humidity defaults to 30–60 %; pass `false` to turn a default off.',
346
+ name: 'safeRange',
347
+ optional: true,
348
+ type: 'SafeRange | false',
349
+ },
350
+ {
351
+ doc: 'Tapping a ready numeric reading opens a drawer (current value and safe-range verdict, plus the chart and min/max when `history` is given). Default `true`; `false` keeps it inline text, e.g. for a presence chip.',
352
+ name: 'drawer',
353
+ optional: true,
354
+ type: 'boolean',
355
+ },
356
+ ],
357
+ },
358
+ ActionButton: {
359
+ doc: 'Any one-shot thing to trigger — a scene, script, button or switch, or your own `onPress` — with pending / done / error feedback.',
360
+ props: [
361
+ {
362
+ doc: "Button text. Defaults to the entity's name.",
363
+ name: 'label',
364
+ optional: true,
365
+ type: 'string',
366
+ },
367
+ {
368
+ doc: 'Icon id, e.g. `lu:coffee`.',
369
+ name: 'icon',
370
+ optional: true,
371
+ type: 'IconName',
372
+ },
373
+ {
374
+ doc: 'A second line of text under the label.',
375
+ name: 'secondary',
376
+ optional: true,
377
+ type: 'string',
378
+ },
379
+ {
380
+ doc: 'What to trigger: an action entity (scene, script, button — it runs) or a switch (it flips), as a ref or a handle.',
381
+ name: 'entity',
382
+ optional: true,
383
+ type: "EntityRef | EntityHandle<'action'> | EntityHandle<'switch'>",
384
+ },
385
+ {
386
+ doc: 'A custom press for something no entity covers (a raw backend call, your own logic). Used instead of `entity`.',
387
+ name: 'onPress',
388
+ optional: true,
389
+ type: '() => Promise<unknown>',
390
+ },
391
+ ],
392
+ },
393
+ SceneButton: {
394
+ doc: 'Activates a scene.',
395
+ props: [
396
+ {
397
+ doc: 'A scene (an `action` entity), as a ref like `ha:scene.movie_night` or a handle.',
398
+ name: 'entity',
399
+ optional: false,
400
+ type: "EntityRef | EntityHandle<'action'>",
401
+ },
402
+ {
403
+ doc: "Defaults to the scene's name.",
404
+ name: 'name',
405
+ optional: true,
406
+ type: 'string',
407
+ },
408
+ {
409
+ doc: 'Icon id. Defaults to a palette.',
410
+ name: 'icon',
411
+ optional: true,
412
+ type: 'IconName',
413
+ },
414
+ ],
415
+ },
416
+ MediaPlayerBar: {
417
+ doc: 'Now playing with previous / play-pause / next and a volume control, for a media player entity.',
418
+ props: [
419
+ {
420
+ doc: 'A media player, as a ref like `ha:media_player.living_room` or `ma:living_room`, or a handle (a custom source).',
421
+ name: 'entity',
422
+ optional: false,
423
+ type: "EntityRef | EntityHandle<'mediaPlayer'>",
424
+ },
425
+ {
426
+ doc: "What to call the player: the drawer's title and the name shown when nothing is playing. Defaults to the player's own name.",
427
+ name: 'name',
428
+ optional: true,
429
+ type: 'string',
430
+ },
431
+ {
432
+ doc: "Content for the media browser shown with the player in the drawer. Holding the card or pressing the artwork opens the drawer; the browse button opens it expanded. By default a `MediaBrowser` over the player's own library, shown only for a ref whose player has one; pass your own content to replace it, or `false` for no browse button.",
433
+ name: 'browse',
434
+ optional: true,
435
+ type: 'ReactNode | false',
436
+ },
437
+ ],
438
+ },
439
+ MediaPlayerColumn: {
440
+ doc: 'The player as an upright card for a narrow column beside a dashboard (a quarter to a third of the width): the artwork in a ring that shows (and seeks) the position, title, transport and a volume bar that is always visible. It is only as tall as it needs to be. Holding the card or pressing the artwork opens the drawer with the player and its library; the browse button opens that drawer expanded.',
441
+ props: [
442
+ {
443
+ doc: 'A media player, as a ref like `ma:kitchen` or `ha:media_player.kitchen`, or a handle (a custom source).',
444
+ name: 'entity',
445
+ optional: false,
446
+ type: "EntityRef | EntityHandle<'mediaPlayer'>",
447
+ },
448
+ {
449
+ doc: "What to call the player: the drawer's title and the name shown when nothing is playing. Defaults to the player's own name.",
450
+ name: 'name',
451
+ optional: true,
452
+ type: 'string',
453
+ },
454
+ {
455
+ doc: "Content for the media browser shown with the player in the drawer. By default a `MediaBrowser` over the player's own library, shown only for a ref whose player has one; pass your own content to replace it, or `false` for no drawer.",
456
+ name: 'browse',
457
+ optional: true,
458
+ type: 'ReactNode | false',
459
+ },
460
+ ],
461
+ },
462
+ MediaPlayerPage: {
463
+ doc: "The player as a whole page: the player centered, and the player's library below it, so songs are picked right here instead of in a drawer. It is the same layout as the expanded drawer. It fills the height it is given and scrolls inside it.",
464
+ props: [
465
+ {
466
+ doc: 'A media player, as a ref like `ma:living_room`. A ref, not a handle: the library below the player is read through the runtime.',
467
+ name: 'entity',
468
+ optional: false,
469
+ type: 'EntityRef',
470
+ },
471
+ {
472
+ doc: "What to call the player: the drawer's title and the name shown when nothing is playing. Defaults to the player's own name.",
473
+ name: 'name',
474
+ optional: true,
475
+ type: 'string',
476
+ },
477
+ ],
478
+ },
479
+ MediaBrowser: {
480
+ doc: "The library of a media player, in the app's own style: shelves, albums, playlists and the rest as rows with artwork. Tap a folder to open it, a track or station to play it, or the play button on an album, playlist or artist to play all of it. A search box appears when the library can be searched.",
481
+ props: [
482
+ {
483
+ doc: "The media player whose own library to browse, as a ref like `ma:living_room`. The backend that owns the player is the media source, so a Music Assistant player lists Music Assistant's library and a Home Assistant player Home Assistant's.",
484
+ name: 'entity',
485
+ optional: false,
486
+ type: 'EntityRef',
487
+ },
488
+ {
489
+ doc: 'Called after something is started, e.g. to close a drawer the browser sits in.',
490
+ name: 'onPlay',
491
+ optional: true,
492
+ type: '(item: BrowseItem) => void',
493
+ },
494
+ {
495
+ doc: 'How items are laid out. `list` is rows, compact enough for a narrow drawer. `theater` is a single row of large cards that scrolls sideways, for a wide space. `auto` is `theater` inside an expanded drawer and `list` anywhere else. Default `list`.',
496
+ name: 'layout',
497
+ optional: true,
498
+ type: "'list' | 'theater' | 'auto'",
499
+ },
500
+ ],
501
+ },
502
+ NavRail: {
503
+ doc: "Fixed left sidebar for switching between a dashboard's pages. Must be rendered inside a router. It is `position: fixed` and reserves its width in the surrounding `Page`, which pads for it so content never sits under it.",
504
+ props: [
505
+ {
506
+ doc: 'The pages to link to; `to` is relative to `base`.',
507
+ name: 'items',
508
+ optional: false,
509
+ type: 'NavItem[]',
510
+ },
511
+ {
512
+ doc: 'Base path items are resolved against, e.g. `/home`.',
513
+ name: 'base',
514
+ optional: false,
515
+ type: 'string',
516
+ },
517
+ {
518
+ doc: 'Adds a light/dark toggle at the bottom of the rail. Off by default — meant for development or a project that deliberately exposes it, not every kiosk install.',
519
+ name: 'showThemeToggle',
520
+ optional: true,
521
+ type: 'boolean',
522
+ },
523
+ ],
524
+ },
525
+ NavDock: {
526
+ doc: "Floating bottom pill for switching between a dashboard's pages. Must be rendered inside a router. `position: fixed`, floating over the page; it reserves the space it takes in the surrounding `Page`, which pads for it.",
527
+ props: [
528
+ {
529
+ doc: 'The pages to link to; `to` is relative to `base`.',
530
+ name: 'items',
531
+ optional: false,
532
+ type: 'NavItem[]',
533
+ },
534
+ {
535
+ doc: 'Base path items are resolved against, e.g. `/home`.',
536
+ name: 'base',
537
+ optional: false,
538
+ type: 'string',
539
+ },
540
+ {
541
+ doc: 'Adds a light/dark toggle at the end of the dock. Off by default — meant for development or a project that deliberately exposes it, not every kiosk install.',
542
+ name: 'showThemeToggle',
543
+ optional: true,
544
+ type: 'boolean',
545
+ },
546
+ ],
547
+ },
548
+ TopBar: {
549
+ doc: "Shared chrome above a dashboard page's content: title (optionally a dashboard switcher), scene shortcuts, and live status (weather, presence, a clock). Composes freely — every prop but `title` is optional.",
550
+ props: [
551
+ {
552
+ doc: "The dashboard's name. Becomes a dashboard switcher when `dashboards` has two or more entries.",
553
+ name: 'title',
554
+ optional: false,
555
+ type: 'string',
556
+ },
557
+ {
558
+ doc: 'Other dashboards to switch to from the title. Under 2 entries renders a plain title.',
559
+ name: 'dashboards',
560
+ optional: true,
561
+ type: 'DashboardOption[]',
562
+ },
563
+ {
564
+ doc: 'Compact circular buttons that fire `scene.turn_on` directly (not the `Tile`-based `SceneButton`); a bare entity ref uses the default icon and an auto-assigned color, or pass `{ entity, icon, color }` to pick either.',
565
+ name: 'scenes',
566
+ optional: true,
567
+ type: '(EntityRef | TopBarScene)[]',
568
+ },
569
+ {
570
+ doc: 'Current weather as a pill with an icon for the sky and a rounded whole-degree reading. A weather entity, like `ha:weather.forecast_home`, shows its real condition; a plain sensor, e.g. an outdoor temperature, gets a fixed sun.',
571
+ name: 'weather',
572
+ optional: true,
573
+ type: 'EntityRef',
574
+ },
575
+ {
576
+ doc: "Your own component(s) for the right-hand side, after the weather: a security mode picker, a custom status. Whatever it is, it sits in the bar's row and is yours to style.",
577
+ name: 'extra',
578
+ optional: true,
579
+ type: 'ReactNode',
580
+ },
581
+ {
582
+ doc: 'A sensor reflecting overall home/away status (e.g. a binary presence sensor), shown as a chip.',
583
+ name: 'presence',
584
+ optional: true,
585
+ type: 'EntityRef',
586
+ },
587
+ {
588
+ doc: 'Individual people, as refs like `ha:person.dan`, shown as an overlapping avatar stack; anyone who is away is dimmed.',
589
+ name: 'people',
590
+ optional: true,
591
+ type: 'EntityRef[]',
592
+ },
593
+ {
594
+ doc: "Avatars show the person's own picture; this only colors the initial of those without one — each person gets one color from the list, always the same one. Optional: a built-in set of six is used unless you want your own, e.g. `['#8B5CF6', '#34D399']`.",
595
+ name: 'presenceColors',
596
+ optional: true,
597
+ type: 'readonly string[]',
598
+ },
599
+ {
600
+ doc: 'Default `true`.',
601
+ name: 'showClock',
602
+ optional: true,
603
+ type: 'boolean',
604
+ },
605
+ {
606
+ doc: 'Short date pill before the weather. Default `true`.',
607
+ name: 'showDate',
608
+ optional: true,
609
+ type: 'boolean',
610
+ },
611
+ {
612
+ doc: "`'auto'` follows the browser's locale (browsers don't read the OS 12/24h setting, so an `en-US` browser shows AM/PM); `'12h'`/`'24h'` force it. Default `'auto'`.",
613
+ name: 'clockFormat',
614
+ optional: true,
615
+ type: "'auto' | '12h' | '24h'",
616
+ },
617
+ {
618
+ doc: 'A status dot at the far right — green when the runtime and every integration are up; click it for the details. Default `true`.',
619
+ name: 'showStatus',
620
+ optional: true,
621
+ type: 'boolean',
622
+ },
623
+ ],
624
+ },
625
+ SystemStatus: {
626
+ doc: 'One dot summarising the runtime link and every integration — green when all are up, amber while something connects, red when something is down; click for per-system detail. `TopBar` renders it from live status, so it only needs the props above for demos.',
627
+ props: [
628
+ {
629
+ doc: 'Overrides the live runtime link status — for demos (the gallery) rather than real dashboards.',
630
+ name: 'link',
631
+ optional: true,
632
+ type: 'LinkStatus',
633
+ },
634
+ {
635
+ doc: 'Overrides the live per-integration statuses, keyed by integration id.',
636
+ name: 'statuses',
637
+ optional: true,
638
+ type: 'Readonly<Record<string, ConnectionStatus>>',
639
+ },
640
+ {
641
+ doc: 'Start with the detail popover open. Default `false`.',
642
+ name: 'defaultOpen',
643
+ optional: true,
644
+ type: 'boolean',
645
+ },
646
+ ],
647
+ },
648
+ PresenceStack: {
649
+ doc: 'Overlapping avatar circles for a handful of `person.*` entities.',
650
+ props: [
651
+ {
652
+ doc: 'People, as refs like `ha:person.dan`: one avatar each (their picture, or a colored initial). Someone who is away is dimmed and grayscale.',
653
+ name: 'entities',
654
+ optional: false,
655
+ type: 'EntityRef[]',
656
+ },
657
+ {
658
+ doc: 'Only colors the initial of people without a picture; each gets one, always the same. Optional: a built-in set of six is used by default.',
659
+ name: 'colors',
660
+ optional: true,
661
+ type: 'readonly string[]',
662
+ },
663
+ ],
664
+ },
665
+ HashsomeProvider: {
666
+ doc: 'Connects the tree to the runtime proxy. Render only on the client.',
667
+ props: [
668
+ {
669
+ doc: 'Runtime WebSocket URL. Defaults to `/ws` on the current origin.',
670
+ name: 'url',
671
+ optional: true,
672
+ type: 'string',
673
+ },
674
+ {
675
+ doc: 'Provide a ready-made client (gallery, tests).',
676
+ name: 'client',
677
+ optional: true,
678
+ type: 'Client',
679
+ },
680
+ {
681
+ doc: 'Options for the default `RemoteClient` (reconnect timing, a custom socket factory). Ignored when `client` is given.',
682
+ name: 'clientOptions',
683
+ optional: true,
684
+ type: "Omit<RemoteClientOptions, 'url'>",
685
+ },
686
+ {
687
+ doc: "`'system'` follows the browser/OS preference and updates live. Default `'dark'`. A `useThemeToggle()` caller (e.g. `NavRail`'s dev toggle) can still override this at runtime.",
688
+ name: 'theme',
689
+ optional: true,
690
+ type: 'ThemeMode',
691
+ },
692
+ {
693
+ doc: "Any Google Fonts family name (e.g. `'Inter'`, `'Roboto'`, `'Poppins'`), loaded dynamically. Default `'Inter'`.",
694
+ name: 'font',
695
+ optional: true,
696
+ type: 'string',
697
+ },
698
+ {
699
+ doc: "`'compact'` for small square displays: tighter spacing, shorter tiles, smaller icon circles. Default `'comfortable'`.",
700
+ name: 'density',
701
+ optional: true,
702
+ type: 'Density',
703
+ },
704
+ {
705
+ doc: 'Partial changes to the built-in theme — colors per light/dark, radii, typography, spacing, density sizes. Pass a constant defined outside the component: a new object each render rebuilds the theme each render.',
706
+ name: 'overrides',
707
+ optional: true,
708
+ type: 'ThemeOverrides',
709
+ },
710
+ {
711
+ doc: 'The app.',
712
+ name: 'children',
713
+ optional: false,
714
+ type: 'ReactNode',
715
+ },
716
+ ],
717
+ },
718
+ };