@the-portland-company/shell 0.87.1 → 0.89.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.cjs CHANGED
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('@chakra-ui/react');
4
+ var clsx = require('clsx');
4
5
  var jsxRuntime = require('react/jsx-runtime');
5
- var clsx2 = require('clsx');
6
6
  var reactRouterDom = require('react-router-dom');
7
7
  var react$1 = require('react');
8
8
  require('react-dom');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
- var clsx2__default = /*#__PURE__*/_interopDefault(clsx2);
12
+ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
13
13
 
14
14
  // src/theme/index.ts
15
15
 
@@ -768,6 +768,12 @@ var components = {
768
768
  };
769
769
 
770
770
  // src/theme/index.ts
771
+ var SHELL_FIELD_MARKER = "data-shell-field";
772
+ var nativeFieldSelector = (state) => {
773
+ const own = `:not([${SHELL_FIELD_MARKER}])`;
774
+ const input = `input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"])${own}${state}`;
775
+ return `${input}, textarea${own}${state}, select${own}${state}`;
776
+ };
771
777
  var config = {
772
778
  initialColorMode: "light",
773
779
  useSystemColorMode: false
@@ -791,13 +797,13 @@ var styles = {
791
797
  "--mode-input-focus-shadow-color": "var(--app-color-brand-500)"
792
798
  },
793
799
  // Ensure non-Chakra/native text-like inputs follow mode border colors as well.
794
- 'input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]), textarea, select': {
800
+ [nativeFieldSelector("")]: {
795
801
  borderColor: "var(--mode-input-border-color)"
796
802
  },
797
- 'input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):hover, textarea:hover, select:hover': {
803
+ [nativeFieldSelector(":hover")]: {
798
804
  borderColor: "var(--mode-input-hover-border-color)"
799
805
  },
800
- 'input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):focus, textarea:focus, select:focus': {
806
+ [nativeFieldSelector(":focus")]: {
801
807
  borderColor: "var(--mode-primary-color)",
802
808
  boxShadow: "0 0 0 1px var(--mode-input-focus-shadow-color)"
803
809
  }
@@ -833,29 +839,72 @@ var politogyTheme = react.extendTheme({
833
839
  full: "9999px"
834
840
  }
835
841
  });
842
+ var PADDING = {
843
+ none: "p-0",
844
+ sm: "p-4",
845
+ md: "p-6",
846
+ lg: "p-8"
847
+ };
836
848
  function Card({
837
849
  title,
850
+ subtitle,
851
+ aside,
852
+ actions,
853
+ footer,
838
854
  children,
855
+ padding = "md",
856
+ bodyClassName,
839
857
  minH,
840
858
  className,
841
859
  style,
842
860
  ...props
843
861
  }) {
862
+ const structured = Boolean(subtitle || aside || actions || footer || bodyClassName);
863
+ const surface = "rounded-lg border border-[color:var(--app-card-border,var(--color-border))] bg-[color:var(--app-card-bg,var(--color-panel))] text-[color:var(--app-card-fg,var(--color-text))] shadow-sm";
864
+ if (!structured) {
865
+ return /* @__PURE__ */ jsxRuntime.jsxs(
866
+ "div",
867
+ {
868
+ "data-shell-card": "",
869
+ className: clsx__default.default(surface, PADDING[padding], className),
870
+ style: { minHeight: minH, ...style },
871
+ ...props,
872
+ children: [
873
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-semibold", children: title }) : null,
874
+ children
875
+ ]
876
+ }
877
+ );
878
+ }
879
+ const hasHeader = Boolean(title || subtitle || aside || actions);
880
+ const divider = "border-[color:var(--app-card-border,var(--color-border))]";
844
881
  return /* @__PURE__ */ jsxRuntime.jsxs(
845
882
  "div",
846
883
  {
847
- className: `rounded-lg border border-slate-200 bg-white p-6 shadow-sm ${className || ""}`,
884
+ "data-shell-card": "",
885
+ "data-shell-card-structured": "",
886
+ className: clsx__default.default(surface, "overflow-hidden", className),
848
887
  style: { minHeight: minH, ...style },
849
888
  ...props,
850
889
  children: [
851
- title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-semibold", children: title }),
852
- children
890
+ hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx__default.default("flex flex-wrap items-start justify-between gap-3 border-b px-5 py-4", divider), children: [
891
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
892
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold", children: title }) : null,
893
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-sm text-[color:var(--app-card-fg-muted,var(--color-text-muted))]", children: subtitle }) : null
894
+ ] }),
895
+ aside || actions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
896
+ aside,
897
+ actions
898
+ ] }) : null
899
+ ] }) : null,
900
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: bodyClassName ?? PADDING[padding], children }),
901
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("border-t px-5 py-3", divider), children: footer }) : null
853
902
  ]
