@gntik-ai/templates 0.10.0 → 0.11.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.ts +34 -8
- package/dist/index.js +167 -125
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/resource-detail/CustomTabs.tsx +41 -0
- package/src/resource-detail/Page.default.test.tsx +28 -0
- package/src/resource-detail/Page.shell-less.test.tsx +36 -0
- package/src/resource-detail/Page.tabs.test.tsx +116 -0
- package/src/resource-detail/Page.tsx +62 -27
- package/src/resource-detail/__snapshots__/Page.default.test.tsx.snap +7 -0
- package/src/resource-detail/examples/embedded-custom-tabs.tsx +44 -0
- package/src/resource-detail/template.meta.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -648,6 +648,17 @@ declare function ResetPasswordPage({ onSubmit, onContinue, error, minPasswordLen
|
|
|
648
648
|
//#region src/reset-password/template.meta.d.ts
|
|
649
649
|
declare const meta$29: TemplateMeta;
|
|
650
650
|
//#endregion
|
|
651
|
+
//#region src/resource-detail/CustomTabs.d.ts
|
|
652
|
+
interface CustomTabsProps {
|
|
653
|
+
tabs: {
|
|
654
|
+
value: string;
|
|
655
|
+
label: string;
|
|
656
|
+
content: ReactNode;
|
|
657
|
+
}[];
|
|
658
|
+
defaultTab?: string;
|
|
659
|
+
onTabChange?: (tab: string) => void;
|
|
660
|
+
}
|
|
661
|
+
//#endregion
|
|
651
662
|
//#region src/resource-detail/data.d.ts
|
|
652
663
|
/** The editable part of the resource (Settings tab). */
|
|
653
664
|
interface ResourceSettings {
|
|
@@ -663,11 +674,11 @@ interface ResourceDetailLabels {
|
|
|
663
674
|
settings: string;
|
|
664
675
|
sections: string;
|
|
665
676
|
}
|
|
666
|
-
interface
|
|
677
|
+
interface ResourceDetailBaseProps {
|
|
667
678
|
/** Per-key copy overrides; explicit props take precedence, then labels, then the active catalog. */
|
|
668
679
|
labels?: Partial<ResourceDetailLabels>;
|
|
669
680
|
/**
|
|
670
|
-
* Optional boolean, default false.
|
|
681
|
+
* Optional boolean, default false. With built-in tabs, shows only the keyboard-accessible Overview tab in
|
|
671
682
|
* the "Resource sections" tablist, using explicit resource props without sample defaults.
|
|
672
683
|
* Ignores activity, events, dangerActions, defaultTab, onSaveSettings and onDangerAction.
|
|
673
684
|
* Explicit actions and onEditDetails are still honored. ConsoleShell defaults are unchanged.
|
|
@@ -696,16 +707,31 @@ interface ResourceDetailProps {
|
|
|
696
707
|
events: readonly StatusEvent[];
|
|
697
708
|
activity: readonly ActivityItem[];
|
|
698
709
|
dangerActions: DangerZoneAction[];
|
|
699
|
-
defaultTab: ResourceDetailTab;
|
|
700
|
-
onTabChange: (tab: ResourceDetailTab) => void;
|
|
701
710
|
onEditDetails: () => void;
|
|
702
711
|
onSaveSettings: (settings: ResourceSettings) => void;
|
|
703
712
|
/** Confirmed Danger zone action id (e.g. `pause`, `delete`). */
|
|
704
713
|
onDangerAction: (actionId: string) => void | Promise<void>;
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
714
|
+
/** null omits ConsoleShell; undefined or an object preserves the default frame. */
|
|
715
|
+
shell: Omit<ConsoleShellProps, 'children'> | null;
|
|
716
|
+
}
|
|
717
|
+
type ResourceDetailTabsProps = {
|
|
718
|
+
tabs?: undefined;
|
|
719
|
+
defaultTab?: ResourceDetailTab;
|
|
720
|
+
onTabChange?: (tab: ResourceDetailTab) => void;
|
|
721
|
+
} |
|
|
722
|
+
/** Replaces the built-in tabs, including in read-only mode; [] hides the tab set. */
|
|
723
|
+
CustomTabsProps;
|
|
724
|
+
type ResourceDetailProps = ResourceDetailBaseProps & ResourceDetailTabsProps;
|
|
725
|
+
/**
|
|
726
|
+
* Resource detail: editable tabs by default, or explicit-only Overview when readOnly is true.
|
|
727
|
+
* Pass tabs to replace the built-in sections with caller labels, values and content; readOnly
|
|
728
|
+
* does not filter custom tabs. An omitted or unknown defaultTab selects the first custom tab.
|
|
729
|
+
* shell={null} renders only Page and its header. The host owns the main landmark and must
|
|
730
|
+
* provide ChartLocaleProvider when its custom chart content needs a locale. Breadcrumbs
|
|
731
|
+
* render in the header in this mode: pass a trail or [] to avoid the editable sample trail.
|
|
732
|
+
* Omitted or object shells and omitted tabs preserve the existing default output.
|
|
733
|
+
*/
|
|
734
|
+
declare function ResourceDetailPage(props: Partial<ResourceDetailBaseProps> & ResourceDetailTabsProps): import("react").JSX.Element;
|
|
709
735
|
//#endregion
|
|
710
736
|
//#region src/resource-detail/template.meta.d.ts
|
|
711
737
|
declare const meta$30: TemplateMeta;
|
package/dist/index.js
CHANGED
|
@@ -3003,6 +3003,33 @@ const meta$29 = {
|
|
|
3003
3003
|
blocks: ["reset-password-form"]
|
|
3004
3004
|
};
|
|
3005
3005
|
//#endregion
|
|
3006
|
+
//#region src/resource-detail/CustomTabs.tsx
|
|
3007
|
+
function CustomTabs({ tabs, defaultTab, onTabChange, label }) {
|
|
3008
|
+
const [selected, setSelected] = useState(defaultTab);
|
|
3009
|
+
const value = tabs.find((tab) => tab.value === selected)?.value ?? tabs[0]?.value ?? null;
|
|
3010
|
+
if (tabs.length === 0) return null;
|
|
3011
|
+
return /* @__PURE__ */ jsxs(Tabs, {
|
|
3012
|
+
value,
|
|
3013
|
+
onValueChange: (next) => {
|
|
3014
|
+
const tab = tabs.find((tab) => tab.value === next);
|
|
3015
|
+
if (tab) {
|
|
3016
|
+
setSelected(tab.value);
|
|
3017
|
+
onTabChange?.(tab.value);
|
|
3018
|
+
}
|
|
3019
|
+
},
|
|
3020
|
+
children: [/* @__PURE__ */ jsx(TabsList, {
|
|
3021
|
+
"aria-label": label,
|
|
3022
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsx(TabsTab, {
|
|
3023
|
+
value: tab.value,
|
|
3024
|
+
children: tab.label
|
|
3025
|
+
}, tab.value))
|
|
3026
|
+
}), tabs.map((tab) => /* @__PURE__ */ jsx(TabsPanel, {
|
|
3027
|
+
value: tab.value,
|
|
3028
|
+
children: tab.content
|
|
3029
|
+
}, tab.value))]
|
|
3030
|
+
});
|
|
3031
|
+
}
|
|
3032
|
+
//#endregion
|
|
3006
3033
|
//#region src/resource-detail/data.ts
|
|
3007
3034
|
const detailResource = {
|
|
3008
3035
|
name: "orders-api",
|
|
@@ -3058,11 +3085,19 @@ const TABS = [
|
|
|
3058
3085
|
"activity",
|
|
3059
3086
|
"settings"
|
|
3060
3087
|
];
|
|
3061
|
-
/**
|
|
3088
|
+
/**
|
|
3089
|
+
* Resource detail: editable tabs by default, or explicit-only Overview when readOnly is true.
|
|
3090
|
+
* Pass tabs to replace the built-in sections with caller labels, values and content; readOnly
|
|
3091
|
+
* does not filter custom tabs. An omitted or unknown defaultTab selects the first custom tab.
|
|
3092
|
+
* shell={null} renders only Page and its header. The host owns the main landmark and must
|
|
3093
|
+
* provide ChartLocaleProvider when its custom chart content needs a locale. Breadcrumbs
|
|
3094
|
+
* render in the header in this mode: pass a trail or [] to avoid the editable sample trail.
|
|
3095
|
+
* Omitted or object shells and omitted tabs preserve the existing default output.
|
|
3096
|
+
*/
|
|
3062
3097
|
function ResourceDetailPage(props) {
|
|
3063
3098
|
const { t } = useI18n();
|
|
3064
3099
|
const readOnly = props.readOnly ?? false;
|
|
3065
|
-
const { name = readOnly ? "" : detailResource.name, description = readOnly ? "" : detailResource.description, status = readOnly ? "" : detailResource.status, breadcrumbs = readOnly ? [] : detailBreadcrumbs, meta: metaProp, actions: actionsProp, details: detailsProp, overviewTitle = "Configuration", overviewDescription = readOnly ? "" : "Settings of this resource.", historyTitle = "Status history", events = readOnly ? [] : detailEvents, activity = readOnly ? [] : detailActivity, dangerActions = readOnly ? [] : detailDangerActions, defaultTab = "overview",
|
|
3100
|
+
const { name = readOnly ? "" : detailResource.name, description = readOnly ? "" : detailResource.description, status = readOnly ? "" : detailResource.status, breadcrumbs = readOnly ? [] : detailBreadcrumbs, meta: metaProp, actions: actionsProp, details: detailsProp, overviewTitle = "Configuration", overviewDescription = readOnly ? "" : "Settings of this resource.", historyTitle = "Status history", events = readOnly ? [] : detailEvents, activity = readOnly ? [] : detailActivity, dangerActions = readOnly ? [] : detailDangerActions, defaultTab = "overview", onEditDetails, onSaveSettings, onDangerAction, shell, labels } = props;
|
|
3066
3101
|
const meta = metaProp ?? (readOnly ? [] : detailMeta);
|
|
3067
3102
|
const actions = actionsProp ?? (readOnly ? [] : [{
|
|
3068
3103
|
label: "View logs",
|
|
@@ -3089,139 +3124,146 @@ function ResourceDetailPage(props) {
|
|
|
3089
3124
|
value,
|
|
3090
3125
|
label: labels?.[value] ?? t(`resourceDetail.${value}`)
|
|
3091
3126
|
}));
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
title: historyTitle,
|
|
3143
|
-
className: "lg:col-span-2",
|
|
3144
|
-
children: /* @__PURE__ */ jsx(StatusTimeline, {
|
|
3145
|
-
events: historyEvents,
|
|
3146
|
-
maxVisible: readOnly ? void 0 : 4
|
|
3147
|
-
})
|
|
3148
|
-
})]
|
|
3149
|
-
})
|
|
3150
|
-
}),
|
|
3151
|
-
!readOnly && /* @__PURE__ */ jsx(TabsPanel, {
|
|
3152
|
-
value: "activity",
|
|
3153
|
-
children: /* @__PURE__ */ jsx(Section, {
|
|
3127
|
+
const content = /* @__PURE__ */ jsx(Page, {
|
|
3128
|
+
width: "wide",
|
|
3129
|
+
header: /* @__PURE__ */ jsx(PageHeader, {
|
|
3130
|
+
as: shell === null ? "div" : void 0,
|
|
3131
|
+
breadcrumbs: shell === null ? breadcrumbs : null,
|
|
3132
|
+
title: name,
|
|
3133
|
+
description,
|
|
3134
|
+
status,
|
|
3135
|
+
meta,
|
|
3136
|
+
actions,
|
|
3137
|
+
tabs: null
|
|
3138
|
+
}),
|
|
3139
|
+
children: props.tabs !== void 0 ? /* @__PURE__ */ jsx(CustomTabs, {
|
|
3140
|
+
tabs: props.tabs,
|
|
3141
|
+
defaultTab: props.defaultTab,
|
|
3142
|
+
onTabChange: props.onTabChange,
|
|
3143
|
+
label: labels?.sections ?? t("resourceDetail.sections")
|
|
3144
|
+
}) : /* @__PURE__ */ jsxs(Tabs, {
|
|
3145
|
+
value: readOnly ? "overview" : tab,
|
|
3146
|
+
onValueChange: (v) => {
|
|
3147
|
+
const next = tabs.find((t) => t.value === v)?.value ?? "overview";
|
|
3148
|
+
setTab(next);
|
|
3149
|
+
if (props.tabs === void 0) props.onTabChange?.(next);
|
|
3150
|
+
},
|
|
3151
|
+
children: [
|
|
3152
|
+
/* @__PURE__ */ jsx(TabsList, {
|
|
3153
|
+
"aria-label": labels?.sections ?? t("resourceDetail.sections"),
|
|
3154
|
+
children: tabs.map((t) => /* @__PURE__ */ jsx(TabsTab, {
|
|
3155
|
+
value: t.value,
|
|
3156
|
+
children: t.label
|
|
3157
|
+
}, t.value))
|
|
3158
|
+
}),
|
|
3159
|
+
/* @__PURE__ */ jsx(TabsPanel, {
|
|
3160
|
+
value: "overview",
|
|
3161
|
+
children: /* @__PURE__ */ jsxs(Grid, {
|
|
3162
|
+
cols: historyEvents === void 0 ? 1 : {
|
|
3163
|
+
base: 1,
|
|
3164
|
+
lg: 5
|
|
3165
|
+
},
|
|
3166
|
+
gap: 6,
|
|
3167
|
+
align: "start",
|
|
3168
|
+
children: [/* @__PURE__ */ jsx(DescriptionListCard, {
|
|
3169
|
+
className: historyEvents === void 0 ? void 0 : "lg:col-span-3",
|
|
3170
|
+
titleAs: "h2",
|
|
3171
|
+
title: overviewTitle,
|
|
3172
|
+
description: overviewDescription,
|
|
3173
|
+
items: details,
|
|
3174
|
+
onEdit: onEditDetails
|
|
3175
|
+
}), historyEvents !== void 0 && /* @__PURE__ */ jsx(Section, {
|
|
3176
|
+
role: readOnly ? "group" : void 0,
|
|
3154
3177
|
variant: "card",
|
|
3155
3178
|
padding: "md",
|
|
3156
|
-
title:
|
|
3157
|
-
|
|
3158
|
-
children: /* @__PURE__ */ jsx(
|
|
3159
|
-
|
|
3160
|
-
|
|
3179
|
+
title: historyTitle,
|
|
3180
|
+
className: "lg:col-span-2",
|
|
3181
|
+
children: /* @__PURE__ */ jsx(StatusTimeline, {
|
|
3182
|
+
events: historyEvents,
|
|
3183
|
+
maxVisible: readOnly ? void 0 : 4
|
|
3161
3184
|
})
|
|
3185
|
+
})]
|
|
3186
|
+
})
|
|
3187
|
+
}),
|
|
3188
|
+
!readOnly && /* @__PURE__ */ jsx(TabsPanel, {
|
|
3189
|
+
value: "activity",
|
|
3190
|
+
children: /* @__PURE__ */ jsx(Section, {
|
|
3191
|
+
variant: "card",
|
|
3192
|
+
padding: "md",
|
|
3193
|
+
title: "Activity",
|
|
3194
|
+
description: "Changes made to this resource by people and automations.",
|
|
3195
|
+
children: /* @__PURE__ */ jsx(ActivityFeed, {
|
|
3196
|
+
items: activity,
|
|
3197
|
+
label: "Activity, newest first"
|
|
3162
3198
|
})
|
|
3163
|
-
})
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
...s,
|
|
3200
|
-
name: v
|
|
3201
|
-
}))
|
|
3202
|
-
}),
|
|
3203
|
-
/* @__PURE__ */ jsx(FieldDescription, { children: "Lowercase letters, numbers and dashes." })
|
|
3204
|
-
] }), /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Description" }), /* @__PURE__ */ jsx(Textarea, {
|
|
3205
|
-
rows: 3,
|
|
3206
|
-
value: settings.description,
|
|
3199
|
+
})
|
|
3200
|
+
}),
|
|
3201
|
+
!readOnly && /* @__PURE__ */ jsx(TabsPanel, {
|
|
3202
|
+
value: "settings",
|
|
3203
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
3204
|
+
gap: 8,
|
|
3205
|
+
children: [/* @__PURE__ */ jsx("form", {
|
|
3206
|
+
noValidate: true,
|
|
3207
|
+
onSubmit: (e) => {
|
|
3208
|
+
e.preventDefault();
|
|
3209
|
+
setSaved(settings);
|
|
3210
|
+
onSaveSettings?.(settings);
|
|
3211
|
+
},
|
|
3212
|
+
children: /* @__PURE__ */ jsx(FormSection, {
|
|
3213
|
+
title: "General",
|
|
3214
|
+
description: "Name and description shown across the console.",
|
|
3215
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Button, {
|
|
3216
|
+
variant: "ghost",
|
|
3217
|
+
disabled: !dirty,
|
|
3218
|
+
onClick: () => setSettings(saved),
|
|
3219
|
+
children: "Discard"
|
|
3220
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
3221
|
+
type: "submit",
|
|
3222
|
+
disabled: !dirty,
|
|
3223
|
+
children: "Save changes"
|
|
3224
|
+
})] }),
|
|
3225
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
3226
|
+
gap: 4,
|
|
3227
|
+
children: [/* @__PURE__ */ jsxs(Field, { children: [
|
|
3228
|
+
/* @__PURE__ */ jsx(FieldLabel, {
|
|
3229
|
+
required: true,
|
|
3230
|
+
children: "Name"
|
|
3231
|
+
}),
|
|
3232
|
+
/* @__PURE__ */ jsx(Input, {
|
|
3233
|
+
required: true,
|
|
3234
|
+
value: settings.name,
|
|
3207
3235
|
onValueChange: (v) => setSettings((s) => ({
|
|
3208
3236
|
...s,
|
|
3209
|
-
|
|
3237
|
+
name: v
|
|
3210
3238
|
}))
|
|
3211
|
-
})
|
|
3212
|
-
|
|
3239
|
+
}),
|
|
3240
|
+
/* @__PURE__ */ jsx(FieldDescription, { children: "Lowercase letters, numbers and dashes." })
|
|
3241
|
+
] }), /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Description" }), /* @__PURE__ */ jsx(Textarea, {
|
|
3242
|
+
rows: 3,
|
|
3243
|
+
value: settings.description,
|
|
3244
|
+
onValueChange: (v) => setSettings((s) => ({
|
|
3245
|
+
...s,
|
|
3246
|
+
description: v
|
|
3247
|
+
}))
|
|
3248
|
+
})] })]
|
|
3213
3249
|
})
|
|
3214
|
-
})
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
})
|
|
3250
|
+
})
|
|
3251
|
+
}), /* @__PURE__ */ jsx(DangerZone, {
|
|
3252
|
+
description: "These actions affect everyone who uses this resource.",
|
|
3253
|
+
actions: dangerActions,
|
|
3254
|
+
onConfirm: onDangerAction
|
|
3255
|
+
})]
|
|
3220
3256
|
})
|
|
3221
|
-
|
|
3222
|
-
|
|
3257
|
+
})
|
|
3258
|
+
]
|
|
3223
3259
|
})
|
|
3224
3260
|
});
|
|
3261
|
+
return shell === null ? content : /* @__PURE__ */ jsx(ConsoleShell, {
|
|
3262
|
+
currentHref: "/deployments",
|
|
3263
|
+
breadcrumbs,
|
|
3264
|
+
...shell,
|
|
3265
|
+
children: content
|
|
3266
|
+
});
|
|
3225
3267
|
}
|
|
3226
3268
|
//#endregion
|
|
3227
3269
|
//#region src/resource-detail/template.meta.ts
|
|
@@ -3230,7 +3272,7 @@ const meta$30 = {
|
|
|
3230
3272
|
family: "Resources",
|
|
3231
3273
|
priority: "P1",
|
|
3232
3274
|
status: "beta",
|
|
3233
|
-
description: "Resource detail with editable Overview, Activity and Settings tabs by default; optional readOnly (boolean, default false) uses only explicit header and detail props and one Overview tab, with optional history (readonly StatusEvent[], default undefined): omitted hides the history card, [] shows the named empty state, and events render exactly as supplied without invented actors. Read-only ignores activity, events, dangerActions, defaultTab, onSaveSettings and onDangerAction; explicit actions and onEditDetails are honored. The Resource sections tablist retains Tab, arrow, Home/End and Enter/Space keyboard navigation; history is a named group containing the Status history list or empty-state region. Uses token styling in dark (default), light and high_contrast. Examples: runtime-with-transition maps state and lastTransitionAt to one actor-free event, runtime-without-transition maps null to [], and realtime-configuration and postgres-table-detail omit history. Optional labels?: Partial<ResourceDetailLabels> overrides overview, activity, settings and sections (all strings). Unset keys use I18nProvider (en/es); no provider keeps English. Only the tabs and tablist are localized by this template; fixtures and other section text are unchanged. readOnly keeps only the localized overview tab. See the Catalog labels live preview. ConsoleShell retains sample frame defaults
|
|
3275
|
+
description: "Resource detail with editable Overview, Activity and Settings tabs by default; optional readOnly (boolean, default false) uses only explicit header and detail props and one Overview tab, with optional history (readonly StatusEvent[], default undefined): omitted hides the history card, [] shows the named empty state, and events render exactly as supplied without invented actors. Read-only ignores activity, events, dangerActions, defaultTab, onSaveSettings and onDangerAction; explicit actions and onEditDetails are honored. The Resource sections tablist retains Tab, arrow, Home/End and Enter/Space keyboard navigation; history is a named group containing the Status history list or empty-state region. Uses token styling in dark (default), light and high_contrast. Examples: runtime-with-transition maps state and lastTransitionAt to one actor-free event, runtime-without-transition maps null to [], and realtime-configuration and postgres-table-detail omit history. Optional labels?: Partial<ResourceDetailLabels> overrides overview, activity, settings and sections (all strings). Unset keys use I18nProvider (en/es); no provider keeps English. Only the tabs and tablist are localized by this template; fixtures and other section text are unchanged. readOnly keeps only the localized overview tab. See the Catalog labels live preview. ConsoleShell retains sample frame defaults when shell is omitted or an object. shell={null} renders only Page and PageHeader, with breadcrumbs in the header; pass breadcrumbs or [] to avoid the editable sample trail. The host owns main and provides ChartLocaleProvider for custom chart locales. Optional tabs?: { value: string; label: string; content: ReactNode }[] replaces the built-in tabs in caller order, even with readOnly; [] hides the tab set. With custom tabs, defaultTab and onTabChange use string values; an omitted or unknown defaultTab selects the first tab. Without tabs they retain ResourceDetailTab values. Custom tabs use the same Base UI keyboard navigation and panel mounting. See the embedded-custom-tabs live preview for shell-less composition inside a host main.",
|
|
3234
3276
|
layout: "SidebarLayout + Page",
|
|
3235
3277
|
blocks: [
|
|
3236
3278
|
"app-sidebar",
|