@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/CHANGELOG.md +22 -0
- package/README.md +51 -0
- package/bin/shell-version-check.mjs +117 -0
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +1 -1
- package/dist/app-chrome.d.ts +1 -1
- package/dist/app-chrome.js +3 -3
- package/dist/chrome.css +20 -0
- package/dist/{chunk-PRZP2SB6.js → chunk-J23MTK56.js} +562 -5
- package/dist/chunk-J23MTK56.js.map +1 -0
- package/dist/{chunk-3JOLELB4.js → chunk-SJDFAK5R.js} +23 -5
- package/dist/chunk-SJDFAK5R.js.map +1 -0
- package/dist/{index-bfbWLC7_.d.cts → index-CZylXAP4.d.cts} +278 -2
- package/dist/{index-C31E7M9l.d.ts → index-DwkSyAip.d.ts} +278 -2
- package/dist/index.cjs +400 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -79
- package/dist/index.d.ts +6 -79
- package/dist/index.js +21 -204
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +589 -4
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +1 -1
- package/dist/native.d.ts +1 -1
- package/dist/native.js +2 -2
- package/eslint/index.cjs +172 -0
- package/eslint/index.d.ts +6 -0
- package/eslint/index.mjs +5 -0
- package/package.json +17 -2
- package/dist/chunk-3JOLELB4.js.map +0 -1
- package/dist/chunk-PRZP2SB6.js.map +0 -1
package/dist/app-chrome.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { v as StandardNavIconKey, w as NavIcon, N as NavItem, x as NavBreadcrumb, y as StandardNavMode, z as NavLinkComponent, A as NavChromeFetcher, D as NavMode, E as NavUserMenu, G as NavOrgOption, o as NotificationsAdapter, J as NavFooterLink, K as NavFooter, L as NavDisplayMode } from './index-CZylXAP4.cjs';
|
|
4
4
|
import './theme-preference.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/app-chrome.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { v as StandardNavIconKey, w as NavIcon, N as NavItem, x as NavBreadcrumb, y as StandardNavMode, z as NavLinkComponent, A as NavChromeFetcher, D as NavMode, E as NavUserMenu, G as NavOrgOption, o as NotificationsAdapter, J as NavFooterLink, K as NavFooter, L as NavDisplayMode } from './index-DwkSyAip.js';
|
|
4
4
|
import './theme-preference.js';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/app-chrome.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { broadcastLogout, watchLogout } from './chunk-LL6LSJAH.js';
|
|
3
3
|
import { writeUrlState } from './chunk-GVQKZI5X.js';
|
|
4
|
-
import { clearBetaBannerDismissal, standardPolitogyNav, standardNavIcons, isNavItemActive, NavAppShell } from './chunk-
|
|
5
|
-
export { standardNavIcons } from './chunk-
|
|
6
|
-
import { warnDeprecated, NavChromeProvider, TopBarWidgetSlot, FuelAction, SpecOverlayAction, NotificationsAction, SupportAction, useChromeMe, useNavChromeDedupedFetch, useChromeOrgs, useNavChromeFetcher } from './chunk-
|
|
4
|
+
import { clearBetaBannerDismissal, standardPolitogyNav, standardNavIcons, isNavItemActive, NavAppShell } from './chunk-SJDFAK5R.js';
|
|
5
|
+
export { standardNavIcons } from './chunk-SJDFAK5R.js';
|
|
6
|
+
import { warnDeprecated, NavChromeProvider, TopBarWidgetSlot, FuelAction, SpecOverlayAction, NotificationsAction, SupportAction, useChromeMe, useNavChromeDedupedFetch, useChromeOrgs, useNavChromeFetcher } from './chunk-J23MTK56.js';
|
|
7
7
|
import './chunk-BHRVZPZ7.js';
|
|
8
8
|
import { NAV_DISPLAY_DEFAULT, resolveNavDisplay, writeNavDisplayLocal, writeNavDisplayCookie, isNavDisplayPreference, NAV_DISPLAY_STORAGE_KEY, readNavDisplayCookie } from './chunk-7YVJ7HQG.js';
|
|
9
9
|
import { authBaseUrl, orgIdTail, settingsBaseUrl, ORG_ID_QUERY_PARAM, readOrgSelectorFromUrl, matchOrgSelector, syncOrgIdInUrl, isOrgId, switchActiveOrg, ACTIVE_ORG_QUERY_PARAM, writeActiveOrgCookie, resolveActiveOrg, readActiveOrgCookie } from './chunk-5LO5W7W5.js';
|
package/dist/chrome.css
CHANGED
|
@@ -599,3 +599,23 @@
|
|
|
599
599
|
box-shadow: none !important;
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
+
|
|
603
|
+
/* ---- Card + Checkbox surface tokens (shell 0.89.0) ---------------------
|
|
604
|
+
* `Card` and `Checkbox` read these so they follow the theme. Light values are
|
|
605
|
+
* the Brand "Card" white, G3 border, graphite text; the muted text is #5C6B80
|
|
606
|
+
* (5.9:1 on white) rather than --color-g4, which is 3.0:1 on white and fails AA.
|
|
607
|
+
* Dark values are the neutral-black ramp (theme/colors.ts `neutral`): surface
|
|
608
|
+
* #161616, border #333333, text #E8E8E8, muted #A3A3A3 (6.9:1 on the surface).
|
|
609
|
+
* `applyThemePreference` puts `.dark` on <html>. The Brand stylesheet's `.dark {}` may override any of them. */
|
|
610
|
+
:root {
|
|
611
|
+
--app-card-bg: #FFFFFF;
|
|
612
|
+
--app-card-border: #D7DADF;
|
|
613
|
+
--app-card-fg: #2F3136;
|
|
614
|
+
--app-card-fg-muted: #5C6B80;
|
|
615
|
+
}
|
|
616
|
+
.dark {
|
|
617
|
+
--app-card-bg: #161616;
|
|
618
|
+
--app-card-border: #333333;
|
|
619
|
+
--app-card-fg: #E8E8E8;
|
|
620
|
+
--app-card-fg-muted: #A3A3A3;
|
|
621
|
+
}
|
|
@@ -1,13 +1,382 @@
|
|
|
1
1
|
import { readThemeCookie, THEME_STORAGE_KEY, isThemePreference, applyThemePreference, readPendingThemeChoice, writeThemeCookie, clearPendingThemeChoice, markThemeChoicePending } from './chunk-BHRVZPZ7.js';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { forwardRef, useId, useRef, useCallback, useEffect, createContext, useState, useContext, useMemo, 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
|
+
function Card({
|
|
15
|
+
title,
|
|
16
|
+
subtitle,
|
|
17
|
+
aside,
|
|
18
|
+
actions,
|
|
19
|
+
footer,
|
|
20
|
+
children,
|
|
21
|
+
padding = "md",
|
|
22
|
+
bodyClassName,
|
|
23
|
+
minH,
|
|
24
|
+
className,
|
|
25
|
+
style,
|
|
26
|
+
...props
|
|
27
|
+
}) {
|
|
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
|
+
return /* @__PURE__ */ jsxs(
|
|
48
|
+
"div",
|
|
49
|
+
{
|
|
50
|
+
"data-shell-card": "",
|
|
51
|
+
"data-shell-card-structured": "",
|
|
52
|
+
className: clsx(surface, "overflow-hidden", className),
|
|
53
|
+
style: { minHeight: minH, ...style },
|
|
54
|
+
...props,
|
|
55
|
+
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
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
8
72
|
function FormColumn({ children, className }) {
|
|
9
73
|
return /* @__PURE__ */ jsx("div", { "data-shell-form-column": "", className: clsx("w-full max-w-[960px]", className), children });
|
|
10
74
|
}
|
|
75
|
+
var VARIANT_CLASS = {
|
|
76
|
+
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))]",
|
|
77
|
+
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))]",
|
|
78
|
+
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))]",
|
|
79
|
+
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)]"
|
|
80
|
+
};
|
|
81
|
+
var SIZE_CLASS = {
|
|
82
|
+
md: "h-[44px]",
|
|
83
|
+
sm: "h-[36px]"
|
|
84
|
+
};
|
|
85
|
+
var Button = forwardRef(function Button2({
|
|
86
|
+
variant = "primary",
|
|
87
|
+
size = "md",
|
|
88
|
+
loading = false,
|
|
89
|
+
disabled = false,
|
|
90
|
+
href,
|
|
91
|
+
as,
|
|
92
|
+
type,
|
|
93
|
+
className,
|
|
94
|
+
children,
|
|
95
|
+
onClick,
|
|
96
|
+
...props
|
|
97
|
+
}, ref) {
|
|
98
|
+
const Component = as ?? (href ? "a" : "button");
|
|
99
|
+
const isNativeButton = Component === "button";
|
|
100
|
+
const inactive = disabled || loading;
|
|
101
|
+
const linkProps = isNativeButton ? { type: type ?? "button", disabled: inactive } : {
|
|
102
|
+
href,
|
|
103
|
+
"aria-disabled": inactive || void 0,
|
|
104
|
+
tabIndex: inactive ? -1 : void 0
|
|
105
|
+
};
|
|
106
|
+
return /* @__PURE__ */ jsxs(
|
|
107
|
+
Component,
|
|
108
|
+
{
|
|
109
|
+
ref,
|
|
110
|
+
"data-shell-button": "",
|
|
111
|
+
"data-variant": variant,
|
|
112
|
+
"aria-busy": loading || void 0,
|
|
113
|
+
className: clsx(
|
|
114
|
+
"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",
|
|
115
|
+
SIZE_CLASS[size],
|
|
116
|
+
VARIANT_CLASS[variant],
|
|
117
|
+
inactive && "cursor-not-allowed opacity-50",
|
|
118
|
+
className
|
|
119
|
+
),
|
|
120
|
+
onClick: inactive ? (event) => {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
event.stopPropagation();
|
|
123
|
+
} : onClick,
|
|
124
|
+
...linkProps,
|
|
125
|
+
...props,
|
|
126
|
+
children: [
|
|
127
|
+
loading ? /* @__PURE__ */ jsx(
|
|
128
|
+
"span",
|
|
129
|
+
{
|
|
130
|
+
"aria-hidden": "true",
|
|
131
|
+
"data-shell-button-spinner": "",
|
|
132
|
+
className: "inline-block h-4 w-4 animate-spin motion-reduce:animate-none rounded-full border-2 border-current border-t-transparent"
|
|
133
|
+
}
|
|
134
|
+
) : null,
|
|
135
|
+
children
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
var Button_default = Button;
|
|
141
|
+
function FormField({
|
|
142
|
+
id,
|
|
143
|
+
label,
|
|
144
|
+
helperText,
|
|
145
|
+
error,
|
|
146
|
+
required,
|
|
147
|
+
className,
|
|
148
|
+
children
|
|
149
|
+
}) {
|
|
150
|
+
return /* @__PURE__ */ jsxs("div", { className: clsx("flex w-full flex-col gap-1", className), children: [
|
|
151
|
+
label ? /* @__PURE__ */ jsxs("label", { htmlFor: id, className: "text-sm font-semibold text-[color:var(--color-text)]", children: [
|
|
152
|
+
label,
|
|
153
|
+
required ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " *" }) : null
|
|
154
|
+
] }) : null,
|
|
155
|
+
children,
|
|
156
|
+
error ? /* @__PURE__ */ jsx(
|
|
157
|
+
"p",
|
|
158
|
+
{
|
|
159
|
+
id: `${id}-error`,
|
|
160
|
+
role: "alert",
|
|
161
|
+
className: "text-xs text-[color:var(--chrome-danger,var(--color-race-red))]",
|
|
162
|
+
children: error
|
|
163
|
+
}
|
|
164
|
+
) : helperText ? /* @__PURE__ */ jsx("p", { id: `${id}-helper`, className: "text-xs text-[color:var(--color-text-muted)]", children: helperText }) : null
|
|
165
|
+
] });
|
|
166
|
+
}
|
|
167
|
+
function describedBy(id, helperText, error, extra) {
|
|
168
|
+
const generated = error ? `${id}-error` : helperText ? `${id}-helper` : void 0;
|
|
169
|
+
const merged = [generated, extra].filter(Boolean).join(" ");
|
|
170
|
+
return merged || void 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/components/fieldStyles.ts
|
|
174
|
+
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";
|
|
175
|
+
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))]";
|
|
176
|
+
var FIELD_INVALID = "border-[color:var(--chrome-danger,var(--color-race-red))] focus:ring-[color:var(--chrome-danger,var(--color-race-red))]";
|
|
177
|
+
var Input = forwardRef(function Input2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
|
|
178
|
+
const autoId = useId();
|
|
179
|
+
const fieldId = id ?? autoId;
|
|
180
|
+
const isInvalid = Boolean(error) || Boolean(invalid);
|
|
181
|
+
return /* @__PURE__ */ jsx(
|
|
182
|
+
FormField,
|
|
183
|
+
{
|
|
184
|
+
id: fieldId,
|
|
185
|
+
label,
|
|
186
|
+
helperText,
|
|
187
|
+
error,
|
|
188
|
+
required,
|
|
189
|
+
className: wrapperClassName,
|
|
190
|
+
children: /* @__PURE__ */ jsx(
|
|
191
|
+
"input",
|
|
192
|
+
{
|
|
193
|
+
ref,
|
|
194
|
+
id: fieldId,
|
|
195
|
+
required,
|
|
196
|
+
"data-shell-field": "",
|
|
197
|
+
"aria-invalid": isInvalid || void 0,
|
|
198
|
+
"aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
|
|
199
|
+
className: clsx(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
|
|
200
|
+
...props
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
var Input_default = Input;
|
|
207
|
+
var Select = forwardRef(function Select2({ label, helperText, error, invalid, className, wrapperClassName, id, required, children, "aria-describedby": ariaDescribedBy, ...props }, ref) {
|
|
208
|
+
const autoId = useId();
|
|
209
|
+
const fieldId = id ?? autoId;
|
|
210
|
+
const isInvalid = Boolean(error) || Boolean(invalid);
|
|
211
|
+
return /* @__PURE__ */ jsx(
|
|
212
|
+
FormField,
|
|
213
|
+
{
|
|
214
|
+
id: fieldId,
|
|
215
|
+
label,
|
|
216
|
+
helperText,
|
|
217
|
+
error,
|
|
218
|
+
required,
|
|
219
|
+
className: wrapperClassName,
|
|
220
|
+
children: /* @__PURE__ */ jsx(
|
|
221
|
+
"select",
|
|
222
|
+
{
|
|
223
|
+
ref,
|
|
224
|
+
id: fieldId,
|
|
225
|
+
required,
|
|
226
|
+
"data-shell-field": "",
|
|
227
|
+
"aria-invalid": isInvalid || void 0,
|
|
228
|
+
"aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
|
|
229
|
+
className: clsx(FIELD_BASE, "h-[44px]", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
|
|
230
|
+
...props,
|
|
231
|
+
children
|
|
232
|
+
}
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
var Select_default = Select;
|
|
238
|
+
var Textarea = forwardRef(function Textarea2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
|
|
239
|
+
const autoId = useId();
|
|
240
|
+
const fieldId = id ?? autoId;
|
|
241
|
+
const isInvalid = Boolean(error) || Boolean(invalid);
|
|
242
|
+
return /* @__PURE__ */ jsx(
|
|
243
|
+
FormField,
|
|
244
|
+
{
|
|
245
|
+
id: fieldId,
|
|
246
|
+
label,
|
|
247
|
+
helperText,
|
|
248
|
+
error,
|
|
249
|
+
required,
|
|
250
|
+
className: wrapperClassName,
|
|
251
|
+
children: /* @__PURE__ */ jsx(
|
|
252
|
+
"textarea",
|
|
253
|
+
{
|
|
254
|
+
ref,
|
|
255
|
+
id: fieldId,
|
|
256
|
+
required,
|
|
257
|
+
"data-shell-field": "",
|
|
258
|
+
"aria-invalid": isInvalid || void 0,
|
|
259
|
+
"aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
|
|
260
|
+
className: clsx(FIELD_BASE, "min-h-[88px] py-3", isInvalid ? FIELD_INVALID : FIELD_VALID, className),
|
|
261
|
+
...props
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
var Textarea_default = Textarea;
|
|
268
|
+
var Checkbox = forwardRef(function Checkbox2({
|
|
269
|
+
label,
|
|
270
|
+
description,
|
|
271
|
+
indeterminate,
|
|
272
|
+
invalid,
|
|
273
|
+
className,
|
|
274
|
+
wrapperClassName,
|
|
275
|
+
id,
|
|
276
|
+
disabled,
|
|
277
|
+
"aria-describedby": ariaDescribedBy,
|
|
278
|
+
...props
|
|
279
|
+
}, ref) {
|
|
280
|
+
const autoId = useId();
|
|
281
|
+
const fieldId = id ?? autoId;
|
|
282
|
+
const descId = description ? `${fieldId}-description` : void 0;
|
|
283
|
+
const inner = useRef(null);
|
|
284
|
+
const setRef = useCallback(
|
|
285
|
+
(node) => {
|
|
286
|
+
inner.current = node;
|
|
287
|
+
if (typeof ref === "function") ref(node);
|
|
288
|
+
else if (ref) ref.current = node;
|
|
289
|
+
},
|
|
290
|
+
[ref]
|
|
291
|
+
);
|
|
292
|
+
useEffect(() => {
|
|
293
|
+
if (inner.current) inner.current.indeterminate = Boolean(indeterminate);
|
|
294
|
+
}, [indeterminate]);
|
|
295
|
+
const describedBy2 = [descId, ariaDescribedBy].filter(Boolean).join(" ") || void 0;
|
|
296
|
+
return /* @__PURE__ */ jsxs(
|
|
297
|
+
"label",
|
|
298
|
+
{
|
|
299
|
+
htmlFor: fieldId,
|
|
300
|
+
"data-shell-checkbox": "",
|
|
301
|
+
className: clsx(
|
|
302
|
+
"flex min-h-[44px] items-start gap-3 py-[10px] text-sm text-[color:var(--app-card-fg,var(--color-text))]",
|
|
303
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
304
|
+
wrapperClassName
|
|
305
|
+
),
|
|
306
|
+
children: [
|
|
307
|
+
/* @__PURE__ */ jsx(
|
|
308
|
+
"input",
|
|
309
|
+
{
|
|
310
|
+
...props,
|
|
311
|
+
ref: setRef,
|
|
312
|
+
id: fieldId,
|
|
313
|
+
type: "checkbox",
|
|
314
|
+
disabled,
|
|
315
|
+
"data-shell-field": "",
|
|
316
|
+
"aria-invalid": invalid || void 0,
|
|
317
|
+
"aria-describedby": describedBy2,
|
|
318
|
+
className: clsx(
|
|
319
|
+
"mt-[2px] h-5 w-5 shrink-0 rounded-[5px] border focus:outline-none focus-visible:ring-2",
|
|
320
|
+
"accent-[color:var(--color-accent-bg-safe,var(--color-accent))]",
|
|
321
|
+
"focus-visible:ring-[color:var(--app-field-focus,var(--color-accent))]",
|
|
322
|
+
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))]",
|
|
323
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
324
|
+
className
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
label || description ? /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
329
|
+
label ? /* @__PURE__ */ jsx("span", { className: "block font-medium", children: label }) : null,
|
|
330
|
+
description ? /* @__PURE__ */ jsx(
|
|
331
|
+
"span",
|
|
332
|
+
{
|
|
333
|
+
id: descId,
|
|
334
|
+
className: "block text-xs text-[color:var(--app-card-fg-muted,var(--color-text-muted))]",
|
|
335
|
+
children: description
|
|
336
|
+
}
|
|
337
|
+
) : null
|
|
338
|
+
] }) : null
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
});
|
|
343
|
+
var Checkbox_default = Checkbox;
|
|
344
|
+
var FileInput = forwardRef(function FileInput2({ label, helperText, error, invalid, className, wrapperClassName, id, required, "aria-describedby": ariaDescribedBy, ...props }, ref) {
|
|
345
|
+
const autoId = useId();
|
|
346
|
+
const fieldId = id ?? autoId;
|
|
347
|
+
const isInvalid = Boolean(error) || Boolean(invalid);
|
|
348
|
+
return /* @__PURE__ */ jsx(
|
|
349
|
+
FormField,
|
|
350
|
+
{
|
|
351
|
+
id: fieldId,
|
|
352
|
+
label,
|
|
353
|
+
helperText,
|
|
354
|
+
error,
|
|
355
|
+
required,
|
|
356
|
+
className: wrapperClassName,
|
|
357
|
+
children: /* @__PURE__ */ jsx(
|
|
358
|
+
"input",
|
|
359
|
+
{
|
|
360
|
+
...props,
|
|
361
|
+
ref,
|
|
362
|
+
id: fieldId,
|
|
363
|
+
type: "file",
|
|
364
|
+
required,
|
|
365
|
+
"data-shell-field": "",
|
|
366
|
+
"aria-invalid": isInvalid || void 0,
|
|
367
|
+
"aria-describedby": describedBy(fieldId, helperText, error, ariaDescribedBy),
|
|
368
|
+
className: clsx(
|
|
369
|
+
FIELD_BASE,
|
|
370
|
+
"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))]",
|
|
371
|
+
isInvalid ? FIELD_INVALID : FIELD_VALID,
|
|
372
|
+
className
|
|
373
|
+
)
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
);
|
|
378
|
+
});
|
|
379
|
+
var FileInput_default = FileInput;
|
|
11
380
|
|
|
12
381
|
// src/lib/deprecation.ts
|
|
13
382
|
var warned = /* @__PURE__ */ new Set();
|
|
@@ -1952,6 +2321,72 @@ function useThemePreference() {
|
|
|
1952
2321
|
);
|
|
1953
2322
|
return { value, setValue };
|
|
1954
2323
|
}
|
|
2324
|
+
function HeaderTabBar({
|
|
2325
|
+
items,
|
|
2326
|
+
activeId,
|
|
2327
|
+
onChange,
|
|
2328
|
+
className,
|
|
2329
|
+
ariaLabel = "Tabs"
|
|
2330
|
+
}) {
|
|
2331
|
+
warnDeprecated(
|
|
2332
|
+
"HeaderTabBar",
|
|
2333
|
+
"<HeaderTabBar> is deprecated: use <NavTabStrip> from @the-portland-company/shell/native, the canonical page tab strip."
|
|
2334
|
+
);
|
|
2335
|
+
return /* @__PURE__ */ jsx(
|
|
2336
|
+
"div",
|
|
2337
|
+
{
|
|
2338
|
+
role: "tablist",
|
|
2339
|
+
"aria-label": ariaLabel,
|
|
2340
|
+
className: clsx(
|
|
2341
|
+
// Header-wide tab strip: background + bottom border only (no outer box).
|
|
2342
|
+
// Left-aligned and fluid: the container spans the full content width,
|
|
2343
|
+
// the tabs keep their natural width packed from the left (Global-Rules
|
|
2344
|
+
// "Tabs & UI Styling": the strip spans the full width of the content
|
|
2345
|
+
// area; tabs keep their natural width, left-aligned. Spencer 2026-10-11:
|
|
2346
|
+
// all apps, all tabs, all screens). No mx-auto / justify-center /
|
|
2347
|
+
// fixed width on the container.
|
|
2348
|
+
"app-header-tab-bar m-0 flex w-full justify-start bg-slate-100 p-0",
|
|
2349
|
+
"border-b border-slate-200",
|
|
2350
|
+
className
|
|
2351
|
+
),
|
|
2352
|
+
children: items.map((item, idx) => {
|
|
2353
|
+
const isActive = item.id === activeId;
|
|
2354
|
+
const isDisabled = Boolean(item.disabled);
|
|
2355
|
+
return /* @__PURE__ */ jsxs(
|
|
2356
|
+
"button",
|
|
2357
|
+
{
|
|
2358
|
+
type: "button",
|
|
2359
|
+
role: "tab",
|
|
2360
|
+
"aria-selected": isActive,
|
|
2361
|
+
"aria-label": item.label,
|
|
2362
|
+
disabled: isDisabled,
|
|
2363
|
+
onClick: () => onChange(item.id),
|
|
2364
|
+
className: clsx(
|
|
2365
|
+
// `group/tbtip relative` powers the shared <TopBarTooltip>.
|
|
2366
|
+
// Natural width (no flex-1 stretch); 40px square hit area for the
|
|
2367
|
+
// icon-only tab so the strip stays tappable.
|
|
2368
|
+
"group/tbtip app-header-tab-button relative inline-flex h-10 min-w-10 items-center justify-center px-3",
|
|
2369
|
+
"transition-colors",
|
|
2370
|
+
"rounded-none",
|
|
2371
|
+
idx === 0 ? "rounded-tl-lg" : null,
|
|
2372
|
+
idx === items.length - 1 ? "rounded-tr-lg" : null,
|
|
2373
|
+
isActive ? "text-white" : "bg-transparent text-slate-600 hover:bg-white/60 hover:text-slate-900",
|
|
2374
|
+
isDisabled ? "cursor-not-allowed opacity-50" : null
|
|
2375
|
+
),
|
|
2376
|
+
style: {
|
|
2377
|
+
background: isActive ? "var(--mode-primary-color, var(--app-btn-primary-bg))" : void 0
|
|
2378
|
+
},
|
|
2379
|
+
children: [
|
|
2380
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center text-[14px] leading-none", children: item.icon }),
|
|
2381
|
+
isDisabled ? null : /* @__PURE__ */ jsx(TopBarTooltip, { title: item.label })
|
|
2382
|
+
]
|
|
2383
|
+
},
|
|
2384
|
+
item.id
|
|
2385
|
+
);
|
|
2386
|
+
})
|
|
2387
|
+
}
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
1955
2390
|
|
|
1956
2391
|
// src/speculation/emitRules.ts
|
|
1957
2392
|
function buildSpeculationRules(currentApp, registry) {
|
|
@@ -2050,7 +2485,129 @@ function SpeculationRulesScript({ items }) {
|
|
|
2050
2485
|
}, [items, origin]);
|
|
2051
2486
|
return null;
|
|
2052
2487
|
}
|
|
2488
|
+
var MODE_EYEBROW_LABEL = {
|
|
2489
|
+
relationship: "Relationship mode",
|
|
2490
|
+
campaign: "Campaign mode",
|
|
2491
|
+
petition: "Petition mode"
|
|
2492
|
+
};
|
|
2493
|
+
var resolveMaxWidthClass = (maxW) => {
|
|
2494
|
+
if (maxW === "full") return "max-w-none";
|
|
2495
|
+
if (maxW === "container.lg") return "max-w-6xl";
|
|
2496
|
+
if (maxW === "container.md") return "max-w-5xl";
|
|
2497
|
+
return "max-w-7xl";
|
|
2498
|
+
};
|
|
2499
|
+
function PageHeaderView({
|
|
2500
|
+
renderCrumbLink,
|
|
2501
|
+
title,
|
|
2502
|
+
mode,
|
|
2503
|
+
eyebrow,
|
|
2504
|
+
showEyebrow = true,
|
|
2505
|
+
subtitle,
|
|
2506
|
+
breadcrumbs = [],
|
|
2507
|
+
actions = null,
|
|
2508
|
+
tabBar = null,
|
|
2509
|
+
maxW = "full",
|
|
2510
|
+
hideSidebar = false
|
|
2511
|
+
}) {
|
|
2512
|
+
const maxWClass = resolveMaxWidthClass(maxW);
|
|
2513
|
+
const titleText = typeof title === "string" ? title.trim() : "";
|
|
2514
|
+
const normalizedTitle = titleText.toLowerCase();
|
|
2515
|
+
const breadcrumbsWithoutCurrent = [...breadcrumbs];
|
|
2516
|
+
const last = breadcrumbsWithoutCurrent[breadcrumbsWithoutCurrent.length - 1];
|
|
2517
|
+
if (breadcrumbsWithoutCurrent.length > 1 && normalizedTitle && last && last.label.trim().toLowerCase() === normalizedTitle) {
|
|
2518
|
+
breadcrumbsWithoutCurrent.pop();
|
|
2519
|
+
}
|
|
2520
|
+
const eyebrowText = showEyebrow ? eyebrow ?? (mode ? MODE_EYEBROW_LABEL[mode] : void 0) : void 0;
|
|
2521
|
+
if (!title && !eyebrowText && breadcrumbsWithoutCurrent.length === 0 && !actions && !tabBar) {
|
|
2522
|
+
return null;
|
|
2523
|
+
}
|
|
2524
|
+
return /* @__PURE__ */ jsxs(
|
|
2525
|
+
"div",
|
|
2526
|
+
{
|
|
2527
|
+
style: { backgroundColor: "var(--app-tab-header-bg, #888888)" },
|
|
2528
|
+
className: clsx("text-slate-100", tabBar ? "pt-3 pb-0" : "py-3 border-b border-gray-200", {
|
|
2529
|
+
"md:ml-60": !hideSidebar
|
|
2530
|
+
}),
|
|
2531
|
+
children: [
|
|
2532
|
+
/* @__PURE__ */ jsx("div", { className: clsx("w-full px-4", maxWClass), children: /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-nowrap items-start justify-between gap-4", children: [
|
|
2533
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
2534
|
+
eyebrowText ? /* @__PURE__ */ jsx(
|
|
2535
|
+
"div",
|
|
2536
|
+
{
|
|
2537
|
+
className: "truncate text-[11px] font-bold uppercase leading-[1.2] tracking-[0.09em]",
|
|
2538
|
+
style: { color: "var(--mode-accent, var(--color-accent, #E63946))" },
|
|
2539
|
+
children: eyebrowText
|
|
2540
|
+
}
|
|
2541
|
+
) : null,
|
|
2542
|
+
title ? /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx(
|
|
2543
|
+
"div",
|
|
2544
|
+
{
|
|
2545
|
+
className: "truncate font-bold text-white",
|
|
2546
|
+
style: {
|
|
2547
|
+
fontFamily: "var(--font-family, ui-sans-serif, system-ui, sans-serif)",
|
|
2548
|
+
fontSize: "var(--type-h2-size, 1.875rem)",
|
|
2549
|
+
lineHeight: "var(--type-h2-line-height, 1.25)"
|
|
2550
|
+
},
|
|
2551
|
+
children: title
|
|
2552
|
+
}
|
|
2553
|
+
) }) : null,
|
|
2554
|
+
subtitle ? /* @__PURE__ */ jsx("div", { className: "mt-1 truncate text-[15px] text-[color:var(--color-g4,#929599)]", children: subtitle }) : null,
|
|
2555
|
+
breadcrumbsWithoutCurrent.length > 0 ? /* @__PURE__ */ jsx(
|
|
2556
|
+
"nav",
|
|
2557
|
+
{
|
|
2558
|
+
"aria-label": "Breadcrumb",
|
|
2559
|
+
className: clsx("min-w-0 text-slate-100", title ? "mt-1" : ""),
|
|
2560
|
+
children: /* @__PURE__ */ jsx("ol", { className: "flex flex-nowrap items-center gap-2 overflow-hidden text-sm text-gray-600", children: breadcrumbsWithoutCurrent.map((item, index) => /* @__PURE__ */ jsxs(
|
|
2561
|
+
"li",
|
|
2562
|
+
{
|
|
2563
|
+
className: "flex min-w-0 flex-shrink-0 items-center gap-2",
|
|
2564
|
+
children: [
|
|
2565
|
+
index > 0 ? /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: ">" }) : null,
|
|
2566
|
+
item.href ? renderCrumbLink(item.href, item.label, "truncate text-slate-100 hover:underline") : /* @__PURE__ */ jsx("span", { className: "truncate text-slate-100", children: item.label })
|
|
2567
|
+
]
|
|
2568
|
+
},
|
|
2569
|
+
`${item.label}-${index}`
|
|
2570
|
+
)) })
|
|
2571
|
+
}
|
|
2572
|
+
) : null
|
|
2573
|
+
] }),
|
|
2574
|
+
actions ? /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: actions }) : null
|
|
2575
|
+
] }) }),
|
|
2576
|
+
tabBar ? /* @__PURE__ */ jsx("div", { className: "m-0 w-full px-0", style: { backgroundColor: "transparent" }, children: tabBar }) : null
|
|
2577
|
+
]
|
|
2578
|
+
}
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
function BreadcrumbBarView({
|
|
2582
|
+
renderCrumbLink,
|
|
2583
|
+
breadcrumbs = [],
|
|
2584
|
+
actions = null,
|
|
2585
|
+
maxW = "full"
|
|
2586
|
+
}) {
|
|
2587
|
+
warnDeprecated(
|
|
2588
|
+
"BreadcrumbBar",
|
|
2589
|
+
"<BreadcrumbBar> is deprecated for apps: the breadcrumb trail is retired. Use the page header (mode eyebrow + title) instead."
|
|
2590
|
+
);
|
|
2591
|
+
if ((!breadcrumbs || breadcrumbs.length === 0) && !actions) {
|
|
2592
|
+
return null;
|
|
2593
|
+
}
|
|
2594
|
+
const maxWClass = maxW === "full" ? "max-w-none" : maxW === "container.xl" ? "max-w-7xl" : maxW === "container.lg" ? "max-w-6xl" : maxW === "container.md" ? "max-w-5xl" : "max-w-7xl";
|
|
2595
|
+
return /* @__PURE__ */ jsx(
|
|
2596
|
+
"div",
|
|
2597
|
+
{
|
|
2598
|
+
className: "ml-0 border-b border-gray-200 px-4 py-3 md:ml-60",
|
|
2599
|
+
style: { backgroundColor: "var(--app-tab-header-bg, #888888)" },
|
|
2600
|
+
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: [
|
|
2601
|
+
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: [
|
|
2602
|
+
index > 0 ? /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: ">" }) : null,
|
|
2603
|
+
item.href ? renderCrumbLink(item.href, item.label, "text-slate-100 hover:underline") : /* @__PURE__ */ jsx("span", { className: "text-slate-100", children: item.label })
|
|
2604
|
+
] }, index)) }) }),
|
|
2605
|
+
actions && /* @__PURE__ */ jsx("div", { children: actions })
|
|
2606
|
+
] }) })
|
|
2607
|
+
}
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2053
2610
|
|
|
2054
|
-
export { CORE_APP_ORIGIN, CORE_BILLING_PATH, CREDIT_TYPE_LABELS, CREDIT_TYPE_ORDER, CreditsAction, FormColumn, FuelAction, NAV_DISPLAY_OPTIONS, NavChromeProvider, NavDisplayAction, NavThemeControl, NotificationsAction, 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 };
|
|
2055
|
-
//# sourceMappingURL=chunk-
|
|
2056
|
-
//# sourceMappingURL=chunk-
|
|
2611
|
+
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 };
|
|
2612
|
+
//# sourceMappingURL=chunk-J23MTK56.js.map
|
|
2613
|
+
//# sourceMappingURL=chunk-J23MTK56.js.map
|