opentui-responsive 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -26
- package/dist/react/index.d.ts +26 -11
- package/dist/react/index.js +18 -13
- package/dist/solid/index.d.ts +26 -11
- package/dist/solid/index.js +19 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,17 +58,15 @@ export function Layout(props: ParentProps) {
|
|
|
58
58
|
import { useBreakpoint } from "./layout.tsx";
|
|
59
59
|
|
|
60
60
|
export function Content() {
|
|
61
|
-
const
|
|
62
|
-
//
|
|
63
|
-
const isWideAndTall =
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
const hasMediumViewport = breakpoint.atLeast(["medium", "medium"]);
|
|
61
|
+
const [width, height, viewport] = useBreakpoint();
|
|
62
|
+
// Each accessor can be named for its local use.
|
|
63
|
+
const isWideAndTall = viewport(["wide", "tall"]);
|
|
64
|
+
const isMediumOrWider = width.atLeast("medium");
|
|
65
|
+
const hasMediumViewport = viewport.atLeast(["medium", "medium"]);
|
|
67
66
|
|
|
68
67
|
return (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<text>{`${breakpoint().width}/${breakpoint().height}`}</text>
|
|
68
|
+
<box flexDirection={width() === "wide" ? "row" : "column"}>
|
|
69
|
+
<text>{`${width()}/${height()}`}</text>
|
|
72
70
|
<text>
|
|
73
71
|
{isWideAndTall || (isMediumOrWider && hasMediumViewport) ? "Full layout" : "Compact layout"}
|
|
74
72
|
</text>
|
|
@@ -92,14 +90,19 @@ export function App() {
|
|
|
92
90
|
}
|
|
93
91
|
```
|
|
94
92
|
|
|
95
|
-
`useBreakpoint()` updates when the terminal crosses a configured threshold.
|
|
93
|
+
`useBreakpoint()` updates when the terminal crosses a configured threshold. It returns `[width, height, viewport]`, letting each caller choose local names while keeping breakpoint names scoped to their axis. Width and height accept one breakpoint name; viewport accepts a `[width, height]` pair. Viewport pair comparisons return true only when both axes satisfy the relation.
|
|
96
94
|
|
|
97
95
|
```tsx
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
const [width, height, viewport] = useBreakpoint();
|
|
97
|
+
|
|
98
|
+
width.below("medium");
|
|
99
|
+
viewport.atMost(["medium", "tall"]);
|
|
100
|
+
height.only("short");
|
|
101
|
+
viewport.atLeast(["medium", "medium"]);
|
|
102
|
+
width.above("medium");
|
|
103
|
+
|
|
104
|
+
const [sidebarWidth] = useBreakpoint();
|
|
105
|
+
const [, , layoutViewport] = useBreakpoint();
|
|
103
106
|
```
|
|
104
107
|
|
|
105
108
|
Run `bun run demo` from the package directory to try the Solid example. Resize the terminal to see its layout respond.
|
|
@@ -110,15 +113,16 @@ The React adapter has the same factory, provider, hook, and inferred breakpoint
|
|
|
110
113
|
|
|
111
114
|
### `opentui-responsive/solid` and `opentui-responsive/react`
|
|
112
115
|
|
|
113
|
-
| API
|
|
114
|
-
|
|
|
115
|
-
| `createResponsiveTui(scales)`
|
|
116
|
-
| `ResponsiveTUI`
|
|
117
|
-
| `useBreakpoint()`
|
|
118
|
-
| `ResponsiveBreakpointAccessor`
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
116
|
+
| API | Description |
|
|
117
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
118
|
+
| `createResponsiveTui(scales)` | Validates the scales and creates a `ResponsiveTUI` provider and `useBreakpoint` hook. |
|
|
119
|
+
| `ResponsiveTUI` | Tracks terminal dimensions and provides the current breakpoint accessor. |
|
|
120
|
+
| `useBreakpoint()` | Reads `[width, height, viewport]` from the nearest generated provider. |
|
|
121
|
+
| `ResponsiveBreakpointAccessor` | The readonly `[width, height, viewport]` accessor tuple. |
|
|
122
|
+
| `ResponsiveBreakpointAxisAccessor` | Reads or compares one axis using that axis's breakpoint names. |
|
|
123
|
+
| `ResponsiveBreakpointViewportAccessor` | Reads or compares the complete viewport using `[width, height]` pairs. |
|
|
124
|
+
| `ResponsiveTuiConfigurationError` | Thrown when the supplied breakpoint scales are invalid. |
|
|
125
|
+
| `ResponsiveTuiProviderError` | Thrown when the generated hook is called outside its provider. |
|
|
122
126
|
|
|
123
127
|
### `opentui-responsive/core`
|
|
124
128
|
|
|
@@ -140,7 +144,7 @@ Width and height use independent sets of inclusive minimum thresholds measured i
|
|
|
140
144
|
|
|
141
145
|
Declaration order does not affect matching. Each axis selects its highest satisfied threshold.
|
|
142
146
|
|
|
143
|
-
Relation methods compare complete tiers rather than their raw threshold values. Given `width: { narrow: 0, medium: 60, wide: 100 }`, `atMost("
|
|
147
|
+
Relation methods compare complete tiers rather than their raw threshold values. Given `width: { narrow: 0, medium: 60, wide: 100 }`, `width.atMost("medium")` matches widths from `0` through `99`.
|
|
144
148
|
|
|
145
149
|
| Method | Tier relation |
|
|
146
150
|
| --------- | ------------- |
|
|
@@ -150,7 +154,7 @@ Relation methods compare complete tiers rather than their raw threshold values.
|
|
|
150
154
|
| `atLeast` | `>=` |
|
|
151
155
|
| `above` | `>` |
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
Width and height relation methods each accept a name from their own scale. Viewport relation methods accept `[width, height]` pairs and use AND semantics. Calling `viewport.only(["wide", "tall"])` is equivalent to calling `viewport(["wide", "tall"])`. The `/core` relation matchers retain `(viewport, axis, name)` and `(viewport, [width, height])` forms for adapter implementations.
|
|
154
158
|
|
|
155
159
|
Use breakpoints for discrete layout modes. Keep continuous measurements such as progress-bar width and available list height on OpenTUI's `useTerminalDimensions()`.
|
|
156
160
|
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
import { type PropsWithChildren } from "react";
|
|
2
2
|
import { createBreakpointDefinition, type BreakpointAxis, type BreakpointMatch, type BreakpointPair, type BreakpointScales } from "../core/index.js";
|
|
3
3
|
export { ResponsiveTuiConfigurationError } from "../core/index.js";
|
|
4
|
-
/** A React breakpoint relation test for one axis
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** A React breakpoint relation test for one axis. */
|
|
5
|
+
export type ResponsiveBreakpointAxisRelationMatcher<Scales extends BreakpointScales = BreakpointScales, Axis extends BreakpointAxis = BreakpointAxis> = {
|
|
6
|
+
(name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
7
|
+
};
|
|
8
|
+
/** A React accessor that reads or tests one breakpoint axis. */
|
|
9
|
+
export type ResponsiveBreakpointAxisAccessor<Scales extends BreakpointScales = BreakpointScales, Axis extends BreakpointAxis = BreakpointAxis> = {
|
|
10
|
+
(): BreakpointMatch<Scales>[Axis];
|
|
11
|
+
(name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
12
|
+
readonly below: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
13
|
+
readonly atMost: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
14
|
+
readonly only: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
15
|
+
readonly atLeast: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
16
|
+
readonly above: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
8
17
|
};
|
|
9
|
-
/** A React accessor that reads or tests the
|
|
10
|
-
export type
|
|
18
|
+
/** A React accessor that reads or tests the complete breakpoint viewport. */
|
|
19
|
+
export type ResponsiveBreakpointViewportAccessor<Scales extends BreakpointScales = BreakpointScales> = {
|
|
11
20
|
(): BreakpointMatch<Scales>;
|
|
12
21
|
(pair: BreakpointPair<Scales>): boolean;
|
|
13
|
-
readonly below:
|
|
14
|
-
readonly atMost:
|
|
15
|
-
readonly only:
|
|
16
|
-
readonly atLeast:
|
|
17
|
-
readonly above:
|
|
22
|
+
readonly below: (pair: BreakpointPair<Scales>) => boolean;
|
|
23
|
+
readonly atMost: (pair: BreakpointPair<Scales>) => boolean;
|
|
24
|
+
readonly only: (pair: BreakpointPair<Scales>) => boolean;
|
|
25
|
+
readonly atLeast: (pair: BreakpointPair<Scales>) => boolean;
|
|
26
|
+
readonly above: (pair: BreakpointPair<Scales>) => boolean;
|
|
18
27
|
};
|
|
28
|
+
/** React breakpoint accessors in width, height, then viewport order. */
|
|
29
|
+
export type ResponsiveBreakpointAccessor<Scales extends BreakpointScales = BreakpointScales> = readonly [
|
|
30
|
+
width: ResponsiveBreakpointAxisAccessor<Scales, "width">,
|
|
31
|
+
height: ResponsiveBreakpointAxisAccessor<Scales, "height">,
|
|
32
|
+
viewport: ResponsiveBreakpointViewportAccessor<Scales>
|
|
33
|
+
];
|
|
19
34
|
/** Thrown when a responsive hook is used outside its generated React provider. */
|
|
20
35
|
export declare class ResponsiveTuiProviderError extends Error {
|
|
21
36
|
readonly _tag = "ResponsiveTuiProviderError";
|
package/dist/react/index.js
CHANGED
|
@@ -123,14 +123,16 @@ var createResponsiveTui = (scales) => {
|
|
|
123
123
|
const ResponsiveTuiContext = createContext(undefined);
|
|
124
124
|
const ResponsiveTUI = (props) => {
|
|
125
125
|
const dimensions = useTerminalDimensions();
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
const width = bindAxisAccessor("width", () => dimensions, breakpoints);
|
|
127
|
+
const height = bindAxisAccessor("height", () => dimensions, breakpoints);
|
|
128
|
+
const viewport = Object.assign((pair) => pair ? breakpoints.matches(dimensions, pair) : breakpoints.match(dimensions), {
|
|
129
|
+
below: bindViewportRelation(() => dimensions, breakpoints.below),
|
|
130
|
+
atMost: bindViewportRelation(() => dimensions, breakpoints.atMost),
|
|
131
|
+
only: bindViewportRelation(() => dimensions, breakpoints.only),
|
|
132
|
+
atLeast: bindViewportRelation(() => dimensions, breakpoints.atLeast),
|
|
133
|
+
above: bindViewportRelation(() => dimensions, breakpoints.above)
|
|
133
134
|
});
|
|
135
|
+
const breakpoint = [width, height, viewport];
|
|
134
136
|
return createElement(ResponsiveTuiContext.Provider, { value: breakpoint }, props.children);
|
|
135
137
|
};
|
|
136
138
|
const useBreakpoint = () => {
|
|
@@ -142,12 +144,15 @@ var createResponsiveTui = (scales) => {
|
|
|
142
144
|
};
|
|
143
145
|
return { ResponsiveTUI, useBreakpoint };
|
|
144
146
|
};
|
|
145
|
-
var
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
var bindAxisAccessor = (axis, viewport, breakpoints) => Object.assign((name) => name === undefined ? breakpoints.match(viewport())[axis] : breakpoints.only(viewport(), axis, name), {
|
|
148
|
+
below: bindAxisRelation(axis, viewport, breakpoints.below),
|
|
149
|
+
atMost: bindAxisRelation(axis, viewport, breakpoints.atMost),
|
|
150
|
+
only: bindAxisRelation(axis, viewport, breakpoints.only),
|
|
151
|
+
atLeast: bindAxisRelation(axis, viewport, breakpoints.atLeast),
|
|
152
|
+
above: bindAxisRelation(axis, viewport, breakpoints.above)
|
|
153
|
+
});
|
|
154
|
+
var bindAxisRelation = (axis, viewport, relation) => (name) => relation(viewport(), axis, name);
|
|
155
|
+
var bindViewportRelation = (viewport, relation) => (pair) => relation(viewport(), pair);
|
|
151
156
|
export {
|
|
152
157
|
ResponsiveTuiConfigurationError,
|
|
153
158
|
ResponsiveTuiProviderError,
|
package/dist/solid/index.d.ts
CHANGED
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
import { type ParentProps } from "solid-js";
|
|
2
2
|
import { createBreakpointDefinition, type BreakpointAxis, type BreakpointMatch, type BreakpointPair, type BreakpointScales } from "../core/index.js";
|
|
3
3
|
export { ResponsiveTuiConfigurationError } from "../core/index.js";
|
|
4
|
-
/** A reactive Solid breakpoint relation test for one axis
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** A reactive Solid breakpoint relation test for one axis. */
|
|
5
|
+
export type ResponsiveBreakpointAxisRelationMatcher<Scales extends BreakpointScales = BreakpointScales, Axis extends BreakpointAxis = BreakpointAxis> = {
|
|
6
|
+
(name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
7
|
+
};
|
|
8
|
+
/** A reactive Solid accessor that reads or tests one breakpoint axis. */
|
|
9
|
+
export type ResponsiveBreakpointAxisAccessor<Scales extends BreakpointScales = BreakpointScales, Axis extends BreakpointAxis = BreakpointAxis> = {
|
|
10
|
+
(): BreakpointMatch<Scales>[Axis];
|
|
11
|
+
(name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
12
|
+
readonly below: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
13
|
+
readonly atMost: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
14
|
+
readonly only: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
15
|
+
readonly atLeast: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
16
|
+
readonly above: ResponsiveBreakpointAxisRelationMatcher<Scales, Axis>;
|
|
8
17
|
};
|
|
9
|
-
/** A reactive Solid accessor that reads or tests the
|
|
10
|
-
export type
|
|
18
|
+
/** A reactive Solid accessor that reads or tests the complete breakpoint viewport. */
|
|
19
|
+
export type ResponsiveBreakpointViewportAccessor<Scales extends BreakpointScales = BreakpointScales> = {
|
|
11
20
|
(): BreakpointMatch<Scales>;
|
|
12
21
|
(pair: BreakpointPair<Scales>): boolean;
|
|
13
|
-
readonly below:
|
|
14
|
-
readonly atMost:
|
|
15
|
-
readonly only:
|
|
16
|
-
readonly atLeast:
|
|
17
|
-
readonly above:
|
|
22
|
+
readonly below: (pair: BreakpointPair<Scales>) => boolean;
|
|
23
|
+
readonly atMost: (pair: BreakpointPair<Scales>) => boolean;
|
|
24
|
+
readonly only: (pair: BreakpointPair<Scales>) => boolean;
|
|
25
|
+
readonly atLeast: (pair: BreakpointPair<Scales>) => boolean;
|
|
26
|
+
readonly above: (pair: BreakpointPair<Scales>) => boolean;
|
|
18
27
|
};
|
|
28
|
+
/** Reactive Solid breakpoint accessors in width, height, then viewport order. */
|
|
29
|
+
export type ResponsiveBreakpointAccessor<Scales extends BreakpointScales = BreakpointScales> = readonly [
|
|
30
|
+
width: ResponsiveBreakpointAxisAccessor<Scales, "width">,
|
|
31
|
+
height: ResponsiveBreakpointAxisAccessor<Scales, "height">,
|
|
32
|
+
viewport: ResponsiveBreakpointViewportAccessor<Scales>
|
|
33
|
+
];
|
|
19
34
|
/** Thrown when a responsive hook is used outside its generated Solid provider. */
|
|
20
35
|
export declare class ResponsiveTuiProviderError extends Error {
|
|
21
36
|
readonly _tag = "ResponsiveTuiProviderError";
|
package/dist/solid/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/solid/index.ts
|
|
2
2
|
import { useTerminalDimensions } from "@opentui/solid";
|
|
3
|
-
import { createContext,
|
|
3
|
+
import { createContext, useContext } from "solid-js";
|
|
4
4
|
|
|
5
5
|
// src/core/breakpoints.ts
|
|
6
6
|
class ResponsiveTuiConfigurationError extends Error {
|
|
@@ -123,15 +123,16 @@ var createResponsiveTui = (scales) => {
|
|
|
123
123
|
const ResponsiveTuiContext = createContext();
|
|
124
124
|
const ResponsiveTUI = (props) => {
|
|
125
125
|
const dimensions = useTerminalDimensions();
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
below:
|
|
130
|
-
atMost:
|
|
131
|
-
only:
|
|
132
|
-
atLeast:
|
|
133
|
-
above:
|
|
126
|
+
const width = bindAxisAccessor("width", dimensions, breakpoints);
|
|
127
|
+
const height = bindAxisAccessor("height", dimensions, breakpoints);
|
|
128
|
+
const viewport = Object.assign((pair) => pair ? breakpoints.matches(dimensions(), pair) : breakpoints.match(dimensions()), {
|
|
129
|
+
below: bindViewportRelation(dimensions, breakpoints.below),
|
|
130
|
+
atMost: bindViewportRelation(dimensions, breakpoints.atMost),
|
|
131
|
+
only: bindViewportRelation(dimensions, breakpoints.only),
|
|
132
|
+
atLeast: bindViewportRelation(dimensions, breakpoints.atLeast),
|
|
133
|
+
above: bindViewportRelation(dimensions, breakpoints.above)
|
|
134
134
|
});
|
|
135
|
+
const breakpoint = [width, height, viewport];
|
|
135
136
|
return ResponsiveTuiContext.Provider({
|
|
136
137
|
get children() {
|
|
137
138
|
return props.children;
|
|
@@ -148,12 +149,15 @@ var createResponsiveTui = (scales) => {
|
|
|
148
149
|
};
|
|
149
150
|
return { ResponsiveTUI, useBreakpoint };
|
|
150
151
|
};
|
|
151
|
-
var
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
var bindAxisAccessor = (axis, viewport, breakpoints) => Object.assign((name) => name === undefined ? breakpoints.match(viewport())[axis] : breakpoints.only(viewport(), axis, name), {
|
|
153
|
+
below: bindAxisRelation(axis, viewport, breakpoints.below),
|
|
154
|
+
atMost: bindAxisRelation(axis, viewport, breakpoints.atMost),
|
|
155
|
+
only: bindAxisRelation(axis, viewport, breakpoints.only),
|
|
156
|
+
atLeast: bindAxisRelation(axis, viewport, breakpoints.atLeast),
|
|
157
|
+
above: bindAxisRelation(axis, viewport, breakpoints.above)
|
|
158
|
+
});
|
|
159
|
+
var bindAxisRelation = (axis, viewport, relation) => (name) => relation(viewport(), axis, name);
|
|
160
|
+
var bindViewportRelation = (viewport, relation) => (pair) => relation(viewport(), pair);
|
|
157
161
|
export {
|
|
158
162
|
ResponsiveTuiConfigurationError,
|
|
159
163
|
ResponsiveTuiProviderError,
|