@glasshome/widget-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/create-entity.d.ts +22 -0
- package/dist/define-widget.d.ts +10 -0
- package/dist/framework/backgrounds/Glow.d.ts +24 -0
- package/dist/framework/backgrounds/WidgetSliderFill.d.ts +33 -0
- package/dist/framework/components/WidgetContent.d.ts +29 -0
- package/dist/framework/components/WidgetEmptyState.d.ts +34 -0
- package/dist/framework/components/WidgetIcon.d.ts +48 -0
- package/dist/framework/components/WidgetMetrics.d.ts +47 -0
- package/dist/framework/components/WidgetStatus.d.ts +26 -0
- package/dist/framework/components/WidgetSubtitle.d.ts +28 -0
- package/dist/framework/components/WidgetTitle.d.ts +29 -0
- package/dist/framework/components/WidgetValue.d.ts +31 -0
- package/dist/framework/core/Widget.d.ts +88 -0
- package/dist/framework/design-system/index.d.ts +8 -0
- package/dist/framework/design-system/spacing.d.ts +40 -0
- package/dist/framework/design-system/typography.d.ts +40 -0
- package/dist/framework/design-system/z-index.d.ts +23 -0
- package/dist/framework/dialogs/WidgetDialog.d.ts +47 -0
- package/dist/framework/dialogs/index.d.ts +4 -0
- package/dist/framework/gestures/cursors.d.ts +17 -0
- package/dist/framework/gestures/use-widget-gestures.d.ts +53 -0
- package/dist/framework/hooks/index.d.ts +15 -0
- package/dist/framework/hooks/use-debug-data.d.ts +46 -0
- package/dist/framework/hooks/use-widget-config.d.ts +48 -0
- package/dist/framework/hooks/use-widget-context.d.ts +46 -0
- package/dist/framework/hooks/use-widget-dialog.d.ts +45 -0
- package/dist/framework/hooks/use-widget-entity-group.d.ts +67 -0
- package/dist/framework/hooks/use-widget-entity.d.ts +53 -0
- package/dist/framework/hooks/use-widget-form.d.ts +79 -0
- package/dist/framework/hooks/use-widget-responsive.d.ts +41 -0
- package/dist/framework/index.d.ts +55 -0
- package/dist/framework/layout/WidgetStack.d.ts +28 -0
- package/dist/framework/theming/adaptive-color.d.ts +28 -0
- package/dist/framework/theming/colors.d.ts +59 -0
- package/dist/framework/theming/index.d.ts +8 -0
- package/dist/framework/types.d.ts +335 -0
- package/dist/framework/utils/cn.d.ts +28 -0
- package/dist/framework/utils/empty-state.d.ts +49 -0
- package/dist/framework/utils/entity-aggregation.d.ts +73 -0
- package/dist/framework/utils/entity-state.d.ts +103 -0
- package/dist/framework/utils/format-value.d.ts +22 -0
- package/dist/framework/utils/index.d.ts +12 -0
- package/dist/framework/utils/interpret-value.d.ts +17 -0
- package/dist/framework/variants/built-in-variants.d.ts +39 -0
- package/dist/framework/variants/index.d.ts +7 -0
- package/dist/framework/variants/variant-utils.d.ts +105 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1955 -0
- package/dist/theme.d.ts +21 -0
- package/dist/types.d.ts +51 -0
- package/dist/version.d.ts +5 -0
- package/dist/vite/index.d.ts +56 -0
- package/dist/vite/index.js +184 -0
- package/package.json +76 -0
- package/preview/host.tsx +89 -0
- package/preview/preview.html +49 -0
- package/tailwind-sources.css +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GlassHome Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @glasshome/widget-sdk
|
|
2
|
+
|
|
3
|
+
SDK for building GlassHome dashboard widgets with SolidJS.
|
|
4
|
+
|
|
5
|
+
Provides `defineWidget`, reactive entity bindings, framework components/hooks, a Vite plugin for widget development, and Tailwind v4 source paths — everything you need to build, preview, and ship dashboard widgets.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @glasshome/widget-sdk solid-js
|
|
11
|
+
# or
|
|
12
|
+
bun add @glasshome/widget-sdk solid-js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> `solid-js ^1.9.11` is a required peer dependency.
|
|
16
|
+
|
|
17
|
+
## Subpath Imports
|
|
18
|
+
|
|
19
|
+
### `@glasshome/widget-sdk` — SDK API
|
|
20
|
+
|
|
21
|
+
Core widget API: define widgets, create reactive entity bindings, and use framework components/hooks.
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { defineWidget, createEntity, SDK_VERSION } from "@glasshome/widget-sdk";
|
|
25
|
+
|
|
26
|
+
const entity = createEntity("light.living_room");
|
|
27
|
+
|
|
28
|
+
export default defineWidget({
|
|
29
|
+
manifest: {
|
|
30
|
+
tag: "glasshome-my-widget",
|
|
31
|
+
type: "status",
|
|
32
|
+
name: "My Widget",
|
|
33
|
+
size: "small",
|
|
34
|
+
sdkVersion: "^0.1.0",
|
|
35
|
+
defaultConfig: { label: "Hello" },
|
|
36
|
+
},
|
|
37
|
+
component: (props) => <div>{props.config.label}</div>,
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### `@glasshome/widget-sdk/vite` — Vite Plugin
|
|
42
|
+
|
|
43
|
+
Vite plugin for widget development. Handles widget bundling, preview server, and registry generation.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// vite.config.ts
|
|
47
|
+
import { defineConfig } from "vite";
|
|
48
|
+
import { glasshomeWidget } from "@glasshome/widget-sdk/vite";
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
plugins: [glasshomeWidget()],
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The plugin accepts an optional `entry` option (defaults to `"src/index.tsx"`):
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
glasshomeWidget({ entry: "src/my-widget.tsx" });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### `@glasshome/widget-sdk/tailwind-sources` — Tailwind v4 CSS Source
|
|
62
|
+
|
|
63
|
+
Provides a `@source` directive for Tailwind v4 so the compiler scans widget SDK source files for class names.
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
/* In your widget's CSS entrypoint */
|
|
67
|
+
@import "tailwindcss";
|
|
68
|
+
@source "@glasshome/widget-sdk/tailwind-sources";
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Peer Dependencies
|
|
72
|
+
|
|
73
|
+
| Package | Required | Notes |
|
|
74
|
+
| ---------- | -------- | ------------------------------------------- |
|
|
75
|
+
| `solid-js` | Yes | SolidJS reactive primitives and JSX runtime |
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SolidJS-specific utility — NOT part of the framework-agnostic SDK contract.
|
|
3
|
+
* This module uses SolidJS signals for reactive entity state management.
|
|
4
|
+
* It is exported from the SDK as a convenience for SolidJS widget authors.
|
|
5
|
+
*/
|
|
6
|
+
import { type Accessor } from "solid-js";
|
|
7
|
+
export interface Entity {
|
|
8
|
+
id: string;
|
|
9
|
+
state: string;
|
|
10
|
+
attributes: Record<string, unknown>;
|
|
11
|
+
last_updated?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a reactive entity signal. Returns a signal accessor that tracks
|
|
15
|
+
* entity state changes.
|
|
16
|
+
*
|
|
17
|
+
* NOTE: The setter from `createSignal` is intentionally destructured away.
|
|
18
|
+
* The signal infrastructure is kept in place so that when the sync-layer is
|
|
19
|
+
* ported, the runtime can update entity state reactively without changing
|
|
20
|
+
* the public API surface. Until then the accessor behaves as a constant.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createEntity(initialState: Entity): Accessor<Entity>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WidgetDefinition } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Define a widget and return its definition for registration with the dashboard.
|
|
4
|
+
*
|
|
5
|
+
* The dashboard renders widgets as plain SolidJS components via <Dynamic>,
|
|
6
|
+
* so no Web Component registration is needed.
|
|
7
|
+
*
|
|
8
|
+
* @template C - Widget configuration type
|
|
9
|
+
*/
|
|
10
|
+
export declare function defineWidget<C = Record<string, unknown>>(definition: WidgetDefinition<C>): WidgetDefinition<C>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Glow Component
|
|
3
|
+
*
|
|
4
|
+
* Background glow effect for widgets.
|
|
5
|
+
* Renders a radial gradient background at the BACKGROUND z-index layer.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Glow color="blue" />
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
import type { JSX } from "solid-js";
|
|
13
|
+
import type { ColorVariant } from "../types";
|
|
14
|
+
export interface GlowProps {
|
|
15
|
+
/** Glow color (Tailwind color name or CSS color) */
|
|
16
|
+
color: ColorVariant;
|
|
17
|
+
/** Additional CSS classes */
|
|
18
|
+
class?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Glow effect component
|
|
22
|
+
* Applies a blurred radial gradient background effect
|
|
23
|
+
*/
|
|
24
|
+
export declare function Glow(props: GlowProps): JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetSliderFill Component
|
|
3
|
+
*
|
|
4
|
+
* Animated fill overlay that follows a slider value.
|
|
5
|
+
* Automatically adapts direction based on widget orientation.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Widget gestures={{ slide: { value, onChange } }}>
|
|
10
|
+
* <Widget.SliderFill value={brightness} color="rgb(255, 200, 0)" />
|
|
11
|
+
* <Widget.Content>...</Widget.Content>
|
|
12
|
+
* </Widget>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
import type { JSX } from "solid-js";
|
|
16
|
+
export interface WidgetSliderFillProps {
|
|
17
|
+
/** Current value (0-100) */
|
|
18
|
+
value: number;
|
|
19
|
+
/** Fill color (CSS color string) */
|
|
20
|
+
color?: string;
|
|
21
|
+
/** Show glow effect */
|
|
22
|
+
glow?: boolean;
|
|
23
|
+
/** Opacity of the fill (0-1) */
|
|
24
|
+
opacity?: number;
|
|
25
|
+
/** Whether slider is currently being dragged (disables transition) */
|
|
26
|
+
isDragging?: boolean;
|
|
27
|
+
/** Additional CSS classes */
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Animated slider fill that adapts to widget orientation
|
|
32
|
+
*/
|
|
33
|
+
export declare function WidgetSliderFill(props: WidgetSliderFillProps): JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetContent Component
|
|
3
|
+
*
|
|
4
|
+
* Standard content container for widgets with consistent padding, gap, and layout direction.
|
|
5
|
+
*
|
|
6
|
+
* Uses contentLayout (not orientation) for UI arrangement:
|
|
7
|
+
* - Tall widgets (150px+) -> vertical layout (stacked)
|
|
8
|
+
* - Other widgets -> follows aspect ratio
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <Widget.Content>
|
|
13
|
+
* <Widget.Icon icon={<Power />} />
|
|
14
|
+
* <Widget.Title>Living Room</Widget.Title>
|
|
15
|
+
* </Widget.Content>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import type { JSX } from "solid-js";
|
|
19
|
+
export interface WidgetContentProps {
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Content children */
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Widget content container with auto-responsive layout
|
|
27
|
+
* Ensures proper z-index layering for title, status, and controls
|
|
28
|
+
*/
|
|
29
|
+
export declare function WidgetContent(props: WidgetContentProps): JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetEmptyState Component
|
|
3
|
+
*
|
|
4
|
+
* Placeholder component for widgets with no data or content.
|
|
5
|
+
* Shows a centered message with optional icon and action.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Widget.EmptyState
|
|
10
|
+
* icon={<AlertCircle />}
|
|
11
|
+
* title="No devices found"
|
|
12
|
+
* message="Add devices to see them here"
|
|
13
|
+
* action={<Button>Add Device</Button>}
|
|
14
|
+
* />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { JSX } from "solid-js";
|
|
18
|
+
export interface WidgetEmptyStateProps {
|
|
19
|
+
/** Icon to display (optional) */
|
|
20
|
+
icon?: JSX.Element;
|
|
21
|
+
/** Main title/heading */
|
|
22
|
+
title?: string;
|
|
23
|
+
/** Descriptive message */
|
|
24
|
+
message?: string;
|
|
25
|
+
/** Optional action button */
|
|
26
|
+
action?: JSX.Element;
|
|
27
|
+
/** Additional CSS classes */
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Widget empty state component
|
|
32
|
+
* Shows centered placeholder when widget has no content
|
|
33
|
+
*/
|
|
34
|
+
export declare function WidgetEmptyState(props: WidgetEmptyStateProps): JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetIcon Component
|
|
3
|
+
*
|
|
4
|
+
* Icon component with automatic sizing and glow effect.
|
|
5
|
+
* Supports both Tailwind classes and dynamic CSS colors for background/glow.
|
|
6
|
+
*
|
|
7
|
+
* @example Static color (Tailwind classes)
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Widget.Icon
|
|
10
|
+
* icon={<Power />}
|
|
11
|
+
* color="bg-blue-500 dark:bg-blue-400"
|
|
12
|
+
* glow="shadow-blue-500/50 dark:shadow-blue-400/50"
|
|
13
|
+
* />
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example Dynamic color (CSS color string — adaptive contrast)
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <Widget.Icon
|
|
19
|
+
* icon={<Lightbulb />}
|
|
20
|
+
* dynamicColor="hsl(320, 100%, 50%)"
|
|
21
|
+
* />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import type { JSX } from "solid-js";
|
|
25
|
+
export interface WidgetIconProps {
|
|
26
|
+
/** Icon component (JSX.Element) */
|
|
27
|
+
icon: JSX.Element;
|
|
28
|
+
/** Background color as Tailwind class (e.g. "bg-blue-500 dark:bg-blue-400") */
|
|
29
|
+
color?: string;
|
|
30
|
+
/** Glow/shadow effect as Tailwind class (e.g. "shadow-blue-500/50") */
|
|
31
|
+
glow?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Dynamic CSS color string (rgb, hsl, hex).
|
|
34
|
+
* When provided, icon background and glow are derived adaptively from this color.
|
|
35
|
+
* Takes precedence over `color` and `glow` props.
|
|
36
|
+
*/
|
|
37
|
+
dynamicColor?: string;
|
|
38
|
+
/** Reduce opacity */
|
|
39
|
+
dimmed?: boolean;
|
|
40
|
+
/** Number of entities - creates stacked background effect (1 = single, 2+ = stacked backgrounds) */
|
|
41
|
+
entityCount?: number;
|
|
42
|
+
/** Additional CSS classes */
|
|
43
|
+
class?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Widget icon component with auto-responsive sizing
|
|
47
|
+
*/
|
|
48
|
+
export declare function WidgetIcon(props: WidgetIconProps): JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetMetrics Component
|
|
3
|
+
*
|
|
4
|
+
* Small data displays for showing multiple stats/values.
|
|
5
|
+
* Automatically arranges metrics based on widget size.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Widget.Metrics>
|
|
10
|
+
* <Widget.Metrics.Item label="Temp" value="72F" />
|
|
11
|
+
* <Widget.Metrics.Item label="Humidity" value="45%" />
|
|
12
|
+
* <Widget.Metrics.Item label="Battery" value="87%" />
|
|
13
|
+
* </Widget.Metrics>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import type { JSX } from "solid-js";
|
|
17
|
+
export interface WidgetMetricsProps {
|
|
18
|
+
/** Layout direction (default: "auto" - horizontal for horizontal widgets, vertical for others) */
|
|
19
|
+
direction?: "horizontal" | "vertical" | "auto";
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Metric items */
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
export interface WidgetMetricsComponent {
|
|
26
|
+
(props: WidgetMetricsProps): JSX.Element;
|
|
27
|
+
Item: typeof WidgetMetricsItem;
|
|
28
|
+
}
|
|
29
|
+
export interface WidgetMetricsItemProps {
|
|
30
|
+
/** Metric label */
|
|
31
|
+
label: string;
|
|
32
|
+
/** Metric value */
|
|
33
|
+
value: string | number;
|
|
34
|
+
/** Optional unit */
|
|
35
|
+
unit?: string;
|
|
36
|
+
/** Optional icon */
|
|
37
|
+
icon?: JSX.Element;
|
|
38
|
+
/** Whether to dim the metric */
|
|
39
|
+
dimmed?: boolean;
|
|
40
|
+
/** Additional CSS classes */
|
|
41
|
+
class?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Individual metric item
|
|
45
|
+
*/
|
|
46
|
+
export declare function WidgetMetricsItem(props: WidgetMetricsItemProps): JSX.Element;
|
|
47
|
+
export declare const WidgetMetrics: WidgetMetricsComponent;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetStatus Component
|
|
3
|
+
*
|
|
4
|
+
* Status text component with auto-responsive typography.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Widget.Status>{entity.state}</Widget.Status>
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
import type { JSX } from "solid-js";
|
|
12
|
+
export interface WidgetStatusProps {
|
|
13
|
+
/** Reduce opacity further */
|
|
14
|
+
dimmed?: boolean;
|
|
15
|
+
/** Additional CSS classes */
|
|
16
|
+
class?: string;
|
|
17
|
+
/** Show "Unavailable" text instead of children */
|
|
18
|
+
isUnavailable?: boolean;
|
|
19
|
+
/** Status text */
|
|
20
|
+
children: JSX.Element;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Widget status component with auto-responsive typography
|
|
24
|
+
* Positioned above other content with proper z-index
|
|
25
|
+
*/
|
|
26
|
+
export declare function WidgetStatus(props: WidgetStatusProps): JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetSubtitle Component
|
|
3
|
+
*
|
|
4
|
+
* Secondary text component below the title with automatic typography scaling.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Widget.Subtitle>Living Room</Widget.Subtitle>
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @example With dimmed style
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Widget.Subtitle dimmed>2 devices offline</Widget.Subtitle>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import type { JSX } from "solid-js";
|
|
17
|
+
export interface WidgetSubtitleProps {
|
|
18
|
+
/** Whether to dim the subtitle */
|
|
19
|
+
dimmed?: boolean;
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Subtitle text */
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Widget subtitle component with auto-responsive typography
|
|
27
|
+
*/
|
|
28
|
+
export declare function WidgetSubtitle(props: WidgetSubtitleProps): JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetTitle Component
|
|
3
|
+
*
|
|
4
|
+
* Title component with automatic typography scaling and optional badge.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Widget.Title>{config.title}</Widget.Title>
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @example With badge
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Widget.Title badge={3}>Living Room</Widget.Title>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import type { JSX } from "solid-js";
|
|
17
|
+
export interface WidgetTitleProps {
|
|
18
|
+
/** Optional badge count */
|
|
19
|
+
badge?: number;
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Title text */
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Widget title component with auto-responsive typography
|
|
27
|
+
* Positioned above other content with proper z-index
|
|
28
|
+
*/
|
|
29
|
+
export declare function WidgetTitle(props: WidgetTitleProps): JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WidgetValue Component
|
|
3
|
+
*
|
|
4
|
+
* Numeric value display with optional unit and semantic interpretation.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Widget.Value value={22} unit="C" />
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @example With interpretation
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Widget.Value value={22} unit="C" interpret />
|
|
14
|
+
* // Displays: "22C Warm"
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { JSX } from "solid-js";
|
|
18
|
+
export interface WidgetValueProps {
|
|
19
|
+
/** The value to display */
|
|
20
|
+
value: number | string;
|
|
21
|
+
/** Unit of measurement */
|
|
22
|
+
unit?: string;
|
|
23
|
+
/** Show semantic interpretation */
|
|
24
|
+
interpret?: boolean;
|
|
25
|
+
/** Additional CSS classes */
|
|
26
|
+
class?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Widget value component with auto-formatting and interpretation
|
|
30
|
+
*/
|
|
31
|
+
export declare function WidgetValue(props: WidgetValueProps): JSX.Element;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget - Main Container Component
|
|
3
|
+
*
|
|
4
|
+
* The primary container for all widgets. Provides context, gesture handling,
|
|
5
|
+
* and base styling.
|
|
6
|
+
*
|
|
7
|
+
* @example Simple widget
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Widget gestures={{ tap: handleTap }}>
|
|
10
|
+
* <Widget.Icon icon={<Power />} />
|
|
11
|
+
* <Widget.Title>{title}</Widget.Title>
|
|
12
|
+
* </Widget>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example With gradient and loading
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Widget gradient="bg-gradient-to-br from-blue-500/40 to-blue-700/40" loading={isLoading}>
|
|
18
|
+
* {children}
|
|
19
|
+
* </Widget>
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { type JSX } from "solid-js";
|
|
23
|
+
import type { WidgetSliderFill as WidgetSliderFillType } from "../backgrounds/WidgetSliderFill";
|
|
24
|
+
import type { WidgetContent as WidgetContentType } from "../components/WidgetContent";
|
|
25
|
+
import type { WidgetEmptyState as WidgetEmptyStateType } from "../components/WidgetEmptyState";
|
|
26
|
+
import type { WidgetIcon as WidgetIconType } from "../components/WidgetIcon";
|
|
27
|
+
import type { WidgetMetrics as WidgetMetricsType } from "../components/WidgetMetrics";
|
|
28
|
+
import type { WidgetStatus as WidgetStatusType } from "../components/WidgetStatus";
|
|
29
|
+
import type { WidgetSubtitle as WidgetSubtitleType } from "../components/WidgetSubtitle";
|
|
30
|
+
import type { WidgetTitle as WidgetTitleType } from "../components/WidgetTitle";
|
|
31
|
+
import type { WidgetValue as WidgetValueType } from "../components/WidgetValue";
|
|
32
|
+
import type { WidgetOrientation, WidgetSize, WidgetVariantConfig } from "../types";
|
|
33
|
+
export interface WidgetEmptyStateConfig {
|
|
34
|
+
/** Icon to display */
|
|
35
|
+
icon?: JSX.Element;
|
|
36
|
+
/** Main title/heading */
|
|
37
|
+
title?: string;
|
|
38
|
+
/** Descriptive message */
|
|
39
|
+
message?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface WidgetProps {
|
|
42
|
+
/** Widget variant (string ID or inline config) */
|
|
43
|
+
variant?: string | WidgetVariantConfig;
|
|
44
|
+
/** Gradient background (Tailwind classes like "bg-gradient-to-br from-cyan-600/40 to-blue-700/40") */
|
|
45
|
+
gradient?: string;
|
|
46
|
+
/** Show loading overlay */
|
|
47
|
+
loading?: boolean;
|
|
48
|
+
/** Background glow color (Tailwind color like "bg-blue-500") (runtime override) */
|
|
49
|
+
backgroundGlow?: string;
|
|
50
|
+
/** Additional CSS classes */
|
|
51
|
+
class?: string;
|
|
52
|
+
/** Is edit mode (disables gestures) */
|
|
53
|
+
isEditMode?: boolean;
|
|
54
|
+
/** Called when delete button is clicked (only shown in edit mode) */
|
|
55
|
+
onDelete?: () => void;
|
|
56
|
+
/** Empty state configuration - when provided, shows empty state and applies gray gradient */
|
|
57
|
+
emptyState?: WidgetEmptyStateConfig;
|
|
58
|
+
/** Child elements */
|
|
59
|
+
children?: JSX.Element;
|
|
60
|
+
}
|
|
61
|
+
export interface WidgetComponent {
|
|
62
|
+
(props: WidgetProps): JSX.Element;
|
|
63
|
+
Content: typeof WidgetContentType;
|
|
64
|
+
Icon: typeof WidgetIconType;
|
|
65
|
+
Title: typeof WidgetTitleType;
|
|
66
|
+
Subtitle: typeof WidgetSubtitleType;
|
|
67
|
+
Status: typeof WidgetStatusType;
|
|
68
|
+
Value: typeof WidgetValueType;
|
|
69
|
+
Metrics: typeof WidgetMetricsType;
|
|
70
|
+
EmptyState: typeof WidgetEmptyStateType;
|
|
71
|
+
SliderFill: typeof WidgetSliderFillType;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Classify widget size based on grid dimensions
|
|
75
|
+
*/
|
|
76
|
+
export declare function classifySize(gridWidth: number, gridHeight: number): WidgetSize;
|
|
77
|
+
/**
|
|
78
|
+
* Detect orientation from dimensions based on aspect ratio
|
|
79
|
+
* Used for gesture direction (slide horizontal vs vertical)
|
|
80
|
+
*/
|
|
81
|
+
export declare function detectOrientation(width: number, height: number): WidgetOrientation;
|
|
82
|
+
/**
|
|
83
|
+
* Detect content layout direction
|
|
84
|
+
* Used for UI arrangement (stack vertically vs horizontally)
|
|
85
|
+
* Considers height threshold - tall widgets benefit from vertical stacking
|
|
86
|
+
*/
|
|
87
|
+
export declare function detectContentLayout(width: number, height: number): WidgetOrientation;
|
|
88
|
+
export declare const Widget: WidgetComponent;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design System - Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Responsive design tokens for widget sizing, typography, and layering.
|
|
5
|
+
*/
|
|
6
|
+
export { getSpacingClass, spacing } from "./spacing";
|
|
7
|
+
export { typography } from "./typography";
|
|
8
|
+
export { WIDGET_Z, type WidgetZIndex } from "./z-index";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacing System
|
|
3
|
+
*
|
|
4
|
+
* Provides responsive spacing that adapts to widget size.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const { size } = useWidgetContext();
|
|
9
|
+
*
|
|
10
|
+
* <div style={{ "margin-top": spacing.iconToTitle(size) }}>
|
|
11
|
+
* <Widget.Title>{title}</Widget.Title>
|
|
12
|
+
* </div>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
import type { SpacingScale, WidgetSize } from "../types";
|
|
16
|
+
/**
|
|
17
|
+
* Get spacing value based on widget size
|
|
18
|
+
*/
|
|
19
|
+
export declare const spacing: {
|
|
20
|
+
/** Extra small spacing (4-8px) */
|
|
21
|
+
S1: (size: WidgetSize) => string;
|
|
22
|
+
/** Small spacing (6-14px) - default for most layouts */
|
|
23
|
+
S2: (size: WidgetSize) => string;
|
|
24
|
+
/** Medium spacing (8-16px) */
|
|
25
|
+
S3: (size: WidgetSize) => string;
|
|
26
|
+
/** Large spacing (12-20px) */
|
|
27
|
+
S4: (size: WidgetSize) => string;
|
|
28
|
+
/** Icon container size in pixels */
|
|
29
|
+
icon: (size: WidgetSize) => number;
|
|
30
|
+
/** Icon stroke size for lucide icons */
|
|
31
|
+
iconSize: (size: WidgetSize) => number;
|
|
32
|
+
/** Spacing between icon and title */
|
|
33
|
+
iconToTitle: (size: WidgetSize) => string;
|
|
34
|
+
/** Container padding */
|
|
35
|
+
container: (size: WidgetSize) => string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Get Tailwind spacing class name for layout components
|
|
39
|
+
*/
|
|
40
|
+
export declare function getSpacingClass(scale: SpacingScale, size: WidgetSize): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typography System
|
|
3
|
+
*
|
|
4
|
+
* Provides responsive typography classes that adapt to widget size.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const { size } = useWidgetContext();
|
|
9
|
+
*
|
|
10
|
+
* <h3 class={cn("font-bold text-white", typography.title(size))}>
|
|
11
|
+
* {title}
|
|
12
|
+
* </h3>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
import type { WidgetSize } from "../types";
|
|
16
|
+
/**
|
|
17
|
+
* Typography utilities based on current widget patterns
|
|
18
|
+
* Matches existing container query breakpoints from LockWidget:
|
|
19
|
+
* - text-sm @[300px]:text-base @[400px]:text-lg
|
|
20
|
+
*/
|
|
21
|
+
export declare const typography: {
|
|
22
|
+
/** Container base text sizing */
|
|
23
|
+
container: (size: WidgetSize) => string;
|
|
24
|
+
/** Title text sizing (main heading) */
|
|
25
|
+
title: (size: WidgetSize) => string;
|
|
26
|
+
/** Subtitle/secondary text sizing */
|
|
27
|
+
subtitle: (size: WidgetSize) => string;
|
|
28
|
+
/** Value display text sizing (large numbers) */
|
|
29
|
+
value: (size: WidgetSize) => string;
|
|
30
|
+
/** Badge text sizing (entity count badges) */
|
|
31
|
+
badge: (size: WidgetSize) => string;
|
|
32
|
+
/** Metric label text sizing */
|
|
33
|
+
metricLabel: (size: WidgetSize) => string;
|
|
34
|
+
/** Metric value text sizing */
|
|
35
|
+
metricValue: (size: WidgetSize) => string;
|
|
36
|
+
/** Status text (same as subtitle but semantic) */
|
|
37
|
+
status: (size: WidgetSize) => string;
|
|
38
|
+
/** Empty state message text */
|
|
39
|
+
emptyState: (size: WidgetSize) => string;
|
|
40
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Z-Index Constants
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent z-index layering for widget elements.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <div style={{ "z-index": WIDGET_Z.BACKGROUND }}>
|
|
9
|
+
* <CustomBackground />
|
|
10
|
+
* </div>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare const WIDGET_Z: {
|
|
14
|
+
/** Background layer (gradients, images, glows) */
|
|
15
|
+
readonly BACKGROUND: 0;
|
|
16
|
+
/** Main content layer (icon, title, text) */
|
|
17
|
+
readonly CONTENT: 10;
|
|
18
|
+
/** Overlay layer (loading states, volume indicators) */
|
|
19
|
+
readonly OVERLAY: 20;
|
|
20
|
+
/** Action layer (buttons, edit controls) */
|
|
21
|
+
readonly ACTIONS: 30;
|
|
22
|
+
};
|
|
23
|
+
export type WidgetZIndex = (typeof WIDGET_Z)[keyof typeof WIDGET_Z];
|