@the-portland-company/shell 0.90.0 → 0.92.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.
@@ -1,76 +1,33 @@
1
1
  import { readThemeCookie, THEME_STORAGE_KEY, isThemePreference, applyThemePreference, readPendingThemeChoice, writeThemeCookie, clearPendingThemeChoice, markThemeChoicePending } from './chunk-BHRVZPZ7.js';
2
- import clsx from 'clsx';
3
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
- import { forwardRef, useId, useRef, useCallback, useEffect, createContext, useState, useContext, useMemo, useSyncExternalStore } from 'react';
3
+ import clsx2 from 'clsx';
4
+ import { createContext, useState, useEffect, useRef, useContext, useMemo, useCallback, useSyncExternalStore } from 'react';
5
5
  import { FiUser, FiSettings, FiMessageSquare, FiMail, FiInfo, FiSun, FiMoon, FiHelpCircle, FiLifeBuoy, FiAlertCircle, FiAlertTriangle, FiBell, FiGrid, FiZap, FiBatteryCharging, FiBattery } from 'react-icons/fi';
6
6
  import { createPortal } from 'react-dom';
7
7
 
8
- var PADDING = {
9
- none: "p-0",
10
- sm: "p-4",
11
- md: "p-6",
12
- lg: "p-8"
13
- };
14
8
  function Card({
15
9
  title,
16
- subtitle,
17
- aside,
18
- actions,
19
- footer,
20
10
  children,
21
- padding = "md",
22
- bodyClassName,
23
11
  minH,
24
12
  className,
25
13
  style,
26
14
  ...props
27
15
  }) {
28
- const structured = Boolean(subtitle || aside || actions || footer || bodyClassName);
29
- 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";
30
- if (!structured) {
31
- return /* @__PURE__ */ jsxs(
32
- "div",
33
- {
34
- "data-shell-card": "",
35
- className: clsx(surface, PADDING[padding], className),
36
- style: { minHeight: minH, ...style },
37
- ...props,
38
- children: [
39
- title ? /* @__PURE__ */ jsx("h3", { className: "mb-4 text-lg font-semibold", children: title }) : null,
40
- children
41
- ]
42
- }
43
- );
44
- }
45
- const hasHeader = Boolean(title || subtitle || aside || actions);
46
- const divider = "border-[color:var(--app-card-border,var(--color-border))]";
47
16
  return /* @__PURE__ */ jsxs(
48
17
  "div",
49
18
  {
50
- "data-shell-card": "",
51
- "data-shell-card-structured": "",
52
- className: clsx(surface, "overflow-hidden", className),
19
+ className: `rounded-lg border border-slate-200 bg-white p-6 shadow-sm ${className || ""}`,
53
20
  style: { minHeight: minH, ...style },
54
21
  ...props,
55
22
  children: [
56
- hasHeader ? /* @__PURE__ */ jsxs("div", { className: clsx("flex flex-wrap items-start justify-between gap-3 border-b px-5 py-4", divider), children: [
57
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
58
- title ? /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold", children: title }) : null,
59
- subtitle ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-[color:var(--app-card-fg-muted,var(--color-text-muted))]", children: subtitle }) : null
60
- ] }),
61
- aside || actions ? /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
62
- aside,
63
- actions
64
- ] }) : null
65
- ] }) : null,
66
- /* @__PURE__ */ jsx("div", { className: bodyClassName ?? PADDING[padding], children }),
67
- footer ? /* @__PURE__ */ jsx("div", { className: clsx("border-t px-5 py-3", divider), children: footer }) : null
23
+ title && /* @__PURE__ */ jsx("h3", { className: "mb-4 text-lg font-semibold", children: title }),
24
+ children
68
25
  ]
69
26
  }
70
27
  );
71
28
  }
72
29
  function FormColumn({ children, className }) {
73
- return /* @__PURE__ */ jsx("div", { "data-shell-form-column": "", className: clsx("w-full max-w-[960px]", className), children });
30
+ return /* @__PURE__ */ jsx("div", { "data-shell-form-column": "", className: clsx2("w-full max-w-[960px]", className), children });
74
31
  }
