@the-portland-company/shell 0.95.0 → 0.96.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.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-AIzWNzl-.cjs';
2
- export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, T as TabGlyphComponent, h as aiCreditsWalletUrl, i as createCommsNotificationsAdapter, j as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph } from './index-AIzWNzl-.cjs';
1
+ import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-3YFy4JHI.cjs';
2
+ export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, R as RowMenu, h as RowMenuItem, i as RowMenuPlacement, T as TabGlyphComponent, j as aiCreditsWalletUrl, k as createCommsNotificationsAdapter, l as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph, m as rowMenuPosition } from './index-3YFy4JHI.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode, CSSProperties } from 'react';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-Byjq0Whp.js';
2
- export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, T as TabGlyphComponent, h as aiCreditsWalletUrl, i as createCommsNotificationsAdapter, j as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph } from './index-Byjq0Whp.js';
1
+ import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-CqHKy3vG.js';
2
+ export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, R as RowMenu, h as RowMenuItem, i as RowMenuPlacement, T as TabGlyphComponent, j as aiCreditsWalletUrl, k as createCommsNotificationsAdapter, l as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph, m as rowMenuPosition } from './index-CqHKy3vG.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode, CSSProperties } from 'react';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { PageHeaderView, warnDeprecated, BreadcrumbBarView } from './chunk-JQ53VZO5.js';
2
- export { AI_CREDITS_STATE_TITLES, AiCreditsState, Card, FormColumn, HeaderTabBar, KNOWN_TAB_GLYPHS, SpeculationRulesScript, aiCreditsWalletUrl, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, createCommsNotificationsAdapter, emptyNotificationsFeed, normalizeNotificationsFeed, resolveTabGlyph } from './chunk-JQ53VZO5.js';
1
+ import { PageHeaderView, warnDeprecated, BreadcrumbBarView } from './chunk-5OTXPYZU.js';
2
+ export { AI_CREDITS_STATE_TITLES, AiCreditsState, Card, FormColumn, HeaderTabBar, KNOWN_TAB_GLYPHS, RowMenu, RowMenuItem, SpeculationRulesScript, aiCreditsWalletUrl, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, createCommsNotificationsAdapter, emptyNotificationsFeed, normalizeNotificationsFeed, resolveTabGlyph, rowMenuPosition } from './chunk-5OTXPYZU.js';
3
3
  import { readResolvedTheme } from './chunk-BHRVZPZ7.js';
4
4
  export { BRAND_APPLE_ICON_LINK_ID, BRAND_FAVICON_LINK_ID, BrandFavicon, applyBrandFavicon, watchBrandFavicon } from './chunk-BMR5WAWH.js';
5
5
  import { extendTheme, ChakraProvider, useColorMode } from '@chakra-ui/react';
package/dist/native.cjs CHANGED
@@ -2726,6 +2726,258 @@ function AiCreditsState({
2726
2726
  )
2727
2727
  ] });
2728
2728
  }
