@tangle-network/ui 11.43.0 → 11.44.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @tangle-network/ui
|
|
2
2
|
|
|
3
|
+
## 11.44.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e19c28a: Add read-only `value` and optional `mono` presentation to SettingsRow while preserving children, the public props interface, and control message wiring. Value rows use the inline layout and stack in narrow cards; rows without a value keep their existing layout.
|
|
8
|
+
|
|
3
9
|
## 11.43.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -24,21 +24,25 @@ export interface SettingsRowProps {
|
|
|
24
24
|
onRetry?: () => void;
|
|
25
25
|
/**
|
|
26
26
|
* `inline` (default): text left, control right, stacked below 34rem.
|
|
27
|
-
* `compact`: the control keeps its own width and stays on the line (switches, single buttons)
|
|
27
|
+
* `compact`: the control keeps its own width and stays on the line (switches, single buttons); a row with a value uses `inline`.
|
|
28
28
|
* `stacked`: the control spans the row under the text (textareas, lists).
|
|
29
29
|
*/
|
|
30
30
|
layout?: SettingsRowLayout;
|
|
31
31
|
/** Why the control is unavailable, naming who can change it. Replaces the description after a lock glyph. */
|
|
32
32
|
disabledReason?: React.ReactNode;
|
|
33
|
+
/** A read-only value before any children; supplying even an empty value keeps its span. */
|
|
34
|
+
value?: React.ReactNode;
|
|
35
|
+
/** Use mono for the value, such as an identifier; children keep their own font. */
|
|
36
|
+
mono?: boolean;
|
|
33
37
|
children?: React.ReactNode;
|
|
34
38
|
}
|
|
35
39
|
/**
|
|
36
|
-
* One setting: its label, an optional consequence line and
|
|
40
|
+
* One setting: its label, an optional consequence line, read-only value and control. The
|
|
37
41
|
* label carries the save status after it; an error or a lock reason replaces
|
|
38
42
|
* the description. Rows inside a {@link SettingsSection} are divided by a
|
|
39
43
|
* hairline and stack when the card is narrower than 34rem.
|
|
40
44
|
*/
|
|
41
|
-
export declare function SettingsRow(
|
|
45
|
+
export declare function SettingsRow(props: SettingsRowProps): React.JSX.Element;
|
|
42
46
|
export interface SettingsSectionProps {
|
|
43
47
|
/** The section's anchor: `#id` scrolls to it. The title's id is `${id}-title`. */
|
|
44
48
|
id: string;
|
|
@@ -60,18 +60,20 @@ function describeControl(children, htmlFor, messageId, invalid) {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
* One setting: its label, an optional consequence line and
|
|
63
|
+
* One setting: its label, an optional consequence line, read-only value and control. The
|
|
64
64
|
* label carries the save status after it; an error or a lock reason replaces
|
|
65
65
|
* the description. Rows inside a {@link SettingsSection} are divided by a
|
|
66
66
|
* hairline and stack when the card is narrower than 34rem.
|
|
67
67
|
*/
|
|
68
|
-
function SettingsRow(
|
|
68
|
+
function SettingsRow(props) {
|
|
69
|
+
const { id, label, description, info, htmlFor, status, error, onRetry, layout = "inline", disabledReason, value, mono, children } = props;
|
|
70
|
+
const hasValue = Object.hasOwn(props, "value");
|
|
69
71
|
const messageId = htmlFor ? fieldMessageId(htmlFor) : void 0;
|
|
70
72
|
const control = describeControl(children, htmlFor, error != null || disabledReason != null || description != null ? messageId : void 0, error != null);
|
|
71
73
|
return /* @__PURE__ */ jsxs("div", {
|
|
72
74
|
id,
|
|
73
75
|
"data-layout": layout,
|
|
74
|
-
className: cn("grid min-w-0 items-center gap-x-8 gap-y-3 px-5 py-4 @max-[34rem]/settings-section:px-4", SCROLL_OFFSET, DIVIDED, ROW_COLUMNS[layout]),
|
|
76
|
+
className: cn("grid min-w-0 items-center gap-x-8 gap-y-3 px-5 py-4 @max-[34rem]/settings-section:px-4", SCROLL_OFFSET, DIVIDED, ROW_COLUMNS[hasValue && layout === "compact" ? "inline" : layout]),
|
|
75
77
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
76
78
|
className: "min-w-0",
|
|
77
79
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -114,9 +116,13 @@ function SettingsRow({ id, label, description, info, htmlFor, status, error, onR
|
|
|
114
116
|
className: "mt-0.5 text-sm leading-5 text-muted-foreground [overflow-wrap:anywhere]",
|
|
115
117
|
children: description
|
|
116
118
|
})]
|
|
117
|
-
}), control != null && control !== false && /* @__PURE__ */
|
|
118
|
-
className: cn("flex min-w-0 items-center gap-2", ROW_CONTROL[layout]),
|
|
119
|
-
children:
|
|
119
|
+
}), (hasValue || control != null && control !== false) && /* @__PURE__ */ jsxs("div", {
|
|
120
|
+
className: cn("flex min-w-0 items-center gap-2", ROW_CONTROL[hasValue && layout === "compact" ? "inline" : layout]),
|
|
121
|
+
children: [hasValue && /* @__PURE__ */ jsx("span", {
|
|
122
|
+
"data-slot": "settings-value",
|
|
123
|
+
className: cn("min-w-0 text-foreground text-sm [overflow-wrap:anywhere] @min-[34rem]/settings-section:text-right", mono && "font-mono"),
|
|
124
|
+
children: value
|
|
125
|
+
}), control]
|
|
120
126
|
})]
|
|
121
127
|
});
|
|
122
128
|
}
|
package/package.json
CHANGED
|
@@ -243,6 +243,40 @@ function FieldsExample() {
|
|
|
243
243
|
);
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
/** Read-only product data beside existing controls; all values here are sample data. */
|
|
247
|
+
function SettingsValuesExample() {
|
|
248
|
+
const [details, setDetails] = useState(false);
|
|
249
|
+
return (
|
|
250
|
+
<div className="mx-auto max-w-4xl space-y-6 p-6">
|
|
251
|
+
<SettingsSection id="read-only-values" title="Account values">
|
|
252
|
+
<SettingsRow id="value-zero" label="Active sessions" value={0} layout="compact" />
|
|
253
|
+
<SettingsRow id="value-empty" label="Empty value" value="" layout="compact" />
|
|
254
|
+
<SettingsRow id="value-false" label="False value" value={false} layout="compact" />
|
|
255
|
+
<SettingsRow id="value-null" label="Null value" value={null} layout="compact" />
|
|
256
|
+
<SettingsRow id="value-undefined" label="Undefined value" value={undefined} layout="compact" />
|
|
257
|
+
<SettingsRow id="value-mixed" label="Projected monthly cost" value={<>$0.00 <span className="text-muted-foreground">/month</span></>} layout="compact" />
|
|
258
|
+
<SettingsRow id="value-long" label="Session identifier" value="session_with_a_long_unbroken_identifier_that_must_wrap_inside_its_settings_card_without_hiding_the_label_or_overflowing" mono layout="compact" />
|
|
259
|
+
<SettingsRow id="value-agent" label="Agent identifier" value="research-agent" mono layout="compact" />
|
|
260
|
+
<SettingsRow id="value-model" label="Model identifier" value="workspace-model" mono layout="compact" />
|
|
261
|
+
<SettingsRow id="value-provider" label="Provider identifier" value="workspace-provider" mono layout="compact" />
|
|
262
|
+
<SettingsRow id="value-stacked" label="Stacked summary" value="Workspace summary" layout="stacked" />
|
|
263
|
+
<SettingsRow id="value-action" label="Value with action" value="workspace-provider" status={details ? "Details shown" : undefined} layout="compact">
|
|
264
|
+
<Button type="button" variant="outline" onClick={() => setDetails((shown) => !shown)}>{details ? "Hide details" : "Show details"}</Button>
|
|
265
|
+
</SettingsRow>
|
|
266
|
+
<SettingsRow id="value-control" label="Value with input" value="UTC" htmlFor="value-timezone" description="The original input keeps its message wiring.">
|
|
267
|
+
<Input id="value-timezone" defaultValue="UTC" />
|
|
268
|
+
</SettingsRow>
|
|
269
|
+
</SettingsSection>
|
|
270
|
+
<div className="max-w-sm">
|
|
271
|
+
<SettingsSection id="narrow-values" title="Narrow card in any window">
|
|
272
|
+
<SettingsRow id="narrow-value" label="Account email" value="reader@workspace.example" layout="compact" />
|
|
273
|
+
<SettingsRow id="legacy-compact" label="Daily digest" htmlFor="value-digest" layout="compact"><Switch id="value-digest" defaultChecked /></SettingsRow>
|
|
274
|
+
</SettingsSection>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
246
280
|
const meta = {
|
|
247
281
|
title: "Primitives/Settings",
|
|
248
282
|
component: SettingsSection,
|
|
@@ -265,3 +299,6 @@ export const Bounded: Story = { render: () => <SettingsPage className="mx-auto m
|
|
|
265
299
|
|
|
266
300
|
/** The promoted Field: hint, info tip with an aside action, a live error, and a status. */
|
|
267
301
|
export const Fields: Story = { render: () => <FieldsExample /> };
|
|
302
|
+
|
|
303
|
+
/** Values preserve ReactNode content and coexist with controls; only value rows stack in a narrow compact layout. */
|
|
304
|
+
export const Values: Story = { render: () => <SettingsValuesExample /> };
|
|
@@ -67,12 +67,16 @@ export interface SettingsRowProps {
|
|
|
67
67
|
onRetry?: () => void;
|
|
68
68
|
/**
|
|
69
69
|
* `inline` (default): text left, control right, stacked below 34rem.
|
|
70
|
-
* `compact`: the control keeps its own width and stays on the line (switches, single buttons)
|
|
70
|
+
* `compact`: the control keeps its own width and stays on the line (switches, single buttons); a row with a value uses `inline`.
|
|
71
71
|
* `stacked`: the control spans the row under the text (textareas, lists).
|
|
72
72
|
*/
|
|
73
73
|
layout?: SettingsRowLayout;
|
|
74
74
|
/** Why the control is unavailable, naming who can change it. Replaces the description after a lock glyph. */
|
|
75
75
|
disabledReason?: React.ReactNode;
|
|
76
|
+
/** A read-only value before any children; supplying even an empty value keeps its span. */
|
|
77
|
+
value?: React.ReactNode;
|
|
78
|
+
/** Use mono for the value, such as an identifier; children keep their own font. */
|
|
79
|
+
mono?: boolean;
|
|
76
80
|
children?: React.ReactNode;
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -101,14 +105,16 @@ function describeControl(children: React.ReactNode, htmlFor: string | undefined,
|
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
/**
|
|
104
|
-
* One setting: its label, an optional consequence line and
|
|
108
|
+
* One setting: its label, an optional consequence line, read-only value and control. The
|
|
105
109
|
* label carries the save status after it; an error or a lock reason replaces
|
|
106
110
|
* the description. Rows inside a {@link SettingsSection} are divided by a
|
|
107
111
|
* hairline and stack when the card is narrower than 34rem.
|
|
108
112
|
*/
|
|
109
|
-
export function SettingsRow({
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
export function SettingsRow(props: SettingsRowProps) {
|
|
114
|
+
const {
|
|
115
|
+
id, label, description, info, htmlFor, status, error, onRetry, layout = "inline", disabledReason, value, mono, children,
|
|
116
|
+
} = props;
|
|
117
|
+
const hasValue = Object.hasOwn(props, "value");
|
|
112
118
|
const messageId = htmlFor ? fieldMessageId(htmlFor) : undefined;
|
|
113
119
|
const hasMessage = error != null || disabledReason != null || description != null;
|
|
114
120
|
const control = describeControl(children, htmlFor, hasMessage ? messageId : undefined, error != null);
|
|
@@ -120,7 +126,7 @@ export function SettingsRow({
|
|
|
120
126
|
"grid min-w-0 items-center gap-x-8 gap-y-3 px-5 py-4 @max-[34rem]/settings-section:px-4",
|
|
121
127
|
SCROLL_OFFSET,
|
|
122
128
|
DIVIDED,
|
|
123
|
-
ROW_COLUMNS[layout],
|
|
129
|
+
ROW_COLUMNS[hasValue && layout === "compact" ? "inline" : layout],
|
|
124
130
|
)}
|
|
125
131
|
>
|
|
126
132
|
<div className="min-w-0">
|
|
@@ -142,8 +148,11 @@ export function SettingsRow({
|
|
|
142
148
|
<div id={messageId} className="mt-0.5 text-sm leading-5 text-muted-foreground [overflow-wrap:anywhere]">{description}</div>
|
|
143
149
|
)}
|
|
144
150
|
</div>
|
|
145
|
-
{control != null && control !== false && (
|
|
146
|
-
<div className={cn("flex min-w-0 items-center gap-2", ROW_CONTROL[layout])}>
|
|
151
|
+
{(hasValue || (control != null && control !== false)) && (
|
|
152
|
+
<div className={cn("flex min-w-0 items-center gap-2", ROW_CONTROL[hasValue && layout === "compact" ? "inline" : layout])}>
|
|
153
|
+
{hasValue && <span data-slot="settings-value" className={cn("min-w-0 text-foreground text-sm [overflow-wrap:anywhere] @min-[34rem]/settings-section:text-right", mono && "font-mono")}>{value}</span>}
|
|
154
|
+
{control}
|
|
155
|
+
</div>
|
|
147
156
|
)}
|
|
148
157
|
</div>
|
|
149
158
|
);
|