75
32
 
76
33
  // src/lib/deprecation.ts
@@ -87,311 +44,6 @@ function warnDeprecated(key, message) {
87
44
  warned.add(key);
88
45
  console.warn(`[@the-portland-company/shell] ${message}`);
89
46
  }
90
- var VARIANT_CLASS = {
91
- 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))]",
92
- 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))]",
93
- 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))]",
94
- 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)]"
95
- };
96
- var SIZE_CLASS = {
97
- md: "h-[44px]",
98
- sm: "h-[36px]"
99
- };
100
- var Button = forwardRef(function Button2({
101
- variant = "primary",
102
- size = "md",
103
- loading = false,
104
- disabled = false,
105
- href,
106
- as,
107
- type,
108
- className,
109
- children,
110
- onClick,
111
- ...props
112
- }, ref) {
113
- const Component = as ?? (href ? "a" : "button");
114
- const isNativeButton = Component === "button";
115
- const inactive = disabled || loading;
116
- const linkProps = isNativeButton ? { type: type ?? "button", disabled: inactive } : {
117
- href,
118
- "aria-disabled": inactive || void 0,
119
- tabIndex: inactive ? -1 : void 0
120
- };
121
- return /* @__PURE__ */ jsxs(
122
- Component,
123
- {
124
- ref,
125
- "data-shell-button": "",
126
- "data-variant": variant,
127
- "aria-busy": loading || void 0,
128
- className: clsx(
129
- "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",
130
- SIZE_CLASS[size],
131
- VARIANT_CLASS[variant],
132
- inactive && "cursor-not-allowed opacity-50",
133
- className
134
- ),
135
- onClick: inactive ? (event) => {
136
- event.preventDefault();
137
- event.stopPropagation();
138
- } : onClick,
139
- ...linkProps,
140
- ...props,
141
- children: [
142
- loading ? /* @__PURE__ */ jsx(
143
- "span",
144
- {
145
- "aria-hidden": "true",
146
- "data-shell-button-spinner": "",
147
- className: "inline-block h-4 w-4 animate-spin motion-reduce:animate-none rounded-full border-2 border-current border-t-transparent"
148
- }
149
- ) : null,
150
- children
151
- ]
152
- }
153
- );
154
- });
155
- var Button_default = Button;
156
- function FormField({
157
- id,
158
- label,
159
- helperText,
160
- error,
161
- required,
162
- className,
163
- children
164
- }) {
165
- return /* @__PURE__ */ jsxs("div", { className: clsx("flex w-full flex-col gap-1", className), children: [
166
- label ? /* @__PURE__ */ jsxs("label", { htmlFor: id, className: "text-sm font-semibold text-[color:var(--color-text)]", children: [
167
- label,
168
- required ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " *" }) : null
169
- ] }) : null,
170
- children,
171
- error ? /* @__PURE__ */ jsx(
172
- "p",
173
- {
174
- id: `${id}-error`,
175
- role: "alert",
176
- className: "text-xs text-[color:var(--chrome-danger,var(--color-race-red))]",
177
- children: error
178
- }
179
- ) : helperText ? /* @__PURE__ */ jsx("p", { id: `${id}-helper`, className: "text-xs text-[color:var(--color-text-muted)]", children: helperText }) : null
180
- ] });
181
- }
182
- function describedBy(id, helperText, error, extra) {
183
- const generated = error ? `${id}-error` : helperText ? `${id}-helper` : void 0;
184
- const merged = [generated, extra].filter(Boolean).join(" ");
185
- return merged || void 0;
186
- }
187
-
188
- // src/components/fieldStyles.ts
189
- 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";
190
- 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))]";
191
- var FIELD_INVALID = "border-[color:var(--chrome-danger,var(--color-race-red))] focus:ring-[color:var(--chrome-danger,var(--color-race-red))]";
192
- var Input = forwardRef(function Input2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
193
- const autoId = useId();
194
- const fieldId = id ?? autoId;
195
- const isInvalid = Boolean(error) || Boolean(invalid);
196
- return /* @__PURE__ */ jsx(
197
- FormField,
198
- {
199
- id: fieldId,
200
- label,
201
- helperText,
202
- error,
203
- required,
204
- className: wrapperClassName,
205
- children: /* @__PURE__ */ jsx(
206
- "input",
207
- {
208
- ref,
209
- id: fieldId,
210
- required,
211
- "data-shell-field": "",
212
- "aria-invalid": isInvalid || void 0,
213
- "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
214
- className: clsx(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
215
- ...props
216
- }
217
- )
218
- }
219
- );
220
- });
221
- var Input_default = Input;
222
- var Select = forwardRef(function Select2({ label, helperText, error, invalid, className, wrapperClassName, id, required, children, "aria-describedby": ariaDescribedBy, ...props }, ref) {
223
- const autoId = useId();
224
- const fieldId = id ?? autoId;
225
- const isInvalid = Boolean(error) || Boolean(invalid);
226
- return /* @__PURE__ */ jsx(
227
- FormField,
228
- {
229
- id: fieldId,
230
- label,
231
- helperText,
232
- error,
233
- required,
234
- className: wrapperClassName,
235
- children: /* @__PURE__ */ jsx(
236
- "select",
237
- {
238
- ref,
239
- id: fieldId,
240
- required,
241
- "data-shell-field": "",
242
- "aria-invalid": isInvalid || void 0,
243
- "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
244
- className: clsx(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
245
- ...props,
246
- children
247
- }
248
- )
249
- }
250
- );
251
- });
252
- var Select_default = Select;
253
- var Textarea = forwardRef(function Textarea2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
254
- const autoId = useId();
255
- const fieldId = id ?? autoId;
256
- const isInvalid = Boolean(error) || Boolean(invalid);
257
- return /* @__PURE__ */ jsx(
258
- FormField,
259
- {
260
- id: fieldId,
261
- label,
262
- helperText,
263
- error,
264
- required,
265
- className: wrapperClassName,
266
- children: /* @__PURE__ */ jsx(
267
- "textarea",
268
- {
269
- ref,
270
- id: fieldId,
271
- required,
272
- "data-shell-field": "",
273
- "aria-invalid": isInvalid || void 0,
274
- "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
275
- className: clsx(FIELD_BASE, "min-h-[88px] py-3", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
276
- ...props
277
- }
278
- )
279
- }
280
- );
281
- });
282
- var Textarea_default = Textarea;
283
- var Checkbox = forwardRef(function Checkbox2({
284
- label,
285
- description,
286
- indeterminate,
287
- invalid,
288
- className,
289
- wrapperClassName,
290
- id,
291
- disabled,
292
- "aria-describedby": ariaDescribedBy,
293
- ...props
294
- }, ref) {
295
- const autoId = useId();
296
- const fieldId = id ?? autoId;
297
- const descId = description ? `${fieldId}-description` : void 0;
298
- const inner = useRef(null);
299
- const setRef = useCallback(
300
- (node) => {
301
- inner.current = node;
302
- if (typeof ref === "function") ref(node);
303
- else if (ref) ref.current = node;
304
- },
305
- [ref]
306
- );
307
- useEffect(() => {
308
- if (inner.current) inner.current.indeterminate = Boolean(indeterminate);
309
- }, [indeterminate]);
310
- const describedBy2 = [descId, ariaDescribedBy].filter(Boolean).join(" ") || void 0;
311
- return /* @__PURE__ */ jsxs(
312
- "label",
313
- {
314
- htmlFor: fieldId,
315
- "data-shell-checkbox": "",
316
- className: clsx(
317
- "flex min-h-[44px] items-start gap-3 py-[10px] text-sm text-[color:var(--app-card-fg,var(--color-text))]",
318
- disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
319
- wrapperClassName
320
- ),
321
- children: [
322
- /* @__PURE__ */ jsx(
323
- "input",
324
- {
325
- ...props,
326
- ref: setRef,
327
- id: fieldId,
328
- type: "checkbox",
329
- disabled,
330
- "data-shell-field": "",
331
- "aria-invalid": invalid || void 0,
332
- "aria-describedby": describedBy2,
333
- className: clsx(
334
- "mt-[2px] h-5 w-5 shrink-0 rounded-[5px] border focus:outline-none focus-visible:ring-2",
335
- "accent-[color:var(--color-accent-bg-safe,var(--color-accent))]",
336
- "focus-visible:ring-[color:var(--app-field-focus,var(--color-accent))]",
337
- 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))]",
338
- disabled ? "cursor-not-allowed" : "cursor-pointer",
339
- className
340
- )
341
- }
342
- ),
343
- label || description ? /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
344
- label ? /* @__PURE__ */ jsx("span", { className: "block font-medium", children: label }) : null,
345
- description ? /* @__PURE__ */ jsx(
346
- "span",
347
- {
348
- id: descId,
349
- className: "block text-xs text-[color:var(--app-card-fg-muted,var(--color-text-muted))]",
350
- children: description
351
- }
352
- ) : null
353
- ] }) : null
354
- ]
355
- }
356
- );
357
- });
358
- var Checkbox_default = Checkbox;
359
- var FileInput = forwardRef(function FileInput2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
360
- const autoId = useId();
361
- const fieldId = id ?? autoId;
362
- const isInvalid = Boolean(error) || Boolean(invalid);
363
- return /* @__PURE__ */ jsx(
364
- FormField,
365
- {
366
- id: fieldId,
367
- label,
368
- helperText,
369
- error,
370
- required,
371
- className: wrapperClassName,
372
- children: /* @__PURE__ */ jsx(
373
- "input",
374
- {
375
- ...props,
376
- ref,
377
- id: fieldId,
378
- type: "file",
379
- required,
380
- "data-shell-field": "",
381
- "aria-invalid": isInvalid || void 0,
382
- "aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
383
- className: clsx(
384
- FIELD_BASE,
385
- "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))]",
386
- isInvalid ? FIELD_INVALID : FIELD_VALID,
387
- className
388
- )
389
- }
390
- )
391
- }
392
- );
393
- });
394
- var FileInput_default = FileInput;
395
47
  function useTopBarIconSlotGlyph(slot) {
396
48
  const [name, setName] = useState(null);
397
49
  useEffect(() => {
@@ -2337,7 +1989,7 @@ function HeaderTabBar({
2337
1989
  {
2338
1990
  role: "tablist",
2339
1991
  "aria-label": ariaLabel,
2340
- className: clsx(
1992
+ className: clsx2(
2341
1993
  // Header-wide tab strip: background + bottom border only (no outer box).
2342
1994
  // Left-aligned and fluid: the container spans the full content width,
2343
1995
  // the tabs keep their natural width packed from the left (Global-Rules
@@ -2361,7 +2013,7 @@ function HeaderTabBar({
2361
2013
  "aria-label": item.label,
2362
2014
  disabled: isDisabled,
2363
2015
  onClick: () => onChange(item.id),
2364
- className: clsx(
2016
+ className: clsx2(
2365
2017
  // `group/tbtip relative` powers the shared <TopBarTooltip>.
2366
2018
  // Natural width (no flex-1 stretch); 40px square hit area for the
2367
2019
  // icon-only tab so the strip stays tappable.
@@ -2529,7 +2181,7 @@ function PageHeaderView({
2529
2181
  "div",
2530
2182
  {
2531
2183
  "data-shell-page-header": "",
2532
- className: clsx("pt-[22px] text-[color:var(--color-text,#2F3136)]", tabBar ? "pb-0" : "pb-4", {
2184
+ className: clsx2("pt-[22px] text-[color:var(--color-text,#2F3136)]", tabBar ? "pb-0" : "pb-4", {
2533
2185
  "md:ml-60": !hideSidebar
2534
2186
  }),
2535
2187
  children: [
@@ -2584,7 +2236,7 @@ function BreadcrumbBarView({
2584
2236
  {
2585
2237
  className: "ml-0 border-b border-gray-200 px-4 py-3 md:ml-60",
2586
2238
  style: { backgroundColor: "var(--app-tab-header-bg, #888888)" },
2587
- children: /* @__PURE__ */ jsx("div", { className: clsx("mx-auto w-full px-0", maxWClass), children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-between", children: [
2239
+ children: /* @__PURE__ */ jsx("div", { className: clsx2("mx-auto w-full px-0", maxWClass), children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-between", children: [
2588
2240
  breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-2 text-sm text-slate-100", children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2", children: [
2589
2241
  index > 0 ? /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: ">" }) : null,
2590
2242
  item.href ? renderCrumbLink(item.href, item.label, "text-slate-100 hover:underline") : /* @__PURE__ */ jsx("span", { className: "text-slate-100", children: item.label })
@@ -2595,6 +2247,6 @@ function BreadcrumbBarView({
2595
2247
  );
2596
2248
  }
2597
2249
 
2598
- export { BreadcrumbBarView, Button_default, CORE_APP_ORIGIN, CORE_BILLING_PATH, CREDIT_TYPE_LABELS, CREDIT_TYPE_ORDER, Card, Checkbox_default, CreditsAction, FileInput_default, FormColumn, FuelAction, HeaderTabBar, Input_default, NAV_DISPLAY_OPTIONS, NavChromeProvider, NavDisplayAction, NavThemeControl, NotificationsAction, PageHeaderView, SPECS_ORIGIN, Select_default, SpecOverlayAction, SpeculationRulesScript, SupportAction, TOPBAR_GLYPH_SIZE, Textarea_default, TopBarCountBadge, TopBarPanelArrow, TopBarPopover, TopBarTooltip, TopBarWidgetSlot, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, createCommsNotificationsAdapter, creditGaugeRatio, creditStateWord, creditTooltipLine, creditsAriaLabel, creditsIconState, emptyNotificationsFeed, normalizeNotificationsFeed, resolveBrandGlyph, resolveOrgLogoUrl, topBarIconButtonClass, useChromeMe, useChromeOrgs, useNavChromeDedupedFetch, useNavChromeFetcher, useThemePreference, useTopBarIconSlotGlyph, warnDeprecated };
2599
- //# sourceMappingURL=chunk-VBDI7UZS.js.map
2600
- //# sourceMappingURL=chunk-VBDI7UZS.js.map
2250
+ export { BreadcrumbBarView, CORE_APP_ORIGIN, CORE_BILLING_PATH, CREDIT_TYPE_LABELS, CREDIT_TYPE_ORDER, Card, CreditsAction, FormColumn, FuelAction, HeaderTabBar, NAV_DISPLAY_OPTIONS, NavChromeProvider, NavDisplayAction, NavThemeControl, NotificationsAction, PageHeaderView, SPECS_ORIGIN, SpecOverlayAction, SpeculationRulesScript, SupportAction, TOPBAR_GLYPH_SIZE, TopBarCountBadge, TopBarPanelArrow, TopBarPopover, TopBarTooltip, TopBarWidgetSlot, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, createCommsNotificationsAdapter, creditGaugeRatio, creditStateWord, creditTooltipLine, creditsAriaLabel, creditsIconState, emptyNotificationsFeed, normalizeNotificationsFeed, resolveBrandGlyph, resolveOrgLogoUrl, topBarIconButtonClass, useChromeMe, useChromeOrgs, useNavChromeDedupedFetch, useNavChromeFetcher, useThemePreference, useTopBarIconSlotGlyph, warnDeprecated };
2251
+ //# sourceMappingURL=chunk-ZS7MQXDQ.js.map
2252
+ //# sourceMappingURL=chunk-ZS7MQXDQ.js.map