@esphome/compose-ui 0.1.0 → 0.3.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/dist/index.d.mts +127 -16
- package/dist/index.d.ts +127 -16
- package/dist/index.js +237 -37
- package/dist/index.mjs +217 -37
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _esphome_compose from '@esphome/compose';
|
|
2
|
-
import { EspComposeElement } from '@esphome/compose';
|
|
2
|
+
import { EspComposeElement, TriggerHandler } from '@esphome/compose';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Theme type definitions for the LVGL design system.
|
|
@@ -30,6 +30,17 @@ interface StatusColors {
|
|
|
30
30
|
text: string;
|
|
31
31
|
bgPressed: string;
|
|
32
32
|
}
|
|
33
|
+
interface PartColors {
|
|
34
|
+
/** Primary fill / track color. */
|
|
35
|
+
bg: string;
|
|
36
|
+
/** Knob / handle color. */
|
|
37
|
+
knob: string;
|
|
38
|
+
}
|
|
39
|
+
interface ThemeParts {
|
|
40
|
+
slider: PartColors;
|
|
41
|
+
switch: PartColors;
|
|
42
|
+
arc: PartColors;
|
|
43
|
+
}
|
|
33
44
|
interface ThemeColors {
|
|
34
45
|
primary: StatusColors;
|
|
35
46
|
secondary: StatusColors;
|
|
@@ -63,6 +74,13 @@ interface Theme {
|
|
|
63
74
|
radii: Record<RadiusToken, number>;
|
|
64
75
|
/** Component size scale. */
|
|
65
76
|
sizes: Record<SizeToken, SizeDimensions>;
|
|
77
|
+
/**
|
|
78
|
+
* Widget part colors (slider indicator/knob, switch, arc).
|
|
79
|
+
*
|
|
80
|
+
* Optional — when omitted, `themeToStyleDefinitions()` derives sensible
|
|
81
|
+
* defaults from `colors.primary` and `colors.textPrimary`.
|
|
82
|
+
*/
|
|
83
|
+
parts?: ThemeParts;
|
|
66
84
|
}
|
|
67
85
|
|
|
68
86
|
/** The theme context — defaults to `darkTheme` when no provider is present. */
|
|
@@ -130,6 +148,98 @@ declare function fontDefToLvgl(def: FontDef): string;
|
|
|
130
148
|
/** Resolve a radius token or pass through a raw pixel value. */
|
|
131
149
|
declare function resolveRadius(value: RadiusToken | number): number;
|
|
132
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Theme → LVGL bridge.
|
|
153
|
+
*
|
|
154
|
+
* Converts the high-level `Theme` token system into:
|
|
155
|
+
* 1. `style_definitions` — named style bundles referenced by DS components
|
|
156
|
+
* 2. `theme` — static per-widget-type defaults for unthemed raw LVGL widgets
|
|
157
|
+
* 3. `createThemeSwitchActions()` — runtime theme switching via `lvgl.style.update`
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
interface StyleDefinition {
|
|
161
|
+
id: string;
|
|
162
|
+
[prop: string]: unknown;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Convert a `Theme` into an array of ESPHome `style_definitions` entries.
|
|
166
|
+
*
|
|
167
|
+
* Each entry is a plain object with snake_case keys matching the LVGL YAML
|
|
168
|
+
* schema. Colors remain as `#RRGGBB` strings — the serializer converts them
|
|
169
|
+
* to `0xRRGGBB` automatically.
|
|
170
|
+
*/
|
|
171
|
+
declare function themeToStyleDefinitions(theme: Theme): StyleDefinition[];
|
|
172
|
+
/**
|
|
173
|
+
* Build the LVGL `theme:` block — static defaults applied to all widgets of
|
|
174
|
+
* a given type. This is the fallback for raw `<lvgl-*>` elements that don't
|
|
175
|
+
* use `styles:` references.
|
|
176
|
+
*
|
|
177
|
+
* NOTE: The `theme:` block is NOT runtime-updatable. Only `style_definitions`
|
|
178
|
+
* (via `lvgl.style.update`) support runtime switching.
|
|
179
|
+
*/
|
|
180
|
+
declare function themeToLvglTheme(theme: Theme): Record<string, unknown>;
|
|
181
|
+
/**
|
|
182
|
+
* Build the props to spread on the `<lvgl>` element.
|
|
183
|
+
*
|
|
184
|
+
* ```tsx
|
|
185
|
+
* <lvgl displays={[ref]} {...createLvglThemeProps(darkTheme)}>
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function createLvglThemeProps(theme: Theme): {
|
|
189
|
+
styleDefinitions: StyleDefinition[];
|
|
190
|
+
theme: Record<string, unknown>;
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Apply a theme at runtime inside a trigger function.
|
|
194
|
+
*
|
|
195
|
+
* The ESPCompose compiler recognises `applyTheme()` calls inside trigger
|
|
196
|
+
* bodies and spreads the resulting `lvgl.style.update` actions into the
|
|
197
|
+
* action list.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```tsx
|
|
201
|
+
* <Button
|
|
202
|
+
* text="Dark mode"
|
|
203
|
+
* onPress={() => { applyTheme(darkTheme); }}
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
*
|
|
207
|
+
* @espcomposeAction applyTheme
|
|
208
|
+
*/
|
|
209
|
+
declare function applyTheme(theme: Theme): Array<Record<string, unknown>>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* LVGL style definition ID constants.
|
|
213
|
+
*
|
|
214
|
+
* Every design-system component references these IDs via the LVGL `styles:`
|
|
215
|
+
* prop instead of inlining visual values. The IDs correspond 1-to-1 with
|
|
216
|
+
* entries generated by `themeToStyleDefinitions()` in `bridge.ts`.
|
|
217
|
+
*
|
|
218
|
+
* Naming: `ds_{category}[_{variant}]`
|
|
219
|
+
* NOTE: ESPHome requires underscores in IDs — dashes are not allowed.
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
declare const STYLE_BG = "ds_bg";
|
|
223
|
+
declare const STYLE_SURFACE = "ds_surface";
|
|
224
|
+
declare const STYLE_SURFACE_ALT = "ds_surface_alt";
|
|
225
|
+
declare const STYLE_BORDER = "ds_border";
|
|
226
|
+
declare const STYLE_TEXT_PRIMARY = "ds_text_primary";
|
|
227
|
+
declare const STYLE_TEXT_SECONDARY = "ds_text_secondary";
|
|
228
|
+
declare const STYLE_TEXT_DISABLED = "ds_text_disabled";
|
|
229
|
+
/** Typography variant style IDs. */
|
|
230
|
+
declare const STYLE_TEXT_VARIANT: Record<TextVariant, string>;
|
|
231
|
+
type ButtonVariant$1 = 'solid' | 'outline';
|
|
232
|
+
/** Style ID for a status button container. */
|
|
233
|
+
declare function statusStyleId(status: StatusToken, variant: ButtonVariant$1): string;
|
|
234
|
+
/** Style ID for a status button's inner label text. */
|
|
235
|
+
declare function statusTextStyleId(status: StatusToken, variant: ButtonVariant$1): string;
|
|
236
|
+
declare const STYLE_SLIDER_INDICATOR = "ds_slider_indicator";
|
|
237
|
+
declare const STYLE_SLIDER_KNOB = "ds_slider_knob";
|
|
238
|
+
declare const STYLE_SWITCH_INDICATOR = "ds_switch_indicator";
|
|
239
|
+
declare const STYLE_SWITCH_KNOB = "ds_switch_knob";
|
|
240
|
+
declare const STYLE_ARC_INDICATOR = "ds_arc_indicator";
|
|
241
|
+
declare const STYLE_ARC_KNOB = "ds_arc_knob";
|
|
242
|
+
|
|
133
243
|
/**
|
|
134
244
|
* Intent constants for @esphome/compose-ui design system.
|
|
135
245
|
*
|
|
@@ -151,7 +261,7 @@ interface ScreenProps {
|
|
|
151
261
|
padding?: SpacingToken | number;
|
|
152
262
|
/** Skip this page in the page list. */
|
|
153
263
|
skip?: boolean;
|
|
154
|
-
/** Background color override (hex). If
|
|
264
|
+
/** Background color override (hex). If set, overrides the style definition. */
|
|
155
265
|
bgColor?: string;
|
|
156
266
|
/** Border width in pixels. Default: 0. */
|
|
157
267
|
borderWidth?: number;
|
|
@@ -161,7 +271,7 @@ interface ScreenProps {
|
|
|
161
271
|
/**
|
|
162
272
|
* Screen — a top-level LVGL page container.
|
|
163
273
|
*
|
|
164
|
-
* Applies the active theme's background color by default.
|
|
274
|
+
* Applies the active theme's background color by default via style reference.
|
|
165
275
|
*
|
|
166
276
|
* @example
|
|
167
277
|
* <Screen padding="lg">
|
|
@@ -389,7 +499,7 @@ interface TextProps {
|
|
|
389
499
|
text?: string;
|
|
390
500
|
/** Text alignment within the label. */
|
|
391
501
|
align?: 'LEFT' | 'CENTER' | 'RIGHT' | 'AUTO';
|
|
392
|
-
/** Text color (hex). If omitted,
|
|
502
|
+
/** Text color (hex). If omitted, inherits from the variant style definition. */
|
|
393
503
|
color?: string;
|
|
394
504
|
/** Long text mode. */
|
|
395
505
|
longMode?: 'WRAP' | 'DOT' | 'SCROLL' | 'SCROLL_CIRCULAR' | 'CLIP';
|
|
@@ -427,8 +537,8 @@ interface ButtonProps {
|
|
|
427
537
|
width?: number | string;
|
|
428
538
|
/** Height override. */
|
|
429
539
|
height?: number | string;
|
|
430
|
-
/** Press handler (ESPHome
|
|
431
|
-
onPress?:
|
|
540
|
+
/** Press handler (ESPHome trigger function). */
|
|
541
|
+
onPress?: TriggerHandler;
|
|
432
542
|
}
|
|
433
543
|
/**
|
|
434
544
|
* Button — a styled, clickable button with a label.
|
|
@@ -445,7 +555,7 @@ interface CardProps {
|
|
|
445
555
|
padding?: SpacingToken | number;
|
|
446
556
|
/** Corner radius. Default: 'md'. */
|
|
447
557
|
radius?: RadiusToken | number;
|
|
448
|
-
/** Background color (hex).
|
|
558
|
+
/** Background color override (hex). If set, overrides the style definition. */
|
|
449
559
|
bgColor?: string;
|
|
450
560
|
/** Border color (hex). */
|
|
451
561
|
borderColor?: string;
|
|
@@ -475,7 +585,9 @@ interface SliderFieldProps {
|
|
|
475
585
|
/** Bound value (sensor or entity reference). */
|
|
476
586
|
value?: unknown;
|
|
477
587
|
/** Change handler (ESPHome action). */
|
|
478
|
-
onChange?:
|
|
588
|
+
onChange?: TriggerHandler<{
|
|
589
|
+
x: number;
|
|
590
|
+
}>;
|
|
479
591
|
/** Minimum value. Default: 0. */
|
|
480
592
|
min?: number;
|
|
481
593
|
/** Maximum value. Default: 100. */
|
|
@@ -493,18 +605,15 @@ interface SliderFieldProps {
|
|
|
493
605
|
*/
|
|
494
606
|
declare const SliderField: _esphome_compose.IntentComponent<SliderFieldProps, readonly ["lvgl:widget"], readonly [], undefined, undefined>;
|
|
495
607
|
|
|
496
|
-
/**
|
|
497
|
-
* SwitchField — a label + switch in a row layout.
|
|
498
|
-
*
|
|
499
|
-
* Compiles to a container with a label and a switch widget.
|
|
500
|
-
*/
|
|
501
608
|
interface SwitchFieldProps {
|
|
502
609
|
/** Label text displayed next to the switch. */
|
|
503
610
|
label: string;
|
|
504
611
|
/** Bound value (sensor or entity reference). */
|
|
505
612
|
value?: unknown;
|
|
506
613
|
/** Change handler (ESPHome action). */
|
|
507
|
-
onChange?:
|
|
614
|
+
onChange?: TriggerHandler<{
|
|
615
|
+
x: boolean;
|
|
616
|
+
}>;
|
|
508
617
|
/** Width of the field container. */
|
|
509
618
|
width?: number | string;
|
|
510
619
|
}
|
|
@@ -524,7 +633,9 @@ interface DropdownFieldProps {
|
|
|
524
633
|
/** Bound selection index. */
|
|
525
634
|
value?: unknown;
|
|
526
635
|
/** Change handler (ESPHome action). */
|
|
527
|
-
onChange?:
|
|
636
|
+
onChange?: TriggerHandler<{
|
|
637
|
+
x: number;
|
|
638
|
+
}>;
|
|
528
639
|
/** Gap between label and dropdown. Default: 'xs'. */
|
|
529
640
|
gap?: SpacingToken | number;
|
|
530
641
|
/** Width of the field container. */
|
|
@@ -538,4 +649,4 @@ interface DropdownFieldProps {
|
|
|
538
649
|
*/
|
|
539
650
|
declare const DropdownField: _esphome_compose.IntentComponent<DropdownFieldProps, readonly ["lvgl:widget"], readonly [], undefined, undefined>;
|
|
540
651
|
|
|
541
|
-
export { Button, COMPOSE_UI_INTENTS, Card, Col, DropdownField, type FontDef, Grid, GridItem, HStack, type RadiusToken, Row, Screen, type SizeDimensions, type SizeToken, SliderField, Space, type SpacingToken, type StatusColors, type StatusToken, SwitchField, Text, type TextVariant, type Theme, type ThemeColors, ThemeContext, ThemeProvider, type ThemeTypography, type TrackSize, VStack, darkTheme, fontDefToLvgl, lightTheme, resolveRadius, resolveSize, resolveSpacing, resolveStatus, resolveTypography, themeFromJSON, themeToJSON, useTheme };
|
|
652
|
+
export { Button, COMPOSE_UI_INTENTS, Card, Col, DropdownField, type FontDef, Grid, GridItem, HStack, type PartColors, type RadiusToken, Row, STYLE_ARC_INDICATOR, STYLE_ARC_KNOB, STYLE_BG, STYLE_BORDER, STYLE_SLIDER_INDICATOR, STYLE_SLIDER_KNOB, STYLE_SURFACE, STYLE_SURFACE_ALT, STYLE_SWITCH_INDICATOR, STYLE_SWITCH_KNOB, STYLE_TEXT_DISABLED, STYLE_TEXT_PRIMARY, STYLE_TEXT_SECONDARY, STYLE_TEXT_VARIANT, Screen, type SizeDimensions, type SizeToken, SliderField, Space, type SpacingToken, type StatusColors, type StatusToken, type StyleDefinition, SwitchField, Text, type TextVariant, type Theme, type ThemeColors, ThemeContext, type ThemeParts, ThemeProvider, type ThemeTypography, type TrackSize, VStack, applyTheme, createLvglThemeProps, darkTheme, fontDefToLvgl, lightTheme, resolveRadius, resolveSize, resolveSpacing, resolveStatus, resolveTypography, statusStyleId, statusTextStyleId, themeFromJSON, themeToJSON, themeToLvglTheme, themeToStyleDefinitions, useTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _esphome_compose from '@esphome/compose';
|
|
2
|
-
import { EspComposeElement } from '@esphome/compose';
|
|
2
|
+
import { EspComposeElement, TriggerHandler } from '@esphome/compose';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Theme type definitions for the LVGL design system.
|
|
@@ -30,6 +30,17 @@ interface StatusColors {
|
|
|
30
30
|
text: string;
|
|
31
31
|
bgPressed: string;
|
|
32
32
|
}
|
|
33
|
+
interface PartColors {
|
|
34
|
+
/** Primary fill / track color. */
|
|
35
|
+
bg: string;
|
|
36
|
+
/** Knob / handle color. */
|
|
37
|
+
knob: string;
|
|
38
|
+
}
|
|
39
|
+
interface ThemeParts {
|
|
40
|
+
slider: PartColors;
|
|
41
|
+
switch: PartColors;
|
|
42
|
+
arc: PartColors;
|
|
43
|
+
}
|
|
33
44
|
interface ThemeColors {
|
|
34
45
|
primary: StatusColors;
|
|
35
46
|
secondary: StatusColors;
|
|
@@ -63,6 +74,13 @@ interface Theme {
|
|
|
63
74
|
radii: Record<RadiusToken, number>;
|
|
64
75
|
/** Component size scale. */
|
|
65
76
|
sizes: Record<SizeToken, SizeDimensions>;
|
|
77
|
+
/**
|
|
78
|
+
* Widget part colors (slider indicator/knob, switch, arc).
|
|
79
|
+
*
|
|
80
|
+
* Optional — when omitted, `themeToStyleDefinitions()` derives sensible
|
|
81
|
+
* defaults from `colors.primary` and `colors.textPrimary`.
|
|
82
|
+
*/
|
|
83
|
+
parts?: ThemeParts;
|
|
66
84
|
}
|
|
67
85
|
|
|
68
86
|
/** The theme context — defaults to `darkTheme` when no provider is present. */
|
|
@@ -130,6 +148,98 @@ declare function fontDefToLvgl(def: FontDef): string;
|
|
|
130
148
|
/** Resolve a radius token or pass through a raw pixel value. */
|
|
131
149
|
declare function resolveRadius(value: RadiusToken | number): number;
|
|
132
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Theme → LVGL bridge.
|
|
153
|
+
*
|
|
154
|
+
* Converts the high-level `Theme` token system into:
|
|
155
|
+
* 1. `style_definitions` — named style bundles referenced by DS components
|
|
156
|
+
* 2. `theme` — static per-widget-type defaults for unthemed raw LVGL widgets
|
|
157
|
+
* 3. `createThemeSwitchActions()` — runtime theme switching via `lvgl.style.update`
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
interface StyleDefinition {
|
|
161
|
+
id: string;
|
|
162
|
+
[prop: string]: unknown;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Convert a `Theme` into an array of ESPHome `style_definitions` entries.
|
|
166
|
+
*
|
|
167
|
+
* Each entry is a plain object with snake_case keys matching the LVGL YAML
|
|
168
|
+
* schema. Colors remain as `#RRGGBB` strings — the serializer converts them
|
|
169
|
+
* to `0xRRGGBB` automatically.
|
|
170
|
+
*/
|
|
171
|
+
declare function themeToStyleDefinitions(theme: Theme): StyleDefinition[];
|
|
172
|
+
/**
|
|
173
|
+
* Build the LVGL `theme:` block — static defaults applied to all widgets of
|
|
174
|
+
* a given type. This is the fallback for raw `<lvgl-*>` elements that don't
|
|
175
|
+
* use `styles:` references.
|
|
176
|
+
*
|
|
177
|
+
* NOTE: The `theme:` block is NOT runtime-updatable. Only `style_definitions`
|
|
178
|
+
* (via `lvgl.style.update`) support runtime switching.
|
|
179
|
+
*/
|
|
180
|
+
declare function themeToLvglTheme(theme: Theme): Record<string, unknown>;
|
|
181
|
+
/**
|
|
182
|
+
* Build the props to spread on the `<lvgl>` element.
|
|
183
|
+
*
|
|
184
|
+
* ```tsx
|
|
185
|
+
* <lvgl displays={[ref]} {...createLvglThemeProps(darkTheme)}>
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function createLvglThemeProps(theme: Theme): {
|
|
189
|
+
styleDefinitions: StyleDefinition[];
|
|
190
|
+
theme: Record<string, unknown>;
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Apply a theme at runtime inside a trigger function.
|
|
194
|
+
*
|
|
195
|
+
* The ESPCompose compiler recognises `applyTheme()` calls inside trigger
|
|
196
|
+
* bodies and spreads the resulting `lvgl.style.update` actions into the
|
|
197
|
+
* action list.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```tsx
|
|
201
|
+
* <Button
|
|
202
|
+
* text="Dark mode"
|
|
203
|
+
* onPress={() => { applyTheme(darkTheme); }}
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
*
|
|
207
|
+
* @espcomposeAction applyTheme
|
|
208
|
+
*/
|
|
209
|
+
declare function applyTheme(theme: Theme): Array<Record<string, unknown>>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* LVGL style definition ID constants.
|
|
213
|
+
*
|
|
214
|
+
* Every design-system component references these IDs via the LVGL `styles:`
|
|
215
|
+
* prop instead of inlining visual values. The IDs correspond 1-to-1 with
|
|
216
|
+
* entries generated by `themeToStyleDefinitions()` in `bridge.ts`.
|
|
217
|
+
*
|
|
218
|
+
* Naming: `ds_{category}[_{variant}]`
|
|
219
|
+
* NOTE: ESPHome requires underscores in IDs — dashes are not allowed.
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
declare const STYLE_BG = "ds_bg";
|
|
223
|
+
declare const STYLE_SURFACE = "ds_surface";
|
|
224
|
+
declare const STYLE_SURFACE_ALT = "ds_surface_alt";
|
|
225
|
+
declare const STYLE_BORDER = "ds_border";
|
|
226
|
+
declare const STYLE_TEXT_PRIMARY = "ds_text_primary";
|
|
227
|
+
declare const STYLE_TEXT_SECONDARY = "ds_text_secondary";
|
|
228
|
+
declare const STYLE_TEXT_DISABLED = "ds_text_disabled";
|
|
229
|
+
/** Typography variant style IDs. */
|
|
230
|
+
declare const STYLE_TEXT_VARIANT: Record<TextVariant, string>;
|
|
231
|
+
type ButtonVariant$1 = 'solid' | 'outline';
|
|
232
|
+
/** Style ID for a status button container. */
|
|
233
|
+
declare function statusStyleId(status: StatusToken, variant: ButtonVariant$1): string;
|
|
234
|
+
/** Style ID for a status button's inner label text. */
|
|
235
|
+
declare function statusTextStyleId(status: StatusToken, variant: ButtonVariant$1): string;
|
|
236
|
+
declare const STYLE_SLIDER_INDICATOR = "ds_slider_indicator";
|
|
237
|
+
declare const STYLE_SLIDER_KNOB = "ds_slider_knob";
|
|
238
|
+
declare const STYLE_SWITCH_INDICATOR = "ds_switch_indicator";
|
|
239
|
+
declare const STYLE_SWITCH_KNOB = "ds_switch_knob";
|
|
240
|
+
declare const STYLE_ARC_INDICATOR = "ds_arc_indicator";
|
|
241
|
+
declare const STYLE_ARC_KNOB = "ds_arc_knob";
|
|
242
|
+
|
|
133
243
|
/**
|
|
134
244
|
* Intent constants for @esphome/compose-ui design system.
|
|
135
245
|
*
|
|
@@ -151,7 +261,7 @@ interface ScreenProps {
|
|
|
151
261
|
padding?: SpacingToken | number;
|
|
152
262
|
/** Skip this page in the page list. */
|
|
153
263
|
skip?: boolean;
|
|
154
|
-
/** Background color override (hex). If
|
|
264
|
+
/** Background color override (hex). If set, overrides the style definition. */
|
|
155
265
|
bgColor?: string;
|
|
156
266
|
/** Border width in pixels. Default: 0. */
|
|
157
267
|
borderWidth?: number;
|
|
@@ -161,7 +271,7 @@ interface ScreenProps {
|
|
|
161
271
|
/**
|
|
162
272
|
* Screen — a top-level LVGL page container.
|
|
163
273
|
*
|
|
164
|
-
* Applies the active theme's background color by default.
|
|
274
|
+
* Applies the active theme's background color by default via style reference.
|
|
165
275
|
*
|
|
166
276
|
* @example
|
|
167
277
|
* <Screen padding="lg">
|
|
@@ -389,7 +499,7 @@ interface TextProps {
|
|
|
389
499
|
text?: string;
|
|
390
500
|
/** Text alignment within the label. */
|
|
391
501
|
align?: 'LEFT' | 'CENTER' | 'RIGHT' | 'AUTO';
|
|
392
|
-
/** Text color (hex). If omitted,
|
|
502
|
+
/** Text color (hex). If omitted, inherits from the variant style definition. */
|
|
393
503
|
color?: string;
|
|
394
504
|
/** Long text mode. */
|
|
395
505
|
longMode?: 'WRAP' | 'DOT' | 'SCROLL' | 'SCROLL_CIRCULAR' | 'CLIP';
|
|
@@ -427,8 +537,8 @@ interface ButtonProps {
|
|
|
427
537
|
width?: number | string;
|
|
428
538
|
/** Height override. */
|
|
429
539
|
height?: number | string;
|
|
430
|
-
/** Press handler (ESPHome
|
|
431
|
-
onPress?:
|
|
540
|
+
/** Press handler (ESPHome trigger function). */
|
|
541
|
+
onPress?: TriggerHandler;
|
|
432
542
|
}
|
|
433
543
|
/**
|
|
434
544
|
* Button — a styled, clickable button with a label.
|
|
@@ -445,7 +555,7 @@ interface CardProps {
|
|
|
445
555
|
padding?: SpacingToken | number;
|
|
446
556
|
/** Corner radius. Default: 'md'. */
|
|
447
557
|
radius?: RadiusToken | number;
|
|
448
|
-
/** Background color (hex).
|
|
558
|
+
/** Background color override (hex). If set, overrides the style definition. */
|
|
449
559
|
bgColor?: string;
|
|
450
560
|
/** Border color (hex). */
|
|
451
561
|
borderColor?: string;
|
|
@@ -475,7 +585,9 @@ interface SliderFieldProps {
|
|
|
475
585
|
/** Bound value (sensor or entity reference). */
|
|
476
586
|
value?: unknown;
|
|
477
587
|
/** Change handler (ESPHome action). */
|
|
478
|
-
onChange?:
|
|
588
|
+
onChange?: TriggerHandler<{
|
|
589
|
+
x: number;
|
|
590
|
+
}>;
|
|
479
591
|
/** Minimum value. Default: 0. */
|
|
480
592
|
min?: number;
|
|
481
593
|
/** Maximum value. Default: 100. */
|
|
@@ -493,18 +605,15 @@ interface SliderFieldProps {
|
|
|
493
605
|
*/
|
|
494
606
|
declare const SliderField: _esphome_compose.IntentComponent<SliderFieldProps, readonly ["lvgl:widget"], readonly [], undefined, undefined>;
|
|
495
607
|
|
|
496
|
-
/**
|
|
497
|
-
* SwitchField — a label + switch in a row layout.
|
|
498
|
-
*
|
|
499
|
-
* Compiles to a container with a label and a switch widget.
|
|
500
|
-
*/
|
|
501
608
|
interface SwitchFieldProps {
|
|
502
609
|
/** Label text displayed next to the switch. */
|
|
503
610
|
label: string;
|
|
504
611
|
/** Bound value (sensor or entity reference). */
|
|
505
612
|
value?: unknown;
|
|
506
613
|
/** Change handler (ESPHome action). */
|
|
507
|
-
onChange?:
|
|
614
|
+
onChange?: TriggerHandler<{
|
|
615
|
+
x: boolean;
|
|
616
|
+
}>;
|
|
508
617
|
/** Width of the field container. */
|
|
509
618
|
width?: number | string;
|
|
510
619
|
}
|
|
@@ -524,7 +633,9 @@ interface DropdownFieldProps {
|
|
|
524
633
|
/** Bound selection index. */
|
|
525
634
|
value?: unknown;
|
|
526
635
|
/** Change handler (ESPHome action). */
|
|
527
|
-
onChange?:
|
|
636
|
+
onChange?: TriggerHandler<{
|
|
637
|
+
x: number;
|
|
638
|
+
}>;
|
|
528
639
|
/** Gap between label and dropdown. Default: 'xs'. */
|
|
529
640
|
gap?: SpacingToken | number;
|
|
530
641
|
/** Width of the field container. */
|
|
@@ -538,4 +649,4 @@ interface DropdownFieldProps {
|
|
|
538
649
|
*/
|
|
539
650
|
declare const DropdownField: _esphome_compose.IntentComponent<DropdownFieldProps, readonly ["lvgl:widget"], readonly [], undefined, undefined>;
|
|
540
651
|
|
|
541
|
-
export { Button, COMPOSE_UI_INTENTS, Card, Col, DropdownField, type FontDef, Grid, GridItem, HStack, type RadiusToken, Row, Screen, type SizeDimensions, type SizeToken, SliderField, Space, type SpacingToken, type StatusColors, type StatusToken, SwitchField, Text, type TextVariant, type Theme, type ThemeColors, ThemeContext, ThemeProvider, type ThemeTypography, type TrackSize, VStack, darkTheme, fontDefToLvgl, lightTheme, resolveRadius, resolveSize, resolveSpacing, resolveStatus, resolveTypography, themeFromJSON, themeToJSON, useTheme };
|
|
652
|
+
export { Button, COMPOSE_UI_INTENTS, Card, Col, DropdownField, type FontDef, Grid, GridItem, HStack, type PartColors, type RadiusToken, Row, STYLE_ARC_INDICATOR, STYLE_ARC_KNOB, STYLE_BG, STYLE_BORDER, STYLE_SLIDER_INDICATOR, STYLE_SLIDER_KNOB, STYLE_SURFACE, STYLE_SURFACE_ALT, STYLE_SWITCH_INDICATOR, STYLE_SWITCH_KNOB, STYLE_TEXT_DISABLED, STYLE_TEXT_PRIMARY, STYLE_TEXT_SECONDARY, STYLE_TEXT_VARIANT, Screen, type SizeDimensions, type SizeToken, SliderField, Space, type SpacingToken, type StatusColors, type StatusToken, type StyleDefinition, SwitchField, Text, type TextVariant, type Theme, type ThemeColors, ThemeContext, type ThemeParts, ThemeProvider, type ThemeTypography, type TrackSize, VStack, applyTheme, createLvglThemeProps, darkTheme, fontDefToLvgl, lightTheme, resolveRadius, resolveSize, resolveSpacing, resolveStatus, resolveTypography, statusStyleId, statusTextStyleId, themeFromJSON, themeToJSON, themeToLvglTheme, themeToStyleDefinitions, useTheme };
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,20 @@ __export(index_exports, {
|
|
|
29
29
|
GridItem: () => GridItem,
|
|
30
30
|
HStack: () => HStack,
|
|
31
31
|
Row: () => Row,
|
|
32
|
+
STYLE_ARC_INDICATOR: () => STYLE_ARC_INDICATOR,
|
|
33
|
+
STYLE_ARC_KNOB: () => STYLE_ARC_KNOB,
|
|
34
|
+
STYLE_BG: () => STYLE_BG,
|
|
35
|
+
STYLE_BORDER: () => STYLE_BORDER,
|
|
36
|
+
STYLE_SLIDER_INDICATOR: () => STYLE_SLIDER_INDICATOR,
|
|
37
|
+
STYLE_SLIDER_KNOB: () => STYLE_SLIDER_KNOB,
|
|
38
|
+
STYLE_SURFACE: () => STYLE_SURFACE,
|
|
39
|
+
STYLE_SURFACE_ALT: () => STYLE_SURFACE_ALT,
|
|
40
|
+
STYLE_SWITCH_INDICATOR: () => STYLE_SWITCH_INDICATOR,
|
|
41
|
+
STYLE_SWITCH_KNOB: () => STYLE_SWITCH_KNOB,
|
|
42
|
+
STYLE_TEXT_DISABLED: () => STYLE_TEXT_DISABLED,
|
|
43
|
+
STYLE_TEXT_PRIMARY: () => STYLE_TEXT_PRIMARY,
|
|
44
|
+
STYLE_TEXT_SECONDARY: () => STYLE_TEXT_SECONDARY,
|
|
45
|
+
STYLE_TEXT_VARIANT: () => STYLE_TEXT_VARIANT,
|
|
32
46
|
Screen: () => Screen,
|
|
33
47
|
SliderField: () => SliderField,
|
|
34
48
|
Space: () => Space,
|
|
@@ -37,6 +51,8 @@ __export(index_exports, {
|
|
|
37
51
|
ThemeContext: () => ThemeContext,
|
|
38
52
|
ThemeProvider: () => ThemeProvider,
|
|
39
53
|
VStack: () => VStack,
|
|
54
|
+
applyTheme: () => applyTheme,
|
|
55
|
+
createLvglThemeProps: () => createLvglThemeProps,
|
|
40
56
|
darkTheme: () => darkTheme,
|
|
41
57
|
fontDefToLvgl: () => fontDefToLvgl,
|
|
42
58
|
lightTheme: () => lightTheme,
|
|
@@ -45,8 +61,12 @@ __export(index_exports, {
|
|
|
45
61
|
resolveSpacing: () => resolveSpacing,
|
|
46
62
|
resolveStatus: () => resolveStatus,
|
|
47
63
|
resolveTypography: () => resolveTypography,
|
|
64
|
+
statusStyleId: () => statusStyleId,
|
|
65
|
+
statusTextStyleId: () => statusTextStyleId,
|
|
48
66
|
themeFromJSON: () => themeFromJSON,
|
|
49
67
|
themeToJSON: () => themeToJSON,
|
|
68
|
+
themeToLvglTheme: () => themeToLvglTheme,
|
|
69
|
+
themeToStyleDefinitions: () => themeToStyleDefinitions,
|
|
50
70
|
useTheme: () => useTheme
|
|
51
71
|
});
|
|
52
72
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -98,6 +118,11 @@ var darkTheme = {
|
|
|
98
118
|
md: { height: 44, fontSize: 16, paddingX: 16, paddingY: 8 },
|
|
99
119
|
lg: { height: 52, fontSize: 18, paddingX: 20, paddingY: 10 },
|
|
100
120
|
xl: { height: 64, fontSize: 22, paddingX: 24, paddingY: 12 }
|
|
121
|
+
},
|
|
122
|
+
parts: {
|
|
123
|
+
slider: { bg: "#1E88E5", knob: "#E0E0E0" },
|
|
124
|
+
switch: { bg: "#1E88E5", knob: "#E0E0E0" },
|
|
125
|
+
arc: { bg: "#1E88E5", knob: "#E0E0E0" }
|
|
101
126
|
}
|
|
102
127
|
};
|
|
103
128
|
|
|
@@ -152,6 +177,11 @@ var lightTheme = {
|
|
|
152
177
|
md: { height: 44, fontSize: 16, paddingX: 16, paddingY: 8 },
|
|
153
178
|
lg: { height: 52, fontSize: 18, paddingX: 20, paddingY: 10 },
|
|
154
179
|
xl: { height: 64, fontSize: 22, paddingX: 24, paddingY: 12 }
|
|
180
|
+
},
|
|
181
|
+
parts: {
|
|
182
|
+
slider: { bg: "#1565C0", knob: "#212121" },
|
|
183
|
+
switch: { bg: "#1565C0", knob: "#212121" },
|
|
184
|
+
arc: { bg: "#1565C0", knob: "#212121" }
|
|
155
185
|
}
|
|
156
186
|
};
|
|
157
187
|
|
|
@@ -185,6 +215,169 @@ function resolveRadius(value) {
|
|
|
185
215
|
return useTheme().radii[value];
|
|
186
216
|
}
|
|
187
217
|
|
|
218
|
+
// src/theme/style-ids.ts
|
|
219
|
+
var STYLE_BG = "ds_bg";
|
|
220
|
+
var STYLE_SURFACE = "ds_surface";
|
|
221
|
+
var STYLE_SURFACE_ALT = "ds_surface_alt";
|
|
222
|
+
var STYLE_BORDER = "ds_border";
|
|
223
|
+
var STYLE_TEXT_PRIMARY = "ds_text_primary";
|
|
224
|
+
var STYLE_TEXT_SECONDARY = "ds_text_secondary";
|
|
225
|
+
var STYLE_TEXT_DISABLED = "ds_text_disabled";
|
|
226
|
+
var STYLE_TEXT_VARIANT = {
|
|
227
|
+
title: "ds_text_title",
|
|
228
|
+
subtitle: "ds_text_subtitle",
|
|
229
|
+
body: "ds_text_body",
|
|
230
|
+
caption: "ds_text_caption"
|
|
231
|
+
};
|
|
232
|
+
function statusStyleId(status, variant) {
|
|
233
|
+
return `ds_status_${status}_${variant}`;
|
|
234
|
+
}
|
|
235
|
+
function statusTextStyleId(status, variant) {
|
|
236
|
+
return `ds_status_${status}_${variant}_text`;
|
|
237
|
+
}
|
|
238
|
+
var ALL_STATUSES = [
|
|
239
|
+
"primary",
|
|
240
|
+
"secondary",
|
|
241
|
+
"success",
|
|
242
|
+
"warning",
|
|
243
|
+
"danger"
|
|
244
|
+
];
|
|
245
|
+
var STYLE_SLIDER_INDICATOR = "ds_slider_indicator";
|
|
246
|
+
var STYLE_SLIDER_KNOB = "ds_slider_knob";
|
|
247
|
+
var STYLE_SWITCH_INDICATOR = "ds_switch_indicator";
|
|
248
|
+
var STYLE_SWITCH_KNOB = "ds_switch_knob";
|
|
249
|
+
var STYLE_ARC_INDICATOR = "ds_arc_indicator";
|
|
250
|
+
var STYLE_ARC_KNOB = "ds_arc_knob";
|
|
251
|
+
|
|
252
|
+
// src/theme/bridge.ts
|
|
253
|
+
function resolveParts(theme) {
|
|
254
|
+
if (theme.parts) return theme.parts;
|
|
255
|
+
return {
|
|
256
|
+
slider: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary },
|
|
257
|
+
switch: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary },
|
|
258
|
+
arc: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary }
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function themeToStyleDefinitions(theme) {
|
|
262
|
+
const defs = [];
|
|
263
|
+
const bodyFont = fontDefToLvgl(theme.typography.body);
|
|
264
|
+
defs.push({ id: STYLE_BG, bg_color: theme.colors.background });
|
|
265
|
+
defs.push({ id: STYLE_SURFACE, bg_color: theme.colors.surface });
|
|
266
|
+
defs.push({ id: STYLE_SURFACE_ALT, bg_color: theme.colors.surfaceAlt });
|
|
267
|
+
defs.push({ id: STYLE_BORDER, border_color: theme.colors.border });
|
|
268
|
+
defs.push({ id: STYLE_TEXT_PRIMARY, text_color: theme.colors.textPrimary, text_font: bodyFont });
|
|
269
|
+
defs.push({ id: STYLE_TEXT_SECONDARY, text_color: theme.colors.textSecondary, text_font: bodyFont });
|
|
270
|
+
defs.push({ id: STYLE_TEXT_DISABLED, text_color: theme.colors.textDisabled, text_font: bodyFont });
|
|
271
|
+
for (const variant of ["title", "subtitle", "body", "caption"]) {
|
|
272
|
+
const font = fontDefToLvgl(theme.typography[variant]);
|
|
273
|
+
defs.push({
|
|
274
|
+
id: STYLE_TEXT_VARIANT[variant],
|
|
275
|
+
text_color: theme.colors.textPrimary,
|
|
276
|
+
text_font: font
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
for (const status of ALL_STATUSES) {
|
|
280
|
+
const sc = theme.colors[status];
|
|
281
|
+
defs.push({
|
|
282
|
+
id: statusStyleId(status, "solid"),
|
|
283
|
+
bg_color: sc.bg
|
|
284
|
+
});
|
|
285
|
+
defs.push({
|
|
286
|
+
id: statusTextStyleId(status, "solid"),
|
|
287
|
+
text_color: sc.text
|
|
288
|
+
});
|
|
289
|
+
defs.push({
|
|
290
|
+
id: statusStyleId(status, "outline"),
|
|
291
|
+
bg_opa: "TRANSP",
|
|
292
|
+
border_color: sc.bg,
|
|
293
|
+
border_width: 2
|
|
294
|
+
});
|
|
295
|
+
defs.push({
|
|
296
|
+
id: statusTextStyleId(status, "outline"),
|
|
297
|
+
text_color: sc.bg
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
const parts = resolveParts(theme);
|
|
301
|
+
defs.push({ id: STYLE_SLIDER_INDICATOR, bg_color: parts.slider.bg });
|
|
302
|
+
defs.push({ id: STYLE_SLIDER_KNOB, bg_color: parts.slider.knob });
|
|
303
|
+
defs.push({ id: STYLE_SWITCH_INDICATOR, bg_color: parts.switch.bg });
|
|
304
|
+
defs.push({ id: STYLE_SWITCH_KNOB, bg_color: parts.switch.knob });
|
|
305
|
+
defs.push({ id: STYLE_ARC_INDICATOR, bg_color: parts.arc.bg });
|
|
306
|
+
defs.push({ id: STYLE_ARC_KNOB, bg_color: parts.arc.knob });
|
|
307
|
+
return defs;
|
|
308
|
+
}
|
|
309
|
+
function themeToLvglTheme(theme) {
|
|
310
|
+
const bodyFont = fontDefToLvgl(theme.typography.body);
|
|
311
|
+
const parts = resolveParts(theme);
|
|
312
|
+
return {
|
|
313
|
+
label: {
|
|
314
|
+
text_color: theme.colors.textPrimary,
|
|
315
|
+
text_font: bodyFont
|
|
316
|
+
},
|
|
317
|
+
button: {
|
|
318
|
+
bg_color: theme.colors.primary.bg,
|
|
319
|
+
border_width: 0,
|
|
320
|
+
pressed: {
|
|
321
|
+
bg_color: theme.colors.primary.bgPressed
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
obj: {
|
|
325
|
+
border_width: 0,
|
|
326
|
+
bg_opa: "TRANSP"
|
|
327
|
+
},
|
|
328
|
+
slider: {
|
|
329
|
+
bg_color: theme.colors.surfaceAlt,
|
|
330
|
+
indicator: {
|
|
331
|
+
bg_color: parts.slider.bg
|
|
332
|
+
},
|
|
333
|
+
knob: {
|
|
334
|
+
bg_color: parts.slider.knob
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
switch: {
|
|
338
|
+
bg_color: theme.colors.surfaceAlt,
|
|
339
|
+
indicator: {
|
|
340
|
+
bg_color: parts.switch.bg
|
|
341
|
+
},
|
|
342
|
+
knob: {
|
|
343
|
+
bg_color: parts.switch.knob
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
arc: {
|
|
347
|
+
arc_color: theme.colors.surfaceAlt,
|
|
348
|
+
indicator: {
|
|
349
|
+
arc_color: parts.arc.bg
|
|
350
|
+
},
|
|
351
|
+
knob: {
|
|
352
|
+
bg_color: parts.arc.knob
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
dropdown: {
|
|
356
|
+
text_color: theme.colors.textPrimary,
|
|
357
|
+
text_font: bodyFont,
|
|
358
|
+
bg_color: theme.colors.surface,
|
|
359
|
+
border_color: theme.colors.border,
|
|
360
|
+
border_width: 1
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function createLvglThemeProps(theme) {
|
|
365
|
+
return {
|
|
366
|
+
styleDefinitions: themeToStyleDefinitions(theme),
|
|
367
|
+
theme: themeToLvglTheme(theme)
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function createThemeSwitchActions(theme) {
|
|
371
|
+
const defs = themeToStyleDefinitions(theme);
|
|
372
|
+
return defs.map((def) => {
|
|
373
|
+
const { id, ...props } = def;
|
|
374
|
+
return { "lvgl.style.update": { id, ...props } };
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
function applyTheme(theme) {
|
|
378
|
+
return createThemeSwitchActions(theme);
|
|
379
|
+
}
|
|
380
|
+
|
|
188
381
|
// src/intents.ts
|
|
189
382
|
var COMPOSE_UI_INTENTS = {
|
|
190
383
|
/** Col can only be placed inside Row. */
|
|
@@ -198,16 +391,16 @@ var import_compose2 = require("@esphome/compose");
|
|
|
198
391
|
var Screen = (0, import_compose2.createIntentComponent)(
|
|
199
392
|
(props) => {
|
|
200
393
|
const padding = props.padding != null ? resolveSpacing(props.padding) : void 0;
|
|
201
|
-
const theme = useTheme();
|
|
202
|
-
const bgColor = props.bgColor ?? theme.colors.background;
|
|
203
394
|
return {
|
|
204
395
|
type: "lvgl-page",
|
|
205
396
|
props: {
|
|
206
|
-
|
|
397
|
+
styles: STYLE_BG,
|
|
398
|
+
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
207
399
|
borderWidth: props.borderWidth ?? 0,
|
|
208
400
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
209
401
|
...padding != null ? { padAll: padding } : {},
|
|
210
402
|
...props.skip != null ? { skip: props.skip } : {},
|
|
403
|
+
"x:custom": { scrollbar_mode: "OFF" },
|
|
211
404
|
...props.children ? { children: Array.isArray(props.children) ? props.children : [props.children] } : {}
|
|
212
405
|
}
|
|
213
406
|
};
|
|
@@ -239,8 +432,8 @@ function buildSpaceElement(props) {
|
|
|
239
432
|
return {
|
|
240
433
|
type: "lvgl-obj",
|
|
241
434
|
props: {
|
|
242
|
-
|
|
243
|
-
|
|
435
|
+
width: props.width ?? "100%",
|
|
436
|
+
height: props.height ?? "SIZE_CONTENT",
|
|
244
437
|
...padding != null ? { padAll: padding } : {},
|
|
245
438
|
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
246
439
|
...props.bgOpa != null ? { bgOpa: props.bgOpa } : { bgOpa: "TRANSP" },
|
|
@@ -248,6 +441,7 @@ function buildSpaceElement(props) {
|
|
|
248
441
|
borderWidth: props.borderWidth ?? 0,
|
|
249
442
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
250
443
|
"x:custom": {
|
|
444
|
+
scrollbar_mode: "OFF",
|
|
251
445
|
layout: buildFlexLayout(flow, gapKey, props)
|
|
252
446
|
},
|
|
253
447
|
...props.children ? { children: Array.isArray(props.children) ? props.children : [props.children] } : {}
|
|
@@ -407,15 +601,13 @@ var import_compose6 = require("@esphome/compose");
|
|
|
407
601
|
var Text = (0, import_compose6.createIntentComponent)(
|
|
408
602
|
(props) => {
|
|
409
603
|
const variant = props.variant ?? "body";
|
|
410
|
-
const fontDef = resolveTypography(variant);
|
|
411
|
-
const color = props.color ?? useTheme().colors.textPrimary;
|
|
412
604
|
return {
|
|
413
605
|
type: "lvgl-label",
|
|
414
606
|
props: {
|
|
607
|
+
styles: STYLE_TEXT_VARIANT[variant],
|
|
415
608
|
...props.text != null ? { text: props.text } : {},
|
|
416
|
-
textFont: fontDefToLvgl(fontDef),
|
|
417
609
|
...props.align != null ? { textAlign: props.align } : {},
|
|
418
|
-
textColor: color,
|
|
610
|
+
...props.color != null ? { textColor: props.color } : {},
|
|
419
611
|
...props.longMode != null ? { longMode: props.longMode } : {},
|
|
420
612
|
...props.x != null ? { x: props.x } : {},
|
|
421
613
|
...props.y != null ? { y: props.y } : {},
|
|
@@ -436,32 +628,25 @@ var Button = (0, import_compose7.createIntentComponent)(
|
|
|
436
628
|
const status = props.status ?? "primary";
|
|
437
629
|
const size = props.size ?? "md";
|
|
438
630
|
const variant = props.variant ?? "solid";
|
|
439
|
-
const colors = resolveStatus(status);
|
|
440
631
|
const dims = resolveSize(size);
|
|
441
632
|
const theme = useTheme();
|
|
442
|
-
const
|
|
633
|
+
const sc = resolveStatus(status);
|
|
443
634
|
const textFont = fontDefToLvgl({ fontFamily: theme.typography.body.fontFamily, fontSize: dims.fontSize });
|
|
635
|
+
const pressed = variant === "solid" ? { bgColor: sc.bgPressed } : { bgColor: sc.bg, bgOpa: "COVER" };
|
|
444
636
|
const buttonProps = {
|
|
637
|
+
styles: statusStyleId(status, variant),
|
|
445
638
|
width: props.width ?? dims.paddingX * 2 + 80,
|
|
446
639
|
height: props.height ?? dims.height,
|
|
640
|
+
pressed,
|
|
447
641
|
...props.x != null ? { x: props.x } : {},
|
|
448
642
|
...props.y != null ? { y: props.y } : {},
|
|
449
|
-
...isSolid ? {
|
|
450
|
-
bgColor: colors.bg,
|
|
451
|
-
pressed: { bgColor: colors.bgPressed }
|
|
452
|
-
} : {
|
|
453
|
-
bgOpa: "TRANSP",
|
|
454
|
-
borderColor: colors.bg,
|
|
455
|
-
borderWidth: 2,
|
|
456
|
-
pressed: { bgColor: colors.bg, bgOpa: "COVER" }
|
|
457
|
-
},
|
|
458
643
|
...props.onPress != null ? { "x:custom": { on_press: props.onPress } } : {}
|
|
459
644
|
};
|
|
460
645
|
const label = {
|
|
461
646
|
type: "lvgl-label",
|
|
462
647
|
props: {
|
|
648
|
+
styles: statusTextStyleId(status, variant),
|
|
463
649
|
text: props.text ?? "",
|
|
464
|
-
textColor: isSolid ? colors.text : colors.bg,
|
|
465
650
|
textFont,
|
|
466
651
|
align: "CENTER"
|
|
467
652
|
}
|
|
@@ -486,19 +671,20 @@ var Card = (0, import_compose8.createIntentComponent)(
|
|
|
486
671
|
(props) => {
|
|
487
672
|
const padding = resolveSpacing(props.padding ?? "md");
|
|
488
673
|
const radius = resolveRadius(props.radius ?? "md");
|
|
489
|
-
const theme = useTheme();
|
|
490
674
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
491
675
|
return {
|
|
492
676
|
type: "lvgl-obj",
|
|
493
677
|
props: {
|
|
678
|
+
styles: STYLE_SURFACE_ALT,
|
|
494
679
|
padAll: padding,
|
|
495
680
|
radius,
|
|
496
|
-
bgColor: props.bgColor
|
|
681
|
+
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
497
682
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
498
683
|
borderWidth: props.borderWidth ?? 0,
|
|
499
|
-
|
|
500
|
-
|
|
684
|
+
width: props.width ?? "100%",
|
|
685
|
+
height: props.height ?? "SIZE_CONTENT",
|
|
501
686
|
"x:custom": {
|
|
687
|
+
scrollbar_mode: "OFF",
|
|
502
688
|
layout: {
|
|
503
689
|
type: "flex",
|
|
504
690
|
flex_flow: "COLUMN",
|
|
@@ -520,14 +706,12 @@ var Card = (0, import_compose8.createIntentComponent)(
|
|
|
520
706
|
var import_compose9 = require("@esphome/compose");
|
|
521
707
|
var SliderField = (0, import_compose9.createIntentComponent)(
|
|
522
708
|
(props) => {
|
|
523
|
-
const theme = useTheme();
|
|
524
709
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
525
710
|
const label = {
|
|
526
711
|
type: "lvgl-label",
|
|
527
712
|
props: {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
textColor: theme.colors.textPrimary
|
|
713
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
714
|
+
text: props.label
|
|
531
715
|
}
|
|
532
716
|
};
|
|
533
717
|
const sliderProps = {
|
|
@@ -567,13 +751,11 @@ var SliderField = (0, import_compose9.createIntentComponent)(
|
|
|
567
751
|
var import_compose10 = require("@esphome/compose");
|
|
568
752
|
var SwitchField = (0, import_compose10.createIntentComponent)(
|
|
569
753
|
(props) => {
|
|
570
|
-
const theme = useTheme();
|
|
571
754
|
const label = {
|
|
572
755
|
type: "lvgl-label",
|
|
573
756
|
props: {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
textColor: theme.colors.textPrimary
|
|
757
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
758
|
+
text: props.label
|
|
577
759
|
}
|
|
578
760
|
};
|
|
579
761
|
const switchProps = {
|
|
@@ -612,14 +794,12 @@ var SwitchField = (0, import_compose10.createIntentComponent)(
|
|
|
612
794
|
var import_compose11 = require("@esphome/compose");
|
|
613
795
|
var DropdownField = (0, import_compose11.createIntentComponent)(
|
|
614
796
|
(props) => {
|
|
615
|
-
const theme = useTheme();
|
|
616
797
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
617
798
|
const label = {
|
|
618
799
|
type: "lvgl-label",
|
|
619
800
|
props: {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
textColor: theme.colors.textPrimary
|
|
801
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
802
|
+
text: props.label
|
|
623
803
|
}
|
|
624
804
|
};
|
|
625
805
|
const dropdownProps = {
|
|
@@ -664,6 +844,20 @@ var DropdownField = (0, import_compose11.createIntentComponent)(
|
|
|
664
844
|
GridItem,
|
|
665
845
|
HStack,
|
|
666
846
|
Row,
|
|
847
|
+
STYLE_ARC_INDICATOR,
|
|
848
|
+
STYLE_ARC_KNOB,
|
|
849
|
+
STYLE_BG,
|
|
850
|
+
STYLE_BORDER,
|
|
851
|
+
STYLE_SLIDER_INDICATOR,
|
|
852
|
+
STYLE_SLIDER_KNOB,
|
|
853
|
+
STYLE_SURFACE,
|
|
854
|
+
STYLE_SURFACE_ALT,
|
|
855
|
+
STYLE_SWITCH_INDICATOR,
|
|
856
|
+
STYLE_SWITCH_KNOB,
|
|
857
|
+
STYLE_TEXT_DISABLED,
|
|
858
|
+
STYLE_TEXT_PRIMARY,
|
|
859
|
+
STYLE_TEXT_SECONDARY,
|
|
860
|
+
STYLE_TEXT_VARIANT,
|
|
667
861
|
Screen,
|
|
668
862
|
SliderField,
|
|
669
863
|
Space,
|
|
@@ -672,6 +866,8 @@ var DropdownField = (0, import_compose11.createIntentComponent)(
|
|
|
672
866
|
ThemeContext,
|
|
673
867
|
ThemeProvider,
|
|
674
868
|
VStack,
|
|
869
|
+
applyTheme,
|
|
870
|
+
createLvglThemeProps,
|
|
675
871
|
darkTheme,
|
|
676
872
|
fontDefToLvgl,
|
|
677
873
|
lightTheme,
|
|
@@ -680,7 +876,11 @@ var DropdownField = (0, import_compose11.createIntentComponent)(
|
|
|
680
876
|
resolveSpacing,
|
|
681
877
|
resolveStatus,
|
|
682
878
|
resolveTypography,
|
|
879
|
+
statusStyleId,
|
|
880
|
+
statusTextStyleId,
|
|
683
881
|
themeFromJSON,
|
|
684
882
|
themeToJSON,
|
|
883
|
+
themeToLvglTheme,
|
|
884
|
+
themeToStyleDefinitions,
|
|
685
885
|
useTheme
|
|
686
886
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -45,6 +45,11 @@ var darkTheme = {
|
|
|
45
45
|
md: { height: 44, fontSize: 16, paddingX: 16, paddingY: 8 },
|
|
46
46
|
lg: { height: 52, fontSize: 18, paddingX: 20, paddingY: 10 },
|
|
47
47
|
xl: { height: 64, fontSize: 22, paddingX: 24, paddingY: 12 }
|
|
48
|
+
},
|
|
49
|
+
parts: {
|
|
50
|
+
slider: { bg: "#1E88E5", knob: "#E0E0E0" },
|
|
51
|
+
switch: { bg: "#1E88E5", knob: "#E0E0E0" },
|
|
52
|
+
arc: { bg: "#1E88E5", knob: "#E0E0E0" }
|
|
48
53
|
}
|
|
49
54
|
};
|
|
50
55
|
|
|
@@ -99,6 +104,11 @@ var lightTheme = {
|
|
|
99
104
|
md: { height: 44, fontSize: 16, paddingX: 16, paddingY: 8 },
|
|
100
105
|
lg: { height: 52, fontSize: 18, paddingX: 20, paddingY: 10 },
|
|
101
106
|
xl: { height: 64, fontSize: 22, paddingX: 24, paddingY: 12 }
|
|
107
|
+
},
|
|
108
|
+
parts: {
|
|
109
|
+
slider: { bg: "#1565C0", knob: "#212121" },
|
|
110
|
+
switch: { bg: "#1565C0", knob: "#212121" },
|
|
111
|
+
arc: { bg: "#1565C0", knob: "#212121" }
|
|
102
112
|
}
|
|
103
113
|
};
|
|
104
114
|
|
|
@@ -132,6 +142,169 @@ function resolveRadius(value) {
|
|
|
132
142
|
return useTheme().radii[value];
|
|
133
143
|
}
|
|
134
144
|
|
|
145
|
+
// src/theme/style-ids.ts
|
|
146
|
+
var STYLE_BG = "ds_bg";
|
|
147
|
+
var STYLE_SURFACE = "ds_surface";
|
|
148
|
+
var STYLE_SURFACE_ALT = "ds_surface_alt";
|
|
149
|
+
var STYLE_BORDER = "ds_border";
|
|
150
|
+
var STYLE_TEXT_PRIMARY = "ds_text_primary";
|
|
151
|
+
var STYLE_TEXT_SECONDARY = "ds_text_secondary";
|
|
152
|
+
var STYLE_TEXT_DISABLED = "ds_text_disabled";
|
|
153
|
+
var STYLE_TEXT_VARIANT = {
|
|
154
|
+
title: "ds_text_title",
|
|
155
|
+
subtitle: "ds_text_subtitle",
|
|
156
|
+
body: "ds_text_body",
|
|
157
|
+
caption: "ds_text_caption"
|
|
158
|
+
};
|
|
159
|
+
function statusStyleId(status, variant) {
|
|
160
|
+
return `ds_status_${status}_${variant}`;
|
|
161
|
+
}
|
|
162
|
+
function statusTextStyleId(status, variant) {
|
|
163
|
+
return `ds_status_${status}_${variant}_text`;
|
|
164
|
+
}
|
|
165
|
+
var ALL_STATUSES = [
|
|
166
|
+
"primary",
|
|
167
|
+
"secondary",
|
|
168
|
+
"success",
|
|
169
|
+
"warning",
|
|
170
|
+
"danger"
|
|
171
|
+
];
|
|
172
|
+
var STYLE_SLIDER_INDICATOR = "ds_slider_indicator";
|
|
173
|
+
var STYLE_SLIDER_KNOB = "ds_slider_knob";
|
|
174
|
+
var STYLE_SWITCH_INDICATOR = "ds_switch_indicator";
|
|
175
|
+
var STYLE_SWITCH_KNOB = "ds_switch_knob";
|
|
176
|
+
var STYLE_ARC_INDICATOR = "ds_arc_indicator";
|
|
177
|
+
var STYLE_ARC_KNOB = "ds_arc_knob";
|
|
178
|
+
|
|
179
|
+
// src/theme/bridge.ts
|
|
180
|
+
function resolveParts(theme) {
|
|
181
|
+
if (theme.parts) return theme.parts;
|
|
182
|
+
return {
|
|
183
|
+
slider: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary },
|
|
184
|
+
switch: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary },
|
|
185
|
+
arc: { bg: theme.colors.primary.bg, knob: theme.colors.textPrimary }
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function themeToStyleDefinitions(theme) {
|
|
189
|
+
const defs = [];
|
|
190
|
+
const bodyFont = fontDefToLvgl(theme.typography.body);
|
|
191
|
+
defs.push({ id: STYLE_BG, bg_color: theme.colors.background });
|
|
192
|
+
defs.push({ id: STYLE_SURFACE, bg_color: theme.colors.surface });
|
|
193
|
+
defs.push({ id: STYLE_SURFACE_ALT, bg_color: theme.colors.surfaceAlt });
|
|
194
|
+
defs.push({ id: STYLE_BORDER, border_color: theme.colors.border });
|
|
195
|
+
defs.push({ id: STYLE_TEXT_PRIMARY, text_color: theme.colors.textPrimary, text_font: bodyFont });
|
|
196
|
+
defs.push({ id: STYLE_TEXT_SECONDARY, text_color: theme.colors.textSecondary, text_font: bodyFont });
|
|
197
|
+
defs.push({ id: STYLE_TEXT_DISABLED, text_color: theme.colors.textDisabled, text_font: bodyFont });
|
|
198
|
+
for (const variant of ["title", "subtitle", "body", "caption"]) {
|
|
199
|
+
const font = fontDefToLvgl(theme.typography[variant]);
|
|
200
|
+
defs.push({
|
|
201
|
+
id: STYLE_TEXT_VARIANT[variant],
|
|
202
|
+
text_color: theme.colors.textPrimary,
|
|
203
|
+
text_font: font
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
for (const status of ALL_STATUSES) {
|
|
207
|
+
const sc = theme.colors[status];
|
|
208
|
+
defs.push({
|
|
209
|
+
id: statusStyleId(status, "solid"),
|
|
210
|
+
bg_color: sc.bg
|
|
211
|
+
});
|
|
212
|
+
defs.push({
|
|
213
|
+
id: statusTextStyleId(status, "solid"),
|
|
214
|
+
text_color: sc.text
|
|
215
|
+
});
|
|
216
|
+
defs.push({
|
|
217
|
+
id: statusStyleId(status, "outline"),
|
|
218
|
+
bg_opa: "TRANSP",
|
|
219
|
+
border_color: sc.bg,
|
|
220
|
+
border_width: 2
|
|
221
|
+
});
|
|
222
|
+
defs.push({
|
|
223
|
+
id: statusTextStyleId(status, "outline"),
|
|
224
|
+
text_color: sc.bg
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
const parts = resolveParts(theme);
|
|
228
|
+
defs.push({ id: STYLE_SLIDER_INDICATOR, bg_color: parts.slider.bg });
|
|
229
|
+
defs.push({ id: STYLE_SLIDER_KNOB, bg_color: parts.slider.knob });
|
|
230
|
+
defs.push({ id: STYLE_SWITCH_INDICATOR, bg_color: parts.switch.bg });
|
|
231
|
+
defs.push({ id: STYLE_SWITCH_KNOB, bg_color: parts.switch.knob });
|
|
232
|
+
defs.push({ id: STYLE_ARC_INDICATOR, bg_color: parts.arc.bg });
|
|
233
|
+
defs.push({ id: STYLE_ARC_KNOB, bg_color: parts.arc.knob });
|
|
234
|
+
return defs;
|
|
235
|
+
}
|
|
236
|
+
function themeToLvglTheme(theme) {
|
|
237
|
+
const bodyFont = fontDefToLvgl(theme.typography.body);
|
|
238
|
+
const parts = resolveParts(theme);
|
|
239
|
+
return {
|
|
240
|
+
label: {
|
|
241
|
+
text_color: theme.colors.textPrimary,
|
|
242
|
+
text_font: bodyFont
|
|
243
|
+
},
|
|
244
|
+
button: {
|
|
245
|
+
bg_color: theme.colors.primary.bg,
|
|
246
|
+
border_width: 0,
|
|
247
|
+
pressed: {
|
|
248
|
+
bg_color: theme.colors.primary.bgPressed
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
obj: {
|
|
252
|
+
border_width: 0,
|
|
253
|
+
bg_opa: "TRANSP"
|
|
254
|
+
},
|
|
255
|
+
slider: {
|
|
256
|
+
bg_color: theme.colors.surfaceAlt,
|
|
257
|
+
indicator: {
|
|
258
|
+
bg_color: parts.slider.bg
|
|
259
|
+
},
|
|
260
|
+
knob: {
|
|
261
|
+
bg_color: parts.slider.knob
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
switch: {
|
|
265
|
+
bg_color: theme.colors.surfaceAlt,
|
|
266
|
+
indicator: {
|
|
267
|
+
bg_color: parts.switch.bg
|
|
268
|
+
},
|
|
269
|
+
knob: {
|
|
270
|
+
bg_color: parts.switch.knob
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
arc: {
|
|
274
|
+
arc_color: theme.colors.surfaceAlt,
|
|
275
|
+
indicator: {
|
|
276
|
+
arc_color: parts.arc.bg
|
|
277
|
+
},
|
|
278
|
+
knob: {
|
|
279
|
+
bg_color: parts.arc.knob
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
dropdown: {
|
|
283
|
+
text_color: theme.colors.textPrimary,
|
|
284
|
+
text_font: bodyFont,
|
|
285
|
+
bg_color: theme.colors.surface,
|
|
286
|
+
border_color: theme.colors.border,
|
|
287
|
+
border_width: 1
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function createLvglThemeProps(theme) {
|
|
292
|
+
return {
|
|
293
|
+
styleDefinitions: themeToStyleDefinitions(theme),
|
|
294
|
+
theme: themeToLvglTheme(theme)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function createThemeSwitchActions(theme) {
|
|
298
|
+
const defs = themeToStyleDefinitions(theme);
|
|
299
|
+
return defs.map((def) => {
|
|
300
|
+
const { id, ...props } = def;
|
|
301
|
+
return { "lvgl.style.update": { id, ...props } };
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function applyTheme(theme) {
|
|
305
|
+
return createThemeSwitchActions(theme);
|
|
306
|
+
}
|
|
307
|
+
|
|
135
308
|
// src/intents.ts
|
|
136
309
|
var COMPOSE_UI_INTENTS = {
|
|
137
310
|
/** Col can only be placed inside Row. */
|
|
@@ -145,16 +318,16 @@ import { createIntentComponent, LVGL_INTENTS } from "@esphome/compose";
|
|
|
145
318
|
var Screen = createIntentComponent(
|
|
146
319
|
(props) => {
|
|
147
320
|
const padding = props.padding != null ? resolveSpacing(props.padding) : void 0;
|
|
148
|
-
const theme = useTheme();
|
|
149
|
-
const bgColor = props.bgColor ?? theme.colors.background;
|
|
150
321
|
return {
|
|
151
322
|
type: "lvgl-page",
|
|
152
323
|
props: {
|
|
153
|
-
|
|
324
|
+
styles: STYLE_BG,
|
|
325
|
+
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
154
326
|
borderWidth: props.borderWidth ?? 0,
|
|
155
327
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
156
328
|
...padding != null ? { padAll: padding } : {},
|
|
157
329
|
...props.skip != null ? { skip: props.skip } : {},
|
|
330
|
+
"x:custom": { scrollbar_mode: "OFF" },
|
|
158
331
|
...props.children ? { children: Array.isArray(props.children) ? props.children : [props.children] } : {}
|
|
159
332
|
}
|
|
160
333
|
};
|
|
@@ -186,8 +359,8 @@ function buildSpaceElement(props) {
|
|
|
186
359
|
return {
|
|
187
360
|
type: "lvgl-obj",
|
|
188
361
|
props: {
|
|
189
|
-
|
|
190
|
-
|
|
362
|
+
width: props.width ?? "100%",
|
|
363
|
+
height: props.height ?? "SIZE_CONTENT",
|
|
191
364
|
...padding != null ? { padAll: padding } : {},
|
|
192
365
|
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
193
366
|
...props.bgOpa != null ? { bgOpa: props.bgOpa } : { bgOpa: "TRANSP" },
|
|
@@ -195,6 +368,7 @@ function buildSpaceElement(props) {
|
|
|
195
368
|
borderWidth: props.borderWidth ?? 0,
|
|
196
369
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
197
370
|
"x:custom": {
|
|
371
|
+
scrollbar_mode: "OFF",
|
|
198
372
|
layout: buildFlexLayout(flow, gapKey, props)
|
|
199
373
|
},
|
|
200
374
|
...props.children ? { children: Array.isArray(props.children) ? props.children : [props.children] } : {}
|
|
@@ -354,15 +528,13 @@ import { createIntentComponent as createIntentComponent5, LVGL_INTENTS as LVGL_I
|
|
|
354
528
|
var Text = createIntentComponent5(
|
|
355
529
|
(props) => {
|
|
356
530
|
const variant = props.variant ?? "body";
|
|
357
|
-
const fontDef = resolveTypography(variant);
|
|
358
|
-
const color = props.color ?? useTheme().colors.textPrimary;
|
|
359
531
|
return {
|
|
360
532
|
type: "lvgl-label",
|
|
361
533
|
props: {
|
|
534
|
+
styles: STYLE_TEXT_VARIANT[variant],
|
|
362
535
|
...props.text != null ? { text: props.text } : {},
|
|
363
|
-
textFont: fontDefToLvgl(fontDef),
|
|
364
536
|
...props.align != null ? { textAlign: props.align } : {},
|
|
365
|
-
textColor: color,
|
|
537
|
+
...props.color != null ? { textColor: props.color } : {},
|
|
366
538
|
...props.longMode != null ? { longMode: props.longMode } : {},
|
|
367
539
|
...props.x != null ? { x: props.x } : {},
|
|
368
540
|
...props.y != null ? { y: props.y } : {},
|
|
@@ -383,32 +555,25 @@ var Button = createIntentComponent6(
|
|
|
383
555
|
const status = props.status ?? "primary";
|
|
384
556
|
const size = props.size ?? "md";
|
|
385
557
|
const variant = props.variant ?? "solid";
|
|
386
|
-
const colors = resolveStatus(status);
|
|
387
558
|
const dims = resolveSize(size);
|
|
388
559
|
const theme = useTheme();
|
|
389
|
-
const
|
|
560
|
+
const sc = resolveStatus(status);
|
|
390
561
|
const textFont = fontDefToLvgl({ fontFamily: theme.typography.body.fontFamily, fontSize: dims.fontSize });
|
|
562
|
+
const pressed = variant === "solid" ? { bgColor: sc.bgPressed } : { bgColor: sc.bg, bgOpa: "COVER" };
|
|
391
563
|
const buttonProps = {
|
|
564
|
+
styles: statusStyleId(status, variant),
|
|
392
565
|
width: props.width ?? dims.paddingX * 2 + 80,
|
|
393
566
|
height: props.height ?? dims.height,
|
|
567
|
+
pressed,
|
|
394
568
|
...props.x != null ? { x: props.x } : {},
|
|
395
569
|
...props.y != null ? { y: props.y } : {},
|
|
396
|
-
...isSolid ? {
|
|
397
|
-
bgColor: colors.bg,
|
|
398
|
-
pressed: { bgColor: colors.bgPressed }
|
|
399
|
-
} : {
|
|
400
|
-
bgOpa: "TRANSP",
|
|
401
|
-
borderColor: colors.bg,
|
|
402
|
-
borderWidth: 2,
|
|
403
|
-
pressed: { bgColor: colors.bg, bgOpa: "COVER" }
|
|
404
|
-
},
|
|
405
570
|
...props.onPress != null ? { "x:custom": { on_press: props.onPress } } : {}
|
|
406
571
|
};
|
|
407
572
|
const label = {
|
|
408
573
|
type: "lvgl-label",
|
|
409
574
|
props: {
|
|
575
|
+
styles: statusTextStyleId(status, variant),
|
|
410
576
|
text: props.text ?? "",
|
|
411
|
-
textColor: isSolid ? colors.text : colors.bg,
|
|
412
577
|
textFont,
|
|
413
578
|
align: "CENTER"
|
|
414
579
|
}
|
|
@@ -433,19 +598,20 @@ var Card = createIntentComponent7(
|
|
|
433
598
|
(props) => {
|
|
434
599
|
const padding = resolveSpacing(props.padding ?? "md");
|
|
435
600
|
const radius = resolveRadius(props.radius ?? "md");
|
|
436
|
-
const theme = useTheme();
|
|
437
601
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
438
602
|
return {
|
|
439
603
|
type: "lvgl-obj",
|
|
440
604
|
props: {
|
|
605
|
+
styles: STYLE_SURFACE_ALT,
|
|
441
606
|
padAll: padding,
|
|
442
607
|
radius,
|
|
443
|
-
bgColor: props.bgColor
|
|
608
|
+
...props.bgColor != null ? { bgColor: props.bgColor } : {},
|
|
444
609
|
...props.borderColor != null ? { borderColor: props.borderColor } : {},
|
|
445
610
|
borderWidth: props.borderWidth ?? 0,
|
|
446
|
-
|
|
447
|
-
|
|
611
|
+
width: props.width ?? "100%",
|
|
612
|
+
height: props.height ?? "SIZE_CONTENT",
|
|
448
613
|
"x:custom": {
|
|
614
|
+
scrollbar_mode: "OFF",
|
|
449
615
|
layout: {
|
|
450
616
|
type: "flex",
|
|
451
617
|
flex_flow: "COLUMN",
|
|
@@ -467,14 +633,12 @@ var Card = createIntentComponent7(
|
|
|
467
633
|
import { createIntentComponent as createIntentComponent8, LVGL_INTENTS as LVGL_INTENTS8 } from "@esphome/compose";
|
|
468
634
|
var SliderField = createIntentComponent8(
|
|
469
635
|
(props) => {
|
|
470
|
-
const theme = useTheme();
|
|
471
636
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
472
637
|
const label = {
|
|
473
638
|
type: "lvgl-label",
|
|
474
639
|
props: {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
textColor: theme.colors.textPrimary
|
|
640
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
641
|
+
text: props.label
|
|
478
642
|
}
|
|
479
643
|
};
|
|
480
644
|
const sliderProps = {
|
|
@@ -514,13 +678,11 @@ var SliderField = createIntentComponent8(
|
|
|
514
678
|
import { createIntentComponent as createIntentComponent9, LVGL_INTENTS as LVGL_INTENTS9 } from "@esphome/compose";
|
|
515
679
|
var SwitchField = createIntentComponent9(
|
|
516
680
|
(props) => {
|
|
517
|
-
const theme = useTheme();
|
|
518
681
|
const label = {
|
|
519
682
|
type: "lvgl-label",
|
|
520
683
|
props: {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
textColor: theme.colors.textPrimary
|
|
684
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
685
|
+
text: props.label
|
|
524
686
|
}
|
|
525
687
|
};
|
|
526
688
|
const switchProps = {
|
|
@@ -559,14 +721,12 @@ var SwitchField = createIntentComponent9(
|
|
|
559
721
|
import { createIntentComponent as createIntentComponent10, LVGL_INTENTS as LVGL_INTENTS10 } from "@esphome/compose";
|
|
560
722
|
var DropdownField = createIntentComponent10(
|
|
561
723
|
(props) => {
|
|
562
|
-
const theme = useTheme();
|
|
563
724
|
const gap = props.gap != null ? resolveSpacing(props.gap) : void 0;
|
|
564
725
|
const label = {
|
|
565
726
|
type: "lvgl-label",
|
|
566
727
|
props: {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
textColor: theme.colors.textPrimary
|
|
728
|
+
styles: STYLE_TEXT_PRIMARY,
|
|
729
|
+
text: props.label
|
|
570
730
|
}
|
|
571
731
|
};
|
|
572
732
|
const dropdownProps = {
|
|
@@ -610,6 +770,20 @@ export {
|
|
|
610
770
|
GridItem,
|
|
611
771
|
HStack,
|
|
612
772
|
Row,
|
|
773
|
+
STYLE_ARC_INDICATOR,
|
|
774
|
+
STYLE_ARC_KNOB,
|
|
775
|
+
STYLE_BG,
|
|
776
|
+
STYLE_BORDER,
|
|
777
|
+
STYLE_SLIDER_INDICATOR,
|
|
778
|
+
STYLE_SLIDER_KNOB,
|
|
779
|
+
STYLE_SURFACE,
|
|
780
|
+
STYLE_SURFACE_ALT,
|
|
781
|
+
STYLE_SWITCH_INDICATOR,
|
|
782
|
+
STYLE_SWITCH_KNOB,
|
|
783
|
+
STYLE_TEXT_DISABLED,
|
|
784
|
+
STYLE_TEXT_PRIMARY,
|
|
785
|
+
STYLE_TEXT_SECONDARY,
|
|
786
|
+
STYLE_TEXT_VARIANT,
|
|
613
787
|
Screen,
|
|
614
788
|
SliderField,
|
|
615
789
|
Space,
|
|
@@ -618,6 +792,8 @@ export {
|
|
|
618
792
|
ThemeContext,
|
|
619
793
|
ThemeProvider,
|
|
620
794
|
VStack,
|
|
795
|
+
applyTheme,
|
|
796
|
+
createLvglThemeProps,
|
|
621
797
|
darkTheme,
|
|
622
798
|
fontDefToLvgl,
|
|
623
799
|
lightTheme,
|
|
@@ -626,7 +802,11 @@ export {
|
|
|
626
802
|
resolveSpacing,
|
|
627
803
|
resolveStatus,
|
|
628
804
|
resolveTypography,
|
|
805
|
+
statusStyleId,
|
|
806
|
+
statusTextStyleId,
|
|
629
807
|
themeFromJSON,
|
|
630
808
|
themeToJSON,
|
|
809
|
+
themeToLvglTheme,
|
|
810
|
+
themeToStyleDefinitions,
|
|
631
811
|
useTheme
|
|
632
812
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esphome/compose-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "LVGL Design System components for ESPHome Compose",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@esphome/compose": "0.
|
|
38
|
+
"@esphome/compose": "0.3.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^22.0.0",
|
|
42
42
|
"tsup": "^8.0.0",
|
|
43
|
-
"tsx": "^4.
|
|
44
|
-
"typescript": "^5.
|
|
43
|
+
"tsx": "^4.21.0",
|
|
44
|
+
"typescript": "^5.9.3",
|
|
45
45
|
"rimraf": "^6.1.3",
|
|
46
46
|
"vitest": "^2.0.0"
|
|
47
47
|
},
|