opentui-responsive 0.3.0 → 0.4.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 +38 -11
- package/dist/core/breakpoints.d.ts +10 -0
- package/dist/core/index.js +40 -8
- package/dist/react/index.d.ts +11 -1
- package/dist/react/index.js +54 -9
- package/dist/solid/index.d.ts +11 -1
- package/dist/solid/index.js +54 -9
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -61,12 +61,17 @@ export function Content() {
|
|
|
61
61
|
const breakpoint = useBreakpoint();
|
|
62
62
|
// You can use it to directly check [width, height] breakpoint
|
|
63
63
|
const isWideAndTall = breakpoint(["wide", "tall"]);
|
|
64
|
+
// Compare one axis, or compare both axes with AND semantics
|
|
65
|
+
const isMediumOrWider = breakpoint.atLeast("width", "medium");
|
|
66
|
+
const hasMediumViewport = breakpoint.atLeast(["medium", "medium"]);
|
|
64
67
|
|
|
65
68
|
return (
|
|
66
69
|
// Or you can get the current width and height breakpoint
|
|
67
70
|
<box flexDirection={breakpoint().width === "wide" ? "row" : "column"}>
|
|
68
71
|
<text>{`${breakpoint().width}/${breakpoint().height}`}</text>
|
|
69
|
-
<text>
|
|
72
|
+
<text>
|
|
73
|
+
{isWideAndTall || (isMediumOrWider && hasMediumViewport) ? "Full layout" : "Compact layout"}
|
|
74
|
+
</text>
|
|
70
75
|
</box>
|
|
71
76
|
);
|
|
72
77
|
}
|
|
@@ -87,7 +92,15 @@ export function App() {
|
|
|
87
92
|
}
|
|
88
93
|
```
|
|
89
94
|
|
|
90
|
-
`useBreakpoint()` updates when the terminal crosses a configured threshold. Its accessor returns the current width and height names,
|
|
95
|
+
`useBreakpoint()` updates when the terminal crosses a configured threshold. Its accessor returns the current width and height names, accepts an exact `[width, height]` pair, and provides named relation methods. Relation methods accept either an axis and name or a pair; pair comparisons return true only when both axes satisfy the relation.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
breakpoint.below("width", "medium");
|
|
99
|
+
breakpoint.atMost(["medium", "tall"]);
|
|
100
|
+
breakpoint.only("height", "short");
|
|
101
|
+
breakpoint.atLeast(["medium", "medium"]);
|
|
102
|
+
breakpoint.above("width", "medium");
|
|
103
|
+
```
|
|
91
104
|
|
|
92
105
|
Run `bun run demo` from the package directory to try the Solid example. Resize the terminal to see its layout respond.
|
|
93
106
|
|
|
@@ -97,14 +110,15 @@ The React adapter has the same factory, provider, hook, and inferred breakpoint
|
|
|
97
110
|
|
|
98
111
|
### `opentui-responsive/solid` and `opentui-responsive/react`
|
|
99
112
|
|
|
100
|
-
| API
|
|
101
|
-
|
|
|
102
|
-
| `createResponsiveTui(scales)`
|
|
103
|
-
| `ResponsiveTUI`
|
|
104
|
-
| `useBreakpoint()`
|
|
105
|
-
| `ResponsiveBreakpointAccessor`
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
113
|
+
| API | Description |
|
|
114
|
+
| ------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
115
|
+
| `createResponsiveTui(scales)` | Validates the scales and creates a `ResponsiveTUI` provider and `useBreakpoint` hook. |
|
|
116
|
+
| `ResponsiveTUI` | Tracks terminal dimensions and provides the current breakpoint accessor. |
|
|
117
|
+
| `useBreakpoint()` | Reads the accessor from the nearest generated provider. |
|
|
118
|
+
| `ResponsiveBreakpointAccessor` | Reads the current match or tests exact and relative breakpoint positions. |
|
|
119
|
+
| `ResponsiveBreakpointRelationMatcher` | Tests one axis or an AND-combined width and height pair. |
|
|
120
|
+
| `ResponsiveTuiConfigurationError` | Thrown when the supplied breakpoint scales are invalid. |
|
|
121
|
+
| `ResponsiveTuiProviderError` | Thrown when the generated hook is called outside its provider. |
|
|
108
122
|
|
|
109
123
|
### `opentui-responsive/core`
|
|
110
124
|
|
|
@@ -117,14 +131,27 @@ For implementing another framework adapter, not application setup:
|
|
|
117
131
|
| `BreakpointScales` | The width and height scale configuration. |
|
|
118
132
|
| `BreakpointMatch` | The matched breakpoint name for each axis. |
|
|
119
133
|
| `BreakpointPair` | An exact breakpoint pair in width-then-height order. |
|
|
134
|
+
| `BreakpointRelationMatcher` | Tests one axis or an AND-combined pair against a named relation. |
|
|
120
135
|
| `ResponsiveTuiConfigurationError` | Thrown when supplied breakpoint scales are invalid. |
|
|
121
136
|
|
|
122
137
|
## Breakpoint Behavior
|
|
123
138
|
|
|
124
|
-
Width and height use independent sets of inclusive minimum thresholds measured in terminal cells. Each axis must contain a zero threshold so every terminal size has a match. Names must be non-empty, and thresholds must be unique finite non-negative integers within their axis.
|
|
139
|
+
Width and height use independent sets of inclusive minimum thresholds measured in terminal cells. A threshold is selected when the dimension is greater than or equal to it: for example, a width threshold of `60` matches at `width >= 60`. Each axis must contain a zero threshold so every terminal size has a match. Names must be non-empty, and thresholds must be unique finite non-negative integers within their axis.
|
|
125
140
|
|
|
126
141
|
Declaration order does not affect matching. Each axis selects its highest satisfied threshold.
|
|
127
142
|
|
|
143
|
+
Relation methods compare complete tiers rather than their raw threshold values. Given `width: { narrow: 0, medium: 60, wide: 100 }`, `atMost("width", "medium")` matches widths from `0` through `99`.
|
|
144
|
+
|
|
145
|
+
| Method | Tier relation |
|
|
146
|
+
| --------- | ------------- |
|
|
147
|
+
| `below` | `<` |
|
|
148
|
+
| `atMost` | `<=` |
|
|
149
|
+
| `only` | `===` |
|
|
150
|
+
| `atLeast` | `>=` |
|
|
151
|
+
| `above` | `>` |
|
|
152
|
+
|
|
153
|
+
Each method accepts `(axis, name)` for a single-axis comparison or `[width, height]` for a two-axis comparison. Two-axis comparisons use AND semantics. Calling `breakpoint.only(["wide", "tall"])` is equivalent to calling `breakpoint(["wide", "tall"])`.
|
|
154
|
+
|
|
128
155
|
Use breakpoints for discrete layout modes. Keep continuous measurements such as progress-bar width and available list height on OpenTUI's `useTerminalDimensions()`.
|
|
129
156
|
|
|
130
157
|
## Runtime Support
|
|
@@ -24,10 +24,20 @@ export type BreakpointPair<Scales extends BreakpointScales = BreakpointScales> =
|
|
|
24
24
|
width: BreakpointMatch<Scales>["width"],
|
|
25
25
|
height: BreakpointMatch<Scales>["height"]
|
|
26
26
|
];
|
|
27
|
+
/** Tests one axis or both axes against a named breakpoint relation. */
|
|
28
|
+
export type BreakpointRelationMatcher<Scales extends BreakpointScales = BreakpointScales> = {
|
|
29
|
+
<Axis extends BreakpointAxis>(viewport: BreakpointViewport, axis: Axis, name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
30
|
+
(viewport: BreakpointViewport, pair: BreakpointPair<Scales>): boolean;
|
|
31
|
+
};
|
|
27
32
|
/** A validated breakpoint matcher for framework adapter implementations. */
|
|
28
33
|
export type BreakpointDefinition<Scales extends BreakpointScales = BreakpointScales> = {
|
|
29
34
|
readonly match: (viewport: BreakpointViewport) => BreakpointMatch<Scales>;
|
|
30
35
|
readonly matches: (viewport: BreakpointViewport, pair: BreakpointPair<Scales>) => boolean;
|
|
36
|
+
readonly below: BreakpointRelationMatcher<Scales>;
|
|
37
|
+
readonly atMost: BreakpointRelationMatcher<Scales>;
|
|
38
|
+
readonly only: BreakpointRelationMatcher<Scales>;
|
|
39
|
+
readonly atLeast: BreakpointRelationMatcher<Scales>;
|
|
40
|
+
readonly above: BreakpointRelationMatcher<Scales>;
|
|
31
41
|
};
|
|
32
42
|
/** Thrown when breakpoint scales cannot produce a valid definition. */
|
|
33
43
|
export declare class ResponsiveTuiConfigurationError extends Error {
|
package/dist/core/index.js
CHANGED
|
@@ -12,12 +12,19 @@ var createBreakpointDefinition = (scales) => {
|
|
|
12
12
|
width: matchScale(viewport.width, entries.width),
|
|
13
13
|
height: matchScale(viewport.height, entries.height)
|
|
14
14
|
});
|
|
15
|
+
const below = createRelationMatcher(entries, "below");
|
|
16
|
+
const atMost = createRelationMatcher(entries, "atMost");
|
|
17
|
+
const only = createRelationMatcher(entries, "only");
|
|
18
|
+
const atLeast = createRelationMatcher(entries, "atLeast");
|
|
19
|
+
const above = createRelationMatcher(entries, "above");
|
|
15
20
|
return {
|
|
16
21
|
match,
|
|
17
|
-
matches: (viewport, pair) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
matches: (viewport, pair) => only(viewport, pair),
|
|
23
|
+
below,
|
|
24
|
+
atMost,
|
|
25
|
+
only,
|
|
26
|
+
atLeast,
|
|
27
|
+
above
|
|
21
28
|
};
|
|
22
29
|
};
|
|
23
30
|
var breakpointAxes = ["width", "height"];
|
|
@@ -63,14 +70,39 @@ var validateScale = (axis, scale) => {
|
|
|
63
70
|
return validated.sort((left, right) => left[1] - right[1]);
|
|
64
71
|
};
|
|
65
72
|
var matchScale = (value, entries) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
return entries[matchScaleIndex(value, entries)][0];
|
|
74
|
+
};
|
|
75
|
+
var matchScaleIndex = (value, entries) => {
|
|
76
|
+
let match = 0;
|
|
77
|
+
for (let index = 1;index < entries.length; index += 1) {
|
|
78
|
+
if (value < entries[index][1])
|
|
69
79
|
break;
|
|
70
|
-
match =
|
|
80
|
+
match = index;
|
|
71
81
|
}
|
|
72
82
|
return match;
|
|
73
83
|
};
|
|
84
|
+
var createRelationMatcher = (entries, relation) => (viewport, axisOrPair, name) => {
|
|
85
|
+
if (Array.isArray(axisOrPair)) {
|
|
86
|
+
return matchesRelation(viewport.width, entries.width, axisOrPair[0], relation) && matchesRelation(viewport.height, entries.height, axisOrPair[1], relation);
|
|
87
|
+
}
|
|
88
|
+
const axis = axisOrPair;
|
|
89
|
+
return matchesRelation(viewport[axis], entries[axis], name, relation);
|
|
90
|
+
};
|
|
91
|
+
var matchesRelation = (value, entries, name, relation) => {
|
|
92
|
+
const target = entries.findIndex(([entryName]) => entryName === name);
|
|
93
|
+
if (target === -1)
|
|
94
|
+
return false;
|
|
95
|
+
const current = matchScaleIndex(value, entries);
|
|
96
|
+
if (relation === "below")
|
|
97
|
+
return current < target;
|
|
98
|
+
if (relation === "atMost")
|
|
99
|
+
return current <= target;
|
|
100
|
+
if (relation === "only")
|
|
101
|
+
return current === target;
|
|
102
|
+
if (relation === "atLeast")
|
|
103
|
+
return current >= target;
|
|
104
|
+
return current > target;
|
|
105
|
+
};
|
|
74
106
|
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
75
107
|
var isThreshold = (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0;
|
|
76
108
|
export {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { type PropsWithChildren } from "react";
|
|
2
|
-
import { createBreakpointDefinition, type BreakpointMatch, type BreakpointPair, type BreakpointScales } from "../core/index.js";
|
|
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 or both axes. */
|
|
5
|
+
export type ResponsiveBreakpointRelationMatcher<Scales extends BreakpointScales = BreakpointScales> = {
|
|
6
|
+
<Axis extends BreakpointAxis>(axis: Axis, name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
7
|
+
(pair: BreakpointPair<Scales>): boolean;
|
|
8
|
+
};
|
|
4
9
|
/** A React accessor that reads or tests the current breakpoint pair. */
|
|
5
10
|
export type ResponsiveBreakpointAccessor<Scales extends BreakpointScales = BreakpointScales> = {
|
|
6
11
|
(): BreakpointMatch<Scales>;
|
|
7
12
|
(pair: BreakpointPair<Scales>): boolean;
|
|
13
|
+
readonly below: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
14
|
+
readonly atMost: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
15
|
+
readonly only: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
16
|
+
readonly atLeast: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
17
|
+
readonly above: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
8
18
|
};
|
|
9
19
|
/** Thrown when a responsive hook is used outside its generated React provider. */
|
|
10
20
|
export declare class ResponsiveTuiProviderError extends Error {
|
package/dist/react/index.js
CHANGED
|
@@ -16,12 +16,19 @@ var createBreakpointDefinition = (scales) => {
|
|
|
16
16
|
width: matchScale(viewport.width, entries.width),
|
|
17
17
|
height: matchScale(viewport.height, entries.height)
|
|
18
18
|
});
|
|
19
|
+
const below = createRelationMatcher(entries, "below");
|
|
20
|
+
const atMost = createRelationMatcher(entries, "atMost");
|
|
21
|
+
const only = createRelationMatcher(entries, "only");
|
|
22
|
+
const atLeast = createRelationMatcher(entries, "atLeast");
|
|
23
|
+
const above = createRelationMatcher(entries, "above");
|
|
19
24
|
return {
|
|
20
25
|
match,
|
|
21
|
-
matches: (viewport, pair) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
matches: (viewport, pair) => only(viewport, pair),
|
|
27
|
+
below,
|
|
28
|
+
atMost,
|
|
29
|
+
only,
|
|
30
|
+
atLeast,
|
|
31
|
+
above
|
|
25
32
|
};
|
|
26
33
|
};
|
|
27
34
|
var breakpointAxes = ["width", "height"];
|
|
@@ -67,14 +74,39 @@ var validateScale = (axis, scale) => {
|
|
|
67
74
|
return validated.sort((left, right) => left[1] - right[1]);
|
|
68
75
|
};
|
|
69
76
|
var matchScale = (value, entries) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
return entries[matchScaleIndex(value, entries)][0];
|
|
78
|
+
};
|
|
79
|
+
var matchScaleIndex = (value, entries) => {
|
|
80
|
+
let match = 0;
|
|
81
|
+
for (let index = 1;index < entries.length; index += 1) {
|
|
82
|
+
if (value < entries[index][1])
|
|
73
83
|
break;
|
|
74
|
-
match =
|
|
84
|
+
match = index;
|
|
75
85
|
}
|
|
76
86
|
return match;
|
|
77
87
|
};
|
|
88
|
+
var createRelationMatcher = (entries, relation) => (viewport, axisOrPair, name) => {
|
|
89
|
+
if (Array.isArray(axisOrPair)) {
|
|
90
|
+
return matchesRelation(viewport.width, entries.width, axisOrPair[0], relation) && matchesRelation(viewport.height, entries.height, axisOrPair[1], relation);
|
|
91
|
+
}
|
|
92
|
+
const axis = axisOrPair;
|
|
93
|
+
return matchesRelation(viewport[axis], entries[axis], name, relation);
|
|
94
|
+
};
|
|
95
|
+
var matchesRelation = (value, entries, name, relation) => {
|
|
96
|
+
const target = entries.findIndex(([entryName]) => entryName === name);
|
|
97
|
+
if (target === -1)
|
|
98
|
+
return false;
|
|
99
|
+
const current = matchScaleIndex(value, entries);
|
|
100
|
+
if (relation === "below")
|
|
101
|
+
return current < target;
|
|
102
|
+
if (relation === "atMost")
|
|
103
|
+
return current <= target;
|
|
104
|
+
if (relation === "only")
|
|
105
|
+
return current === target;
|
|
106
|
+
if (relation === "atLeast")
|
|
107
|
+
return current >= target;
|
|
108
|
+
return current > target;
|
|
109
|
+
};
|
|
78
110
|
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
79
111
|
var isThreshold = (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0;
|
|
80
112
|
|
|
@@ -91,7 +123,14 @@ var createResponsiveTui = (scales) => {
|
|
|
91
123
|
const ResponsiveTuiContext = createContext(undefined);
|
|
92
124
|
const ResponsiveTUI = (props) => {
|
|
93
125
|
const dimensions = useTerminalDimensions();
|
|
94
|
-
const
|
|
126
|
+
const bind = (relation) => bindRelation(() => dimensions, relation);
|
|
127
|
+
const breakpoint = Object.assign((pair) => pair ? breakpoints.matches(dimensions, pair) : breakpoints.match(dimensions), {
|
|
128
|
+
below: bind(breakpoints.below),
|
|
129
|
+
atMost: bind(breakpoints.atMost),
|
|
130
|
+
only: bind(breakpoints.only),
|
|
131
|
+
atLeast: bind(breakpoints.atLeast),
|
|
132
|
+
above: bind(breakpoints.above)
|
|
133
|
+
});
|
|
95
134
|
return createElement(ResponsiveTuiContext.Provider, { value: breakpoint }, props.children);
|
|
96
135
|
};
|
|
97
136
|
const useBreakpoint = () => {
|
|
@@ -103,6 +142,12 @@ var createResponsiveTui = (scales) => {
|
|
|
103
142
|
};
|
|
104
143
|
return { ResponsiveTUI, useBreakpoint };
|
|
105
144
|
};
|
|
145
|
+
var bindRelation = (viewport, relation) => (axisOrPair, name) => {
|
|
146
|
+
if (typeof axisOrPair !== "string") {
|
|
147
|
+
return relation(viewport(), axisOrPair);
|
|
148
|
+
}
|
|
149
|
+
return relation(viewport(), axisOrPair, name);
|
|
150
|
+
};
|
|
106
151
|
export {
|
|
107
152
|
ResponsiveTuiConfigurationError,
|
|
108
153
|
ResponsiveTuiProviderError,
|
package/dist/solid/index.d.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { type ParentProps } from "solid-js";
|
|
2
|
-
import { createBreakpointDefinition, type BreakpointMatch, type BreakpointPair, type BreakpointScales } from "../core/index.js";
|
|
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 or both axes. */
|
|
5
|
+
export type ResponsiveBreakpointRelationMatcher<Scales extends BreakpointScales = BreakpointScales> = {
|
|
6
|
+
<Axis extends BreakpointAxis>(axis: Axis, name: BreakpointMatch<Scales>[Axis]): boolean;
|
|
7
|
+
(pair: BreakpointPair<Scales>): boolean;
|
|
8
|
+
};
|
|
4
9
|
/** A reactive Solid accessor that reads or tests the current breakpoint pair. */
|
|
5
10
|
export type ResponsiveBreakpointAccessor<Scales extends BreakpointScales = BreakpointScales> = {
|
|
6
11
|
(): BreakpointMatch<Scales>;
|
|
7
12
|
(pair: BreakpointPair<Scales>): boolean;
|
|
13
|
+
readonly below: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
14
|
+
readonly atMost: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
15
|
+
readonly only: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
16
|
+
readonly atLeast: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
17
|
+
readonly above: ResponsiveBreakpointRelationMatcher<Scales>;
|
|
8
18
|
};
|
|
9
19
|
/** Thrown when a responsive hook is used outside its generated Solid provider. */
|
|
10
20
|
export declare class ResponsiveTuiProviderError extends Error {
|
package/dist/solid/index.js
CHANGED
|
@@ -16,12 +16,19 @@ var createBreakpointDefinition = (scales) => {
|
|
|
16
16
|
width: matchScale(viewport.width, entries.width),
|
|
17
17
|
height: matchScale(viewport.height, entries.height)
|
|
18
18
|
});
|
|
19
|
+
const below = createRelationMatcher(entries, "below");
|
|
20
|
+
const atMost = createRelationMatcher(entries, "atMost");
|
|
21
|
+
const only = createRelationMatcher(entries, "only");
|
|
22
|
+
const atLeast = createRelationMatcher(entries, "atLeast");
|
|
23
|
+
const above = createRelationMatcher(entries, "above");
|
|
19
24
|
return {
|
|
20
25
|
match,
|
|
21
|
-
matches: (viewport, pair) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
matches: (viewport, pair) => only(viewport, pair),
|
|
27
|
+
below,
|
|
28
|
+
atMost,
|
|
29
|
+
only,
|
|
30
|
+
atLeast,
|
|
31
|
+
above
|
|
25
32
|
};
|
|
26
33
|
};
|
|
27
34
|
var breakpointAxes = ["width", "height"];
|
|
@@ -67,14 +74,39 @@ var validateScale = (axis, scale) => {
|
|
|
67
74
|
return validated.sort((left, right) => left[1] - right[1]);
|
|
68
75
|
};
|
|
69
76
|
var matchScale = (value, entries) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
return entries[matchScaleIndex(value, entries)][0];
|
|
78
|
+
};
|
|
79
|
+
var matchScaleIndex = (value, entries) => {
|
|
80
|
+
let match = 0;
|
|
81
|
+
for (let index = 1;index < entries.length; index += 1) {
|
|
82
|
+
if (value < entries[index][1])
|
|
73
83
|
break;
|
|
74
|
-
match =
|
|
84
|
+
match = index;
|
|
75
85
|
}
|
|
76
86
|
return match;
|
|
77
87
|
};
|
|
88
|
+
var createRelationMatcher = (entries, relation) => (viewport, axisOrPair, name) => {
|
|
89
|
+
if (Array.isArray(axisOrPair)) {
|
|
90
|
+
return matchesRelation(viewport.width, entries.width, axisOrPair[0], relation) && matchesRelation(viewport.height, entries.height, axisOrPair[1], relation);
|
|
91
|
+
}
|
|
92
|
+
const axis = axisOrPair;
|
|
93
|
+
return matchesRelation(viewport[axis], entries[axis], name, relation);
|
|
94
|
+
};
|
|
95
|
+
var matchesRelation = (value, entries, name, relation) => {
|
|
96
|
+
const target = entries.findIndex(([entryName]) => entryName === name);
|
|
97
|
+
if (target === -1)
|
|
98
|
+
return false;
|
|
99
|
+
const current = matchScaleIndex(value, entries);
|
|
100
|
+
if (relation === "below")
|
|
101
|
+
return current < target;
|
|
102
|
+
if (relation === "atMost")
|
|
103
|
+
return current <= target;
|
|
104
|
+
if (relation === "only")
|
|
105
|
+
return current === target;
|
|
106
|
+
if (relation === "atLeast")
|
|
107
|
+
return current >= target;
|
|
108
|
+
return current > target;
|
|
109
|
+
};
|
|
78
110
|
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
79
111
|
var isThreshold = (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0;
|
|
80
112
|
|
|
@@ -92,7 +124,14 @@ var createResponsiveTui = (scales) => {
|
|
|
92
124
|
const ResponsiveTUI = (props) => {
|
|
93
125
|
const dimensions = useTerminalDimensions();
|
|
94
126
|
const current = createMemo(() => breakpoints.match(dimensions()));
|
|
95
|
-
const
|
|
127
|
+
const bind = (relation) => bindRelation(dimensions, relation);
|
|
128
|
+
const breakpoint = Object.assign((pair) => pair ? breakpoints.matches(dimensions(), pair) : current(), {
|
|
129
|
+
below: bind(breakpoints.below),
|
|
130
|
+
atMost: bind(breakpoints.atMost),
|
|
131
|
+
only: bind(breakpoints.only),
|
|
132
|
+
atLeast: bind(breakpoints.atLeast),
|
|
133
|
+
above: bind(breakpoints.above)
|
|
134
|
+
});
|
|
96
135
|
return ResponsiveTuiContext.Provider({
|
|
97
136
|
get children() {
|
|
98
137
|
return props.children;
|
|
@@ -109,6 +148,12 @@ var createResponsiveTui = (scales) => {
|
|
|
109
148
|
};
|
|
110
149
|
return { ResponsiveTUI, useBreakpoint };
|
|
111
150
|
};
|
|
151
|
+
var bindRelation = (viewport, relation) => (axisOrPair, name) => {
|
|
152
|
+
if (typeof axisOrPair !== "string") {
|
|
153
|
+
return relation(viewport(), axisOrPair);
|
|
154
|
+
}
|
|
155
|
+
return relation(viewport(), axisOrPair, name);
|
|
156
|
+
};
|
|
112
157
|
export {
|
|
113
158
|
ResponsiveTuiConfigurationError,
|
|
114
159
|
ResponsiveTuiProviderError,
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opentui-responsive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Typed responsive breakpoints for OpenTUI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"breakpoints",
|
|
7
|
+
"cli",
|
|
7
8
|
"opentui",
|
|
8
9
|
"reactjs",
|
|
9
10
|
"responsive",
|
|
10
|
-
"solidjs"
|
|
11
|
+
"solidjs",
|
|
12
|
+
"terminal",
|
|
13
|
+
"tui"
|
|
11
14
|
],
|
|
12
15
|
"license": "MIT",
|
|
13
16
|
"repository": {
|