2729
+ var GAP = 4;
2730
+ var EDGE = 8;
2731
+ var closeOpenRowMenu = null;
2732
+ var TRIGGER_STYLE = {
2733
+ display: "inline-flex",
2734
+ alignItems: "center",
2735
+ justifyContent: "center",
2736
+ width: 28,
2737
+ height: 28,
2738
+ borderRadius: 6,
2739
+ border: "none",
2740
+ background: "transparent",
2741
+ color: "var(--color-text-muted, #6b7280)",
2742
+ cursor: "pointer",
2743
+ lineHeight: 1
2744
+ };
2745
+ var PANEL_STYLE = {
2746
+ minWidth: 160,
2747
+ padding: 4,
2748
+ border: "1px solid var(--color-border, #e5e7eb)",
2749
+ borderRadius: 8,
2750
+ background: "var(--color-surface, #fff)",
2751
+ boxShadow: "0 10px 24px rgba(15, 23, 42, 0.12)",
2752
+ display: "flex",
2753
+ flexDirection: "column",
2754
+ textAlign: "left"
2755
+ };
2756
+ var ITEM_STYLE = {
2757
+ display: "flex",
2758
+ alignItems: "center",
2759
+ gap: 8,
2760
+ width: "100%",
2761
+ padding: "6px 10px",
2762
+ border: "none",
2763
+ borderRadius: 6,
2764
+ background: "transparent",
2765
+ font: "inherit",
2766
+ fontSize: 14,
2767
+ color: "var(--color-text, #2F3136)",
2768
+ textAlign: "left",
2769
+ cursor: "pointer"
2770
+ };
2771
+ function rowMenuPosition(trigger, panel, viewport) {
2772
+ const below = viewport.height - trigger.bottom - GAP - EDGE;
2773
+ const above = trigger.top - GAP - EDGE;
2774
+ const placement = panel.height > below && above > below ? "above" : "below";
2775
+ const rawTop = placement === "above" ? trigger.top - GAP - panel.height : trigger.bottom + GAP;
2776
+ const top = Math.max(EDGE, Math.min(rawTop, viewport.height - panel.height - EDGE));
2777
+ const left = Math.max(EDGE, Math.min(trigger.right - panel.width, viewport.width - panel.width - EDGE));
2778
+ return { top, left, placement };
2779
+ }
2780
+ function menuItems(panel) {
2781
+ if (!panel) return [];
2782
+ return Array.from(panel.querySelectorAll('[role="menuitem"]')).filter(
2783
+ (el) => !el.disabled && el.getAttribute("aria-disabled") !== "true"
2784
+ );
2785
+ }
2786
+ function RowMenu({
2787
+ label = "More actions",
2788
+ title,
2789
+ icon,
2790
+ children,
2791
+ triggerClassName,
2792
+ triggerStyle,
2793
+ panelClassName,
2794
+ panelStyle,
2795
+ onOpenChange
2796
+ }) {
2797
+ const [open, setOpen] = react.useState(false);
2798
+ const [pos, setPos] = react.useState(null);
2799
+ const triggerRef = react.useRef(null);
2800
+ const panelRef = react.useRef(null);
2801
+ const focusFirstRef = react.useRef(false);
2802
+ const onOpenChangeRef = react.useRef(onOpenChange);
2803
+ onOpenChangeRef.current = onOpenChange;
2804
+ const close = react.useCallback((restoreFocus = false) => {
2805
+ setOpen(false);
2806
+ if (restoreFocus) triggerRef.current?.focus();
2807
+ }, []);
2808
+ const place = react.useCallback(() => {
2809
+ const t = triggerRef.current;
2810
+ const p = panelRef.current;
2811
+ if (!t || !p) return;
2812
+ const r = t.getBoundingClientRect();
2813
+ setPos(rowMenuPosition(
2814
+ { top: r.top, bottom: r.bottom, right: r.right },
2815
+ { width: p.offsetWidth, height: p.offsetHeight },
2816
+ { width: window.innerWidth, height: window.innerHeight }
2817
+ ));
2818
+ }, []);
2819
+ react.useEffect(() => {
2820
+ onOpenChangeRef.current?.(open);
2821
+ if (!open) {
2822
+ setPos(null);
2823
+ return;
2824
+ }
2825
+ const mine = () => setOpen(false);
2826
+ if (closeOpenRowMenu && closeOpenRowMenu !== mine) closeOpenRowMenu();
2827
+ closeOpenRowMenu = mine;
2828
+ return () => {
2829
+ if (closeOpenRowMenu === mine) closeOpenRowMenu = null;
2830
+ };
2831
+ }, [open]);
2832
+ react.useLayoutEffect(() => {
2833
+ if (!open) return;
2834
+ place();
2835
+ const p = panelRef.current;
2836
+ if (!p || typeof ResizeObserver === "undefined") return;
2837
+ const ro = new ResizeObserver(() => place());
2838
+ ro.observe(p);
2839
+ return () => ro.disconnect();
2840
+ }, [open, place]);
2841
+ react.useEffect(() => {
2842
+ if (!open || !pos || !focusFirstRef.current) return;
2843
+ focusFirstRef.current = false;
2844
+ menuItems(panelRef.current)[0]?.focus();
2845
+ }, [open, pos]);
2846
+ react.useEffect(() => {
2847
+ if (!open) return;
2848
+ const inside = (n) => n instanceof Node && (!!triggerRef.current?.contains(n) || !!panelRef.current?.contains(n));
2849
+ const onPointerDown = (e) => {
2850
+ if (!inside(e.target)) close();
2851
+ };
2852
+ const onKey = (e) => {
2853
+ if (e.key === "Escape") {
2854
+ e.stopPropagation();
2855
+ close(true);
2856
+ }
2857
+ };
2858
+ const onScroll = (e) => {
2859
+ if (!inside(e.target)) close();
2860
+ };
2861
+ const onResize = () => close();
2862
+ document.addEventListener("pointerdown", onPointerDown, true);
2863
+ document.addEventListener("keydown", onKey, true);
2864
+ window.addEventListener("scroll", onScroll, true);
2865
+ window.addEventListener("resize", onResize);
2866
+ return () => {
2867
+ document.removeEventListener("pointerdown", onPointerDown, true);
2868
+ document.removeEventListener("keydown", onKey, true);
2869
+ window.removeEventListener("scroll", onScroll, true);
2870
+ window.removeEventListener("resize", onResize);
2871
+ };
2872
+ }, [open, close]);
2873
+ function onTriggerKeyDown(e) {
2874
+ if (e.key === "ArrowDown" || (e.key === "Enter" || e.key === " ") && !open) {
2875
+ e.preventDefault();
2876
+ focusFirstRef.current = true;
2877
+ if (open) menuItems(panelRef.current)[0]?.focus();
2878
+ else setOpen(true);
2879
+ }
2880
+ }
2881
+ function onPanelKeyDown(e) {
2882
+ e.stopPropagation();
2883
+ if (e.key === "Tab") {
2884
+ close();
2885
+ return;
2886
+ }
2887
+ if (e.key !== "ArrowDown" && e.key !== "ArrowUp" && e.key !== "Home" && e.key !== "End") return;
2888
+ const items = menuItems(panelRef.current);
2889
+ if (items.length === 0) return;
2890
+ e.preventDefault();
2891
+ const at = items.indexOf(document.activeElement);
2892
+ const next = e.key === "Home" ? 0 : e.key === "End" ? items.length - 1 : e.key === "ArrowDown" ? (at + 1) % items.length : (at - 1 + items.length) % items.length;
2893
+ items[next]?.focus();
2894
+ }
2895
+ function onPanelClick(e) {
2896
+ e.stopPropagation();
2897
+ const item = e.target.closest?.('[role="menuitem"]');
2898
+ if (!item || !panelRef.current?.contains(item)) return;
2899
+ if (item.disabled || item.getAttribute("aria-disabled") === "true") return;
2900
+ setTimeout(() => close(), 0);
2901
+ }
2902
+ const panel = open && typeof document !== "undefined" ? reactDom.createPortal(
2903
+ /* @__PURE__ */ jsxRuntime.jsx(
2904
+ "div",
2905
+ {
2906
+ ref: panelRef,
2907
+ role: "menu",
2908
+ "aria-label": label,
2909
+ "data-row-menu": "",
2910
+ "data-placement": pos?.placement,
2911
+ className: panelClassName,
2912
+ onClick: onPanelClick,
2913
+ onKeyDown: onPanelKeyDown,
2914
+ style: {
2915
+ ...panelClassName ? null : PANEL_STYLE,
2916
+ ...panelStyle,
2917
+ position: "fixed",
2918
+ zIndex: 1e3,
2919
+ top: pos?.top ?? 0,
2920
+ left: pos?.left ?? 0,
2921
+ right: "auto",
2922
+ bottom: "auto",
2923
+ margin: 0,
2924
+ visibility: pos ? "visible" : "hidden"
2925
+ },
2926
+ children
2927
+ }
2928
+ ),
2929
+ document.body
2930
+ ) : null;
2931
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2932
+ /* @__PURE__ */ jsxRuntime.jsx(
2933
+ "button",
2934
+ {
2935
+ ref: triggerRef,
2936
+ type: "button",
2937
+ className: triggerClassName,
2938
+ style: { ...triggerClassName ? null : TRIGGER_STYLE, ...triggerStyle },
2939
+ "aria-label": label,
2940
+ title,
2941
+ "aria-haspopup": "menu",
2942
+ "aria-expanded": open,
2943
+ "data-open": open ? "" : void 0,
2944
+ onClick: (e) => {
2945
+ e.stopPropagation();
2946
+ setOpen((v) => !v);
2947
+ },
2948
+ onKeyDown: onTriggerKeyDown,
2949
+ children: icon ?? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u22EF" })
2950
+ }
2951
+ ),
2952
+ panel
2953
+ ] });
2954
+ }
2955
+ function RowMenuItem({
2956
+ onSelect,
2957
+ disabled,
2958
+ danger,
2959
+ className,
2960
+ style,
2961
+ children
2962
+ }) {
2963
+ return /* @__PURE__ */ jsxRuntime.jsx(
2964
+ "button",
2965
+ {
2966
+ type: "button",
2967
+ role: "menuitem",
2968
+ className,
2969
+ disabled,
2970
+ onClick: onSelect,
2971
+ style: {
2972
+ ...className ? null : ITEM_STYLE,
2973
+ ...className || !danger ? null : { color: "var(--color-red, #e63946)" },
2974
+ ...className || !disabled ? null : { opacity: 0.5, cursor: "default" },
2975
+ ...style
2976
+ },
2977
+ children
2978
+ }
2979
+ );
2980
+ }
2729
2981
  var standardNavIcons = {
2730
2982
  home: lu.LuHouse,
2731
2983
  users: lu.LuUsers,
@@ -4711,6 +4963,8 @@ exports.NavThemeControl = NavThemeControl;
4711
4963
  exports.NavTopBar = NavTopBar;
4712
4964
  exports.NotificationsAction = NotificationsAction;
4713
4965
  exports.PageHeader = PageHeader;
4966
+ exports.RowMenu = RowMenu;
4967
+ exports.RowMenuItem = RowMenuItem;
4714
4968
  exports.SPECS_ORIGIN = SPECS_ORIGIN;
4715
4969
  exports.SpecOverlayAction = SpecOverlayAction;
4716
4970
  exports.SupportAction = SupportAction;
@@ -4732,6 +4986,7 @@ exports.isNavItemActive = isNavItemActive;
4732
4986
  exports.modeIdFromLabel = modeIdFromLabel;
4733
4987
  exports.resolveOrgLogoUrl = resolveOrgLogoUrl;
4734
4988
  exports.resolveTabGlyph = resolveTabGlyph;
4989
+ exports.rowMenuPosition = rowMenuPosition;
4735
4990
  exports.shortEnvLabel = shortEnvLabel;
4736
4991
  exports.shortUserName = shortUserName;
4737
4992
  exports.standardPolitogyNav = standardPolitogyNav;