854
903
  }
855
904
  );
856
905
  }
857
906
  function FormColumn({ children, className }) {
858
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-shell-form-column": "", className: clsx2__default.default("w-full max-w-[960px]", className), children });
907
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-shell-form-column": "", className: clsx__default.default("w-full max-w-[960px]", className), children });
859
908
  }
860
909
  var MODE_EYEBROW_LABEL = {
861
910
  relationship: "Relationship mode",
@@ -868,7 +917,8 @@ var resolveMaxWidthClass = (maxW) => {
868
917
  if (maxW === "container.md") return "max-w-5xl";
869
918
  return "max-w-7xl";
870
919
  };
871
- function PageHeader({
920
+ function PageHeaderView({
921
+ renderCrumbLink,
872
922
  title,
873
923
  mode,
874
924
  eyebrow,
@@ -896,11 +946,11 @@ function PageHeader({
896
946
  "div",
897
947
  {
898
948
  style: { backgroundColor: "var(--app-tab-header-bg, #888888)" },
899
- className: clsx2__default.default("text-slate-100", tabBar ? "pt-3 pb-0" : "py-3 border-b border-gray-200", {
949
+ className: clsx__default.default("text-slate-100", tabBar ? "pt-3 pb-0" : "py-3 border-b border-gray-200", {
900
950
  "md:ml-60": !hideSidebar
901
951
  }),
902
952
  children: [
903
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx2__default.default("w-full px-4", maxWClass), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-nowrap items-start justify-between gap-4", children: [
953
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("w-full px-4", maxWClass), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-nowrap items-start justify-between gap-4", children: [
904
954
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
905
955
  eyebrowText ? /* @__PURE__ */ jsxRuntime.jsx(
906
956
  "div",
@@ -927,14 +977,14 @@ function PageHeader({
927
977
  "nav",
928
978
  {
929
979
  "aria-label": "Breadcrumb",
930
- className: clsx2__default.default("min-w-0 text-slate-100", title ? "mt-1" : ""),
980
+ className: clsx__default.default("min-w-0 text-slate-100", title ? "mt-1" : ""),
931
981
  children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex flex-nowrap items-center gap-2 overflow-hidden text-sm text-gray-600", children: breadcrumbsWithoutCurrent.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
932
982
  "li",
933
983
  {
934
984
  className: "flex min-w-0 flex-shrink-0 items-center gap-2",
935
985
  children: [
936
986
  index > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: ">" }) : null,
937
- item.href ? /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: item.href, className: "truncate text-slate-100 hover:underline", children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-slate-100", children: item.label })
987
+ item.href ? renderCrumbLink(item.href, item.label, "truncate text-slate-100 hover:underline") : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-slate-100", children: item.label })
938
988
  ]
939
989
  },
940
990
  `${item.label}-${index}`
@@ -949,6 +999,320 @@ function PageHeader({
949
999
  }
950
1000
  );
951
1001
  }
1002
+ function PageHeader(props) {
1003
+ return /* @__PURE__ */ jsxRuntime.jsx(
1004
+ PageHeaderView,
1005
+ {
1006
+ ...props,
1007
+ renderCrumbLink: (href, label, className) => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: href, className, children: label })
1008
+ }
1009
+ );
1010
+ }
1011
+ var VARIANT_CLASS = {
1012
+ primary: "border border-transparent bg-[color:var(--app-btn-primary-bg,var(--color-accent))] text-[color:var(--app-btn-primary-fg,var(--color-white))] hover:bg-[color:var(--app-btn-primary-bg-hover,var(--color-accent-hover))]",
1013
+ secondary: "border border-[color:var(--app-btn-secondary-border,var(--color-border))] bg-[color:var(--app-btn-secondary-bg,var(--color-white))] text-[color:var(--app-btn-secondary-fg,var(--color-text))] hover:bg-[color:var(--app-btn-secondary-bg-hover,var(--color-bg))]",
1014
+ ghost: "border border-transparent bg-transparent text-[color:var(--app-btn-secondary-fg,var(--color-text))] hover:bg-[color:var(--app-btn-secondary-bg-hover,var(--color-bg))]",
1015
+ danger: "border border-transparent bg-[color:var(--chrome-danger,var(--color-race-red))] text-[color:var(--color-white)] hover:bg-[color:var(--color-race-red-600)]"
1016
+ };
1017
+ var SIZE_CLASS = {
1018
+ md: "h-[44px]",
1019
+ sm: "h-[36px]"
1020
+ };
1021
+ var Button = react$1.forwardRef(function Button2({
1022
+ variant = "primary",
1023
+ size = "md",
1024
+ loading = false,
1025
+ disabled = false,
1026
+ href,
1027
+ as,
1028
+ type,
1029
+ className,
1030
+ children,
1031
+ onClick,
1032
+ ...props
1033
+ }, ref) {
1034
+ const Component = as ?? (href ? "a" : "button");
1035
+ const isNativeButton = Component === "button";
1036
+ const inactive = disabled || loading;
1037
+ const linkProps = isNativeButton ? { type: type ?? "button", disabled: inactive } : {
1038
+ href,
1039
+ "aria-disabled": inactive || void 0,
1040
+ tabIndex: inactive ? -1 : void 0
1041
+ };
1042
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1043
+ Component,
1044
+ {
1045
+ ref,
1046
+ "data-shell-button": "",
1047
+ "data-variant": variant,
1048
+ "aria-busy": loading || void 0,
1049
+ className: clsx__default.default(
1050
+ "inline-flex items-center justify-center gap-2 rounded-[5px] px-3 text-sm font-semibold no-underline transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--app-field-focus,var(--color-accent))] focus-visible:ring-offset-2",
1051
+ SIZE_CLASS[size],
1052
+ VARIANT_CLASS[variant],
1053
+ inactive && "cursor-not-allowed opacity-50",
1054
+ className
1055
+ ),
1056
+ onClick: inactive ? (event) => {
1057
+ event.preventDefault();
1058
+ event.stopPropagation();
1059
+ } : onClick,
1060
+ ...linkProps,
1061
+ ...props,
1062
+ children: [
1063
+ loading ? /* @__PURE__ */ jsxRuntime.jsx(
1064
+ "span",
1065
+ {
1066
+ "aria-hidden": "true",
1067
+ "data-shell-button-spinner": "",
1068
+ className: "inline-block h-4 w-4 animate-spin motion-reduce:animate-none rounded-full border-2 border-current border-t-transparent"
1069
+ }
1070
+ ) : null,
1071
+ children
1072
+ ]
1073
+ }
1074
+ );
1075
+ });
1076
+ var Button_default = Button;
1077
+ function FormField({
1078
+ id,
1079
+ label,
1080
+ helperText,
1081
+ error,
1082
+ required,
1083
+ className,
1084
+ children
1085
+ }) {
1086
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx__default.default("flex w-full flex-col gap-1", className), children: [
1087
+ label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: id, className: "text-sm font-semibold text-[color:var(--color-text)]", children: [
1088
+ label,
1089
+ required ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: " *" }) : null
1090
+ ] }) : null,
1091
+ children,
1092
+ error ? /* @__PURE__ */ jsxRuntime.jsx(
1093
+ "p",
1094
+ {
1095
+ id: `${id}-error`,
1096
+ role: "alert",
1097
+ className: "text-xs text-[color:var(--chrome-danger,var(--color-race-red))]",
1098
+ children: error
1099
+ }
1100
+ ) : helperText ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${id}-helper`, className: "text-xs text-[color:var(--color-text-muted)]", children: helperText }) : null
1101
+ ] });
1102
+ }
1103
+ function describedBy(id, helperText, error, extra) {
1104
+ const generated = error ? `${id}-error` : helperText ? `${id}-helper` : void 0;
1105
+ const merged = [generated, extra].filter(Boolean).join(" ");
1106
+ return merged || void 0;
1107
+ }
1108
+
1109
+ // src/components/fieldStyles.ts
1110
+ var FIELD_BASE = "w-full rounded-[5px] border bg-[color:var(--app-field-bg,var(--color-white))] px-3 text-sm text-[color:var(--color-text)] placeholder:text-[color:var(--color-text-muted)] focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-50";
1111
+ var FIELD_VALID = "border-[color:var(--app-field-border,var(--color-border))] hover:border-[color:var(--app-field-border-hover,var(--color-g4))] focus:border-[color:var(--app-field-focus,var(--color-accent))] focus:ring-[color:var(--app-field-focus,var(--color-accent))]";
1112
+ var FIELD_INVALID = "border-[color:var(--chrome-danger,var(--color-race-red))] focus:ring-[color:var(--chrome-danger,var(--color-race-red))]";
1113
+ var Input = react$1.forwardRef(function Input2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
1114
+ const autoId = react$1.useId();
1115
+ const fieldId = id ?? autoId;
1116
+ const isInvalid = Boolean(error) || Boolean(invalid);
1117
+ return /* @__PURE__ */ jsxRuntime.jsx(
1118
+ FormField,
1119
+ {
1120
+ id: fieldId,
1121
+ label,
1122
+ helperText,
1123
+ error,
1124
+ required,
1125
+ className: wrapperClassName,
1126
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1127
+ "input",
1128
+ {
1129
+ ref,
1130
+ id: fieldId,
1131
+ required,
1132
+ "data-shell-field": "",
1133
+ "aria-invalid": isInvalid || void 0,
1134
+ "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
1135
+ className: clsx__default.default(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
1136
+ ...props
1137
+ }
1138
+ )
1139
+ }
1140
+ );
1141
+ });
1142
+ var Input_default = Input;
1143
+ var Select = react$1.forwardRef(function Select2({ label, helperText, error, invalid, className, wrapperClassName, id, required, children, "aria-describedby": ariaDescribedBy, ...props }, ref) {
1144
+ const autoId = react$1.useId();
1145
+ const fieldId = id ?? autoId;
1146
+ const isInvalid = Boolean(error) || Boolean(invalid);
1147
+ return /* @__PURE__ */ jsxRuntime.jsx(
1148
+ FormField,
1149
+ {
1150
+ id: fieldId,
1151
+ label,
1152
+ helperText,
1153
+ error,
1154
+ required,
1155
+ className: wrapperClassName,
1156
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1157
+ "select",
1158
+ {
1159
+ ref,
1160
+ id: fieldId,
1161
+ required,
1162
+ "data-shell-field": "",
1163
+ "aria-invalid": isInvalid || void 0,
1164
+ "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
1165
+ className: clsx__default.default(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
1166
+ ...props,
1167
+ children
1168
+ }
1169
+ )
1170
+ }
1171
+ );
1172
+ });
1173
+ var Select_default = Select;
1174
+ var Textarea = react$1.forwardRef(function Textarea2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
1175
+ const autoId = react$1.useId();
1176
+ const fieldId = id ?? autoId;
1177
+ const isInvalid = Boolean(error) || Boolean(invalid);
1178
+ return /* @__PURE__ */ jsxRuntime.jsx(
1179
+ FormField,
1180
+ {
1181
+ id: fieldId,
1182
+ label,
1183
+ helperText,
1184
+ error,
1185
+ required,
1186
+ className: wrapperClassName,
1187
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1188
+ "textarea",
1189
+ {
1190
+ ref,
1191
+ id: fieldId,
1192
+ required,
1193
+ "data-shell-field": "",
1194
+ "aria-invalid": isInvalid || void 0,
1195
+ "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
1196
+ className: clsx__default.default(FIELD_BASE, "min-h-[88px] py-3", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
1197
+ ...props
1198
+ }
1199
+ )
1200
+ }
1201
+ );
1202
+ });
1203
+ var Textarea_default = Textarea;
1204
+ var Checkbox = react$1.forwardRef(function Checkbox2({
1205
+ label,
1206
+ description,
1207
+ indeterminate,
1208
+ invalid,
1209
+ className,
1210
+ wrapperClassName,
1211
+ id,
1212
+ disabled,
1213
+ "aria-describedby": ariaDescribedBy,
1214
+ ...props
1215
+ }, ref) {
1216
+ const autoId = react$1.useId();
1217
+ const fieldId = id ?? autoId;
1218
+ const descId = description ? `${fieldId}-description` : void 0;
1219
+ const inner = react$1.useRef(null);
1220
+ const setRef = react$1.useCallback(
1221
+ (node) => {
1222
+ inner.current = node;
1223
+ if (typeof ref === "function") ref(node);
1224
+ else if (ref) ref.current = node;
1225
+ },
1226
+ [ref]
1227
+ );
1228
+ react$1.useEffect(() => {
1229
+ if (inner.current) inner.current.indeterminate = Boolean(indeterminate);
1230
+ }, [indeterminate]);
1231
+ const describedBy2 = [descId, ariaDescribedBy].filter(Boolean).join(" ") || void 0;
1232
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1233
+ "label",
1234
+ {
1235
+ htmlFor: fieldId,
1236
+ "data-shell-checkbox": "",
1237
+ className: clsx__default.default(
1238
+ "flex min-h-[44px] items-start gap-3 py-[10px] text-sm text-[color:var(--app-card-fg,var(--color-text))]",
1239
+ disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
1240
+ wrapperClassName
1241
+ ),
1242
+ children: [
1243
+ /* @__PURE__ */ jsxRuntime.jsx(
1244
+ "input",
1245
+ {
1246
+ ...props,
1247
+ ref: setRef,
1248
+ id: fieldId,
1249
+ type: "checkbox",
1250
+ disabled,
1251
+ "data-shell-field": "",
1252
+ "aria-invalid": invalid || void 0,
1253
+ "aria-describedby": describedBy2,
1254
+ className: clsx__default.default(
1255
+ "mt-[2px] h-5 w-5 shrink-0 rounded-[5px] border focus:outline-none focus-visible:ring-2",
1256
+ "accent-[color:var(--color-accent-bg-safe,var(--color-accent))]",
1257
+ "focus-visible:ring-[color:var(--app-field-focus,var(--color-accent))]",
1258
+ invalid ? "border-[color:var(--chrome-danger,var(--color-race-red))] outline outline-2 outline-[color:var(--chrome-danger,var(--color-race-red))]" : "border-[color:var(--app-field-border,var(--color-border))]",
1259
+ disabled ? "cursor-not-allowed" : "cursor-pointer",
1260
+ className
1261
+ )
1262
+ }
1263
+ ),
1264
+ label || description ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
1265
+ label ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block font-medium", children: label }) : null,
1266
+ description ? /* @__PURE__ */ jsxRuntime.jsx(
1267
+ "span",
1268
+ {
1269
+ id: descId,
1270
+ className: "block text-xs text-[color:var(--app-card-fg-muted,var(--color-text-muted))]",
1271
+ children: description
1272
+ }
1273
+ ) : null
1274
+ ] }) : null
1275
+ ]
1276
+ }
1277
+ );
1278
+ });
1279
+ var Checkbox_default = Checkbox;
1280
+ var FileInput = react$1.forwardRef(function FileInput2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
1281
+ const autoId = react$1.useId();
1282
+ const fieldId = id ?? autoId;
1283
+ const isInvalid = Boolean(error) || Boolean(invalid);
1284
+ return /* @__PURE__ */ jsxRuntime.jsx(
1285
+ FormField,
1286
+ {
1287
+ id: fieldId,
1288
+ label,
1289
+ helperText,
1290
+ error,
1291
+ required,
1292
+ className: wrapperClassName,
1293
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1294
+ "input",
1295
+ {
1296
+ ...props,
1297
+ ref,
1298
+ id: fieldId,
1299
+ type: "file",
1300
+ required,
1301
+ "data-shell-field": "",
1302
+ "aria-invalid": isInvalid || void 0,
1303
+ "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
1304
+ className: clsx__default.default(
1305
+ FIELD_BASE,
1306
+ "h-[44px] cursor-pointer py-[5px] file:mr-3 file:h-[32px] file:cursor-pointer file:rounded-[5px] file:border file:border-[color:var(--app-btn-secondary-border,var(--color-border))] file:bg-[color:var(--app-btn-secondary-bg,var(--color-white))] file:px-3 file:text-sm file:font-medium file:text-[color:var(--app-btn-secondary-fg,var(--color-text))]",
1307
+ isInvalid ? FIELD_INVALID : FIELD_VALID,
1308
+ className
1309
+ )
1310
+ }
1311
+ )
1312
+ }
1313
+ );
1314
+ });
1315
+ var FileInput_default = FileInput;
952
1316
 
953
1317
  // src/lib/deprecation.ts
954
1318
  var warned = /* @__PURE__ */ new Set();
@@ -992,7 +1356,7 @@ function PageContainer({
992
1356
  children: /* @__PURE__ */ jsxRuntime.jsx(
993
1357
  "div",
994
1358
  {
995
- className: clsx2__default.default(
1359
+ className: clsx__default.default(
996
1360
  "mx-auto w-full",
997
1361
  maxWClass,
998
1362
  pxClass,
@@ -1006,7 +1370,8 @@ function PageContainer({
1006
1370
  }
1007
1371
  );
1008
1372
  }
1009
- function BreadcrumbBar({
1373
+ function BreadcrumbBarView({
1374
+ renderCrumbLink,
1010
1375
  breadcrumbs = [],
1011
1376
  actions = null,
1012
1377
  maxW = "full"
@@ -1024,16 +1389,25 @@ function BreadcrumbBar({
1024
1389
  {
1025
1390
  className: "ml-0 border-b border-gray-200 px-4 py-3 md:ml-60",
1026
1391
  style: { backgroundColor: "var(--app-tab-header-bg, #888888)" },
1027
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx2__default.default("mx-auto w-full px-0", maxWClass), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between", children: [
1392
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("mx-auto w-full px-0", maxWClass), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between", children: [
1028
1393
  breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex items-center gap-2 text-sm text-slate-100", children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center gap-2", children: [
1029
1394
  index > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: ">" }) : null,
1030
- item.href ? /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: item.href, className: "text-slate-100 hover:underline", children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-100", children: item.label })
1395
+ item.href ? renderCrumbLink(item.href, item.label, "text-slate-100 hover:underline") : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-100", children: item.label })
1031
1396
  ] }, index)) }) }),
1032
1397
  actions && /* @__PURE__ */ jsxRuntime.jsx("div", { children: actions })
1033
1398
  ] }) })
1034
1399
  }
1035
1400
  );
1036
1401
  }
1402
+ function BreadcrumbBar(props) {
1403
+ return /* @__PURE__ */ jsxRuntime.jsx(
1404
+ BreadcrumbBarView,
1405
+ {
1406
+ ...props,
1407
+ renderCrumbLink: (href, label, className) => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: href, className, children: label })
1408
+ }
1409
+ );
1410
+ }
1037
1411
 
1038
1412
  // src/notifications/adapter.ts
1039
1413
  function emptyNotificationsFeed() {
@@ -1182,7 +1556,7 @@ function HeaderTabBar({
1182
1556
  {
1183
1557
  role: "tablist",
1184
1558
  "aria-label": ariaLabel,
1185
- className: clsx2__default.default(
1559
+ className: clsx__default.default(
1186
1560
  // Header-wide tab strip: background + bottom border only (no outer box).
1187
1561
  // Left-aligned and fluid: the container spans the full content width,
1188
1562
  // the tabs keep their natural width packed from the left (Global-Rules
@@ -1206,7 +1580,7 @@ function HeaderTabBar({
1206
1580
  "aria-label": item.label,
1207
1581
  disabled: isDisabled,
1208
1582
  onClick: () => onChange(item.id),
1209
- className: clsx2__default.default(
1583
+ className: clsx__default.default(
1210
1584
  // `group/tbtip relative` powers the shared <TopBarTooltip>.
1211
1585
  // Natural width (no flex-1 stretch); 40px square hit area for the
1212
1586
  // icon-only tab so the strip stays tappable.
@@ -1768,12 +2142,17 @@ function SpeculationRulesScript({ items }) {
1768
2142
  exports.BrandIcon = BrandIcon;
1769
2143
  exports.BrandLogo = BrandLogo;
1770
2144
  exports.BreadcrumbBar = BreadcrumbBar;
2145
+ exports.Button = Button_default;
1771
2146
  exports.Card = Card;
2147
+ exports.Checkbox = Checkbox_default;
2148
+ exports.FileInput = FileInput_default;
1772
2149
  exports.FormColumn = FormColumn;
1773
2150
  exports.GlobalUiIdProvider = GlobalUiIdProvider;
1774
2151
  exports.HeaderTabBar = HeaderTabBar;
2152
+ exports.Input = Input_default;
1775
2153
  exports.PageContainer = PageContainer;
1776
2154
  exports.PageHeader = PageHeader;
2155
+ exports.Select = Select_default;
1777
2156
  exports.ShellChromeContext = ShellChromeContext;
1778
2157
  exports.ShellFooterContext = ShellFooterContext;
1779
2158
  exports.ShellLinkedAccountsContext = ShellLinkedAccountsContext;
@@ -1785,6 +2164,7 @@ exports.ShellProvider = ShellProvider;
1785
2164
  exports.ShellRoleContext = ShellRoleContext;
1786
2165
  exports.ShellSupportProviderContext = ShellSupportProviderContext;
1787
2166
  exports.SpeculationRulesScript = SpeculationRulesScript;
2167
+ exports.Textarea = Textarea_default;
1788
2168
  exports.buildNavSpeculationRules = buildNavSpeculationRules;
1789
2169
  exports.buildSpeculationRules = buildSpeculationRules;
1790
2170
  exports.collectSiblingAppUrls = collectSiblingAppUrls;