@estiva-app/ui 0.44.0 → 0.45.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/SelectionToolbar.d.ts +62 -0
- package/dist/SelectionToolbar.d.ts.map +1 -0
- package/dist/SuggestionMenu.d.ts +75 -0
- package/dist/SuggestionMenu.d.ts.map +1 -0
- package/dist/editor.d.ts +12 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +357 -0
- package/dist/editor.js.map +7 -0
- package/dist/eslint/index.js +2 -2
- package/dist/eslint/index.js.map +2 -2
- package/dist/gates/app-checks.d.ts.map +1 -1
- package/dist/gates/index.js +3 -1
- package/dist/gates/index.js.map +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +201 -99
- package/dist/index.js.map +4 -4
- package/dist/registry/{app-YMABQII6.js → app-LDGOH6UW.js} +3 -3
- package/dist/registry/{build-3EANARLQ.js → build-P6X3PTZP.js} +6 -2
- package/dist/registry/build.d.ts +4 -0
- package/dist/registry/build.d.ts.map +1 -1
- package/dist/registry/{chunk-SIB44CES.js → chunk-P55P2QFD.js} +9 -4
- package/dist/registry/chunk-P55P2QFD.js.map +7 -0
- package/dist/registry/{chunk-EVJW26UR.js → chunk-TQ6UQER3.js} +10 -10
- package/dist/registry/chunk-TQ6UQER3.js.map +7 -0
- package/dist/registry/cli.js +2 -2
- package/dist/registry/index.js +2 -2
- package/dist/shortcuts.d.ts +27 -0
- package/dist/shortcuts.d.ts.map +1 -0
- package/dist/suggestionPopup.d.ts +41 -0
- package/dist/suggestionPopup.d.ts.map +1 -0
- package/package.json +27 -2
- package/registry.json +341 -3
- package/src/SelectionToolbar.mdx +78 -0
- package/src/SelectionToolbar.stories.tsx +63 -0
- package/src/SelectionToolbar.test.ts +105 -0
- package/src/SelectionToolbar.tsx +487 -0
- package/src/SuggestionMenu.mdx +107 -0
- package/src/SuggestionMenu.stories.tsx +202 -0
- package/src/SuggestionMenu.test.tsx +128 -0
- package/src/SuggestionMenu.tsx +189 -0
- package/src/editor.ts +11 -0
- package/src/eslint/no-rebuilt-behaviour.test.ts +1 -1
- package/src/eslint/no-rebuilt-behaviour.ts +2 -2
- package/src/gates/app-checks.ts +6 -1
- package/src/gates/create-app.test.ts +1 -2
- package/src/how.test.ts +1 -1
- package/src/index.ts +2 -0
- package/src/keptSelection.test.ts +67 -0
- package/src/registry/app.ts +8 -8
- package/src/registry/build.ts +10 -2
- package/src/registry/registry.test.ts +14 -9
- package/src/shortcuts.ts +40 -0
- package/src/suggestionPopup.tsx +119 -0
- package/stories/Choosing.mdx +2 -0
- package/dist/registry/chunk-EVJW26UR.js.map +0 -7
- package/dist/registry/chunk-SIB44CES.js.map +0 -7
- /package/dist/registry/{app-YMABQII6.js.map → app-LDGOH6UW.js.map} +0 -0
- /package/dist/registry/{build-3EANARLQ.js.map → build-P6X3PTZP.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -2875,11 +2875,97 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2875
2875
|
);
|
|
2876
2876
|
}
|
|
2877
2877
|
|
|
2878
|
+
// src/SuggestionMenu.tsx
|
|
2879
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useId, useImperativeHandle, useMemo as useMemo4, useState as useState7 } from "react";
|
|
2880
|
+
import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2881
|
+
function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sections, itemKey, row, onSelect, handle }) {
|
|
2882
|
+
const shown = useMemo4(() => sections.filter((section) => section.items.length > 0), [sections]);
|
|
2883
|
+
const items = useMemo4(() => shown.flatMap((section) => section.items), [shown]);
|
|
2884
|
+
const keys = items.map(itemKey).join("\n");
|
|
2885
|
+
const [highlight, setHighlight] = useState7(0);
|
|
2886
|
+
const base = useId();
|
|
2887
|
+
const listboxId = `${base}-list`;
|
|
2888
|
+
useEffect4(() => setHighlight(0), [keys]);
|
|
2889
|
+
useImperativeHandle(handle, () => ({
|
|
2890
|
+
// The editor hands its arrow keys to this list: Base UI's lists need a text field of their own, and an editor is not one.
|
|
2891
|
+
onKeyDown: (event) => {
|
|
2892
|
+
if (!items.length) return false;
|
|
2893
|
+
if (event.key === "ArrowDown") {
|
|
2894
|
+
setHighlight((h) => (h + 1) % items.length);
|
|
2895
|
+
return true;
|
|
2896
|
+
}
|
|
2897
|
+
if (event.key === "ArrowUp") {
|
|
2898
|
+
setHighlight((h) => (h - 1 + items.length) % items.length);
|
|
2899
|
+
return true;
|
|
2900
|
+
}
|
|
2901
|
+
if (event.key === "Enter") {
|
|
2902
|
+
const item = items[highlight];
|
|
2903
|
+
if (item !== void 0) onSelect(item);
|
|
2904
|
+
return true;
|
|
2905
|
+
}
|
|
2906
|
+
return false;
|
|
2907
|
+
}
|
|
2908
|
+
}), [items, highlight, onSelect]);
|
|
2909
|
+
const open = rect !== null && items.length > 0;
|
|
2910
|
+
useEffect4(() => {
|
|
2911
|
+
if (!editorElement || !open) return;
|
|
2912
|
+
editorElement.setAttribute("aria-autocomplete", "list");
|
|
2913
|
+
editorElement.setAttribute("aria-haspopup", "listbox");
|
|
2914
|
+
editorElement.setAttribute("aria-controls", listboxId);
|
|
2915
|
+
return () => {
|
|
2916
|
+
for (const name of ["aria-autocomplete", "aria-haspopup", "aria-controls", "aria-activedescendant"]) editorElement.removeAttribute(name);
|
|
2917
|
+
};
|
|
2918
|
+
}, [editorElement, open, listboxId]);
|
|
2919
|
+
useEffect4(() => {
|
|
2920
|
+
if (!editorElement || !open) return;
|
|
2921
|
+
editorElement.setAttribute("aria-activedescendant", `${base}-${highlight}`);
|
|
2922
|
+
}, [editorElement, open, base, highlight]);
|
|
2923
|
+
const scrollRef = useCallback3((el) => {
|
|
2924
|
+
el?.scrollIntoView({ block: "nearest" });
|
|
2925
|
+
}, []);
|
|
2926
|
+
if (items.length === 0) return null;
|
|
2927
|
+
const drawRow = (item) => {
|
|
2928
|
+
const index = items.indexOf(item);
|
|
2929
|
+
const selected = index === highlight;
|
|
2930
|
+
const { label, description, leading, shortcut, hint, size } = row(item);
|
|
2931
|
+
return (
|
|
2932
|
+
// A row of a list the editor drives from its caret: focus stays in the text, so the row is no Tab stop.
|
|
2933
|
+
/* @__PURE__ */ jsx45(
|
|
2934
|
+
MenuItem,
|
|
2935
|
+
{
|
|
2936
|
+
role: "option",
|
|
2937
|
+
id: `${base}-${index}`,
|
|
2938
|
+
"aria-selected": selected,
|
|
2939
|
+
tabIndex: -1,
|
|
2940
|
+
ref: selected ? scrollRef : void 0,
|
|
2941
|
+
size,
|
|
2942
|
+
label,
|
|
2943
|
+
description,
|
|
2944
|
+
leading,
|
|
2945
|
+
shortcut,
|
|
2946
|
+
hint,
|
|
2947
|
+
selected,
|
|
2948
|
+
onMouseEnter: () => setHighlight(index),
|
|
2949
|
+
onMouseDown: (event) => {
|
|
2950
|
+
event.preventDefault();
|
|
2951
|
+
onSelect(item);
|
|
2952
|
+
}
|
|
2953
|
+
},
|
|
2954
|
+
itemKey(item)
|
|
2955
|
+
)
|
|
2956
|
+
);
|
|
2957
|
+
};
|
|
2958
|
+
return /* @__PURE__ */ jsx45(Popover, { anchor: rect, open: rect !== null, side: "top", align: "left", className: width, maxHeight, ariaLabel, children: /* @__PURE__ */ jsx45("div", { id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "flex flex-col", children: shown.map((section, i) => /* @__PURE__ */ jsxs31("div", { className: "contents", children: [
|
|
2959
|
+
i > 0 && /* @__PURE__ */ jsx45(MenuSeparator, {}),
|
|
2960
|
+
section.label ? /* @__PURE__ */ jsx45("div", { role: "group", "aria-label": section.label, children: /* @__PURE__ */ jsx45(MenuSection, { label: section.label, className: section.className, children: section.items.map(drawRow) }) }) : section.items.map(drawRow)
|
|
2961
|
+
] }, section.label ?? i)) }) });
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2878
2964
|
// src/Toolbar.tsx
|
|
2879
2965
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
2880
|
-
import { jsx as
|
|
2966
|
+
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
2881
2967
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
2882
|
-
const strip = /* @__PURE__ */
|
|
2968
|
+
const strip = /* @__PURE__ */ jsx46(
|
|
2883
2969
|
BaseToolbar.Root,
|
|
2884
2970
|
{
|
|
2885
2971
|
"aria-label": ariaLabel,
|
|
@@ -2890,27 +2976,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
2890
2976
|
}
|
|
2891
2977
|
);
|
|
2892
2978
|
if (!surface) return strip;
|
|
2893
|
-
return /* @__PURE__ */
|
|
2979
|
+
return /* @__PURE__ */ jsx46(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
2894
2980
|
}
|
|
2895
2981
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
2896
|
-
return /* @__PURE__ */
|
|
2982
|
+
return /* @__PURE__ */ jsx46(
|
|
2897
2983
|
BaseToolbar.Button,
|
|
2898
2984
|
{
|
|
2899
2985
|
ref,
|
|
2900
2986
|
disabled: disabled || !!disabledReason,
|
|
2901
2987
|
focusableWhenDisabled: true,
|
|
2902
|
-
render: /* @__PURE__ */
|
|
2988
|
+
render: /* @__PURE__ */ jsx46(IconButton, { disabled, disabledReason, ...props })
|
|
2903
2989
|
}
|
|
2904
2990
|
);
|
|
2905
2991
|
}
|
|
2906
2992
|
function ToolbarLink({ ref, href, ...props }) {
|
|
2907
|
-
return /* @__PURE__ */
|
|
2993
|
+
return /* @__PURE__ */ jsx46(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx46(IconButton, { href, ...props }) });
|
|
2908
2994
|
}
|
|
2909
2995
|
function ToolbarInput({ size, ...props }) {
|
|
2910
|
-
return /* @__PURE__ */
|
|
2996
|
+
return /* @__PURE__ */ jsx46(BaseToolbar.Input, { render: /* @__PURE__ */ jsx46(TextInput, { size }), ...props });
|
|
2911
2997
|
}
|
|
2912
2998
|
function ToolbarSeparator({ className }) {
|
|
2913
|
-
return /* @__PURE__ */
|
|
2999
|
+
return /* @__PURE__ */ jsx46(
|
|
2914
3000
|
BaseToolbar.Separator,
|
|
2915
3001
|
{
|
|
2916
3002
|
orientation: "vertical",
|
|
@@ -2920,9 +3006,9 @@ function ToolbarSeparator({ className }) {
|
|
|
2920
3006
|
}
|
|
2921
3007
|
|
|
2922
3008
|
// src/ReactionPicker.tsx
|
|
2923
|
-
import { jsx as
|
|
3009
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
2924
3010
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
2925
|
-
return /* @__PURE__ */
|
|
3011
|
+
return /* @__PURE__ */ jsx47(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
2926
3012
|
/*
|
|
2927
3013
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
2928
3014
|
would become the toolbar's item and the button inside it would never
|
|
@@ -2932,14 +3018,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2932
3018
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
2933
3019
|
and both say the meaning rather than the glyph.
|
|
2934
3020
|
*/
|
|
2935
|
-
/* @__PURE__ */
|
|
3021
|
+
/* @__PURE__ */ jsx47(
|
|
2936
3022
|
ToolbarButton,
|
|
2937
3023
|
{
|
|
2938
3024
|
"aria-label": option.label,
|
|
2939
3025
|
tooltip: option.label,
|
|
2940
3026
|
onClick: () => onSelect(option.emoji),
|
|
2941
3027
|
className: "size-7",
|
|
2942
|
-
children: /* @__PURE__ */
|
|
3028
|
+
children: /* @__PURE__ */ jsx47("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
2943
3029
|
},
|
|
2944
3030
|
option.emoji
|
|
2945
3031
|
)
|
|
@@ -2948,23 +3034,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2948
3034
|
|
|
2949
3035
|
// src/PreviewCard.tsx
|
|
2950
3036
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
2951
|
-
import { jsx as
|
|
3037
|
+
import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2952
3038
|
var GAP6 = 12;
|
|
2953
3039
|
var VIEWPORT_PAD6 = 8;
|
|
2954
3040
|
var OPEN_DELAY2 = 350;
|
|
2955
3041
|
var CLOSE_DELAY = 200;
|
|
2956
3042
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
|
|
2957
|
-
return /* @__PURE__ */
|
|
2958
|
-
/* @__PURE__ */
|
|
3043
|
+
return /* @__PURE__ */ jsxs32(BasePreviewCard.Root, { children: [
|
|
3044
|
+
/* @__PURE__ */ jsx48(
|
|
2959
3045
|
BasePreviewCard.Trigger,
|
|
2960
3046
|
{
|
|
2961
3047
|
delay,
|
|
2962
3048
|
closeDelay,
|
|
2963
|
-
render: /* @__PURE__ */
|
|
3049
|
+
render: /* @__PURE__ */ jsx48("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
2964
3050
|
children
|
|
2965
3051
|
}
|
|
2966
3052
|
),
|
|
2967
|
-
/* @__PURE__ */
|
|
3053
|
+
/* @__PURE__ */ jsx48(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx48(
|
|
2968
3054
|
BasePreviewCard.Positioner,
|
|
2969
3055
|
{
|
|
2970
3056
|
side,
|
|
@@ -2972,12 +3058,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2972
3058
|
sideOffset: GAP6,
|
|
2973
3059
|
collisionPadding: VIEWPORT_PAD6,
|
|
2974
3060
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2975
|
-
children: /* @__PURE__ */
|
|
3061
|
+
children: /* @__PURE__ */ jsx48(
|
|
2976
3062
|
BasePreviewCard.Popup,
|
|
2977
3063
|
{
|
|
2978
3064
|
className: cn("w-[360px] p-0 outline-none", className),
|
|
2979
|
-
render: /* @__PURE__ */
|
|
2980
|
-
children: /* @__PURE__ */
|
|
3065
|
+
render: /* @__PURE__ */ jsx48(MenuPanel, {}),
|
|
3066
|
+
children: /* @__PURE__ */ jsx48(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
|
|
2981
3067
|
}
|
|
2982
3068
|
)
|
|
2983
3069
|
}
|
|
@@ -2986,15 +3072,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2986
3072
|
}
|
|
2987
3073
|
|
|
2988
3074
|
// src/Rail.tsx
|
|
2989
|
-
import { jsx as
|
|
3075
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
2990
3076
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
2991
|
-
return /* @__PURE__ */
|
|
3077
|
+
return /* @__PURE__ */ jsx49("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
2992
3078
|
}
|
|
2993
3079
|
|
|
2994
3080
|
// src/RailItem.tsx
|
|
2995
|
-
import { jsx as
|
|
3081
|
+
import { jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2996
3082
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
2997
|
-
return /* @__PURE__ */
|
|
3083
|
+
return /* @__PURE__ */ jsxs33(
|
|
2998
3084
|
"a",
|
|
2999
3085
|
{
|
|
3000
3086
|
href,
|
|
@@ -3002,14 +3088,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3002
3088
|
className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
3003
3089
|
...props,
|
|
3004
3090
|
children: [
|
|
3005
|
-
/* @__PURE__ */
|
|
3091
|
+
/* @__PURE__ */ jsx50(
|
|
3006
3092
|
"div",
|
|
3007
3093
|
{
|
|
3008
3094
|
className: cn(
|
|
3009
3095
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
3010
3096
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
3011
3097
|
),
|
|
3012
|
-
children: /* @__PURE__ */
|
|
3098
|
+
children: /* @__PURE__ */ jsx50(
|
|
3013
3099
|
"span",
|
|
3014
3100
|
{
|
|
3015
3101
|
className: cn(
|
|
@@ -3021,14 +3107,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3021
3107
|
)
|
|
3022
3108
|
}
|
|
3023
3109
|
),
|
|
3024
|
-
/* @__PURE__ */
|
|
3110
|
+
/* @__PURE__ */ jsx50("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
3025
3111
|
]
|
|
3026
3112
|
}
|
|
3027
3113
|
);
|
|
3028
3114
|
}
|
|
3029
3115
|
|
|
3030
3116
|
// src/Property.tsx
|
|
3031
|
-
import { jsx as
|
|
3117
|
+
import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3032
3118
|
var VALUE_CLASSES = "contents";
|
|
3033
3119
|
function Property({ label, layout = "row", children, className }) {
|
|
3034
3120
|
if (layout === "stacked") {
|
|
@@ -3036,25 +3122,25 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
3036
3122
|
// gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
|
|
3037
3123
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
3038
3124
|
// 6px, and unifying means the bigger, calmer one.
|
|
3039
|
-
/* @__PURE__ */
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
/* @__PURE__ */
|
|
3125
|
+
/* @__PURE__ */ jsxs34("dl", { className: cn("flex flex-col gap-3", className), children: [
|
|
3126
|
+
/* @__PURE__ */ jsx51("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
|
|
3127
|
+
/* @__PURE__ */ jsx51("dd", { className: VALUE_CLASSES, children })
|
|
3042
3128
|
] })
|
|
3043
3129
|
);
|
|
3044
3130
|
}
|
|
3045
|
-
return /* @__PURE__ */
|
|
3046
|
-
/* @__PURE__ */
|
|
3047
|
-
/* @__PURE__ */
|
|
3131
|
+
return /* @__PURE__ */ jsxs34("dl", { className: cn("flex items-center gap-2", className), children: [
|
|
3132
|
+
/* @__PURE__ */ jsx51("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
3133
|
+
/* @__PURE__ */ jsx51("dd", { className: VALUE_CLASSES, children })
|
|
3048
3134
|
] });
|
|
3049
3135
|
}
|
|
3050
3136
|
|
|
3051
3137
|
// src/Reaction.tsx
|
|
3052
3138
|
import { Toggle } from "@base-ui/react/toggle";
|
|
3053
|
-
import { jsx as
|
|
3139
|
+
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3054
3140
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
3055
3141
|
return (
|
|
3056
3142
|
// @estiva-escape(no-copied-look): W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
|
|
3057
|
-
/* @__PURE__ */
|
|
3143
|
+
/* @__PURE__ */ jsxs35(
|
|
3058
3144
|
Toggle,
|
|
3059
3145
|
{
|
|
3060
3146
|
pressed,
|
|
@@ -3076,8 +3162,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3076
3162
|
),
|
|
3077
3163
|
...props,
|
|
3078
3164
|
children: [
|
|
3079
|
-
/* @__PURE__ */
|
|
3080
|
-
/* @__PURE__ */
|
|
3165
|
+
/* @__PURE__ */ jsx52("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
3166
|
+
/* @__PURE__ */ jsx52("span", { className: CHIP_TEXT_CLASSES, children: count })
|
|
3081
3167
|
]
|
|
3082
3168
|
}
|
|
3083
3169
|
)
|
|
@@ -3087,9 +3173,9 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3087
3173
|
// src/SearchInput.tsx
|
|
3088
3174
|
import "react";
|
|
3089
3175
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
3090
|
-
import { jsx as
|
|
3176
|
+
import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3091
3177
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
3092
|
-
return /* @__PURE__ */
|
|
3178
|
+
return /* @__PURE__ */ jsxs36(
|
|
3093
3179
|
"div",
|
|
3094
3180
|
{
|
|
3095
3181
|
className: cn(
|
|
@@ -3101,7 +3187,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3101
3187
|
className
|
|
3102
3188
|
),
|
|
3103
3189
|
children: [
|
|
3104
|
-
/* @__PURE__ */
|
|
3190
|
+
/* @__PURE__ */ jsx53(
|
|
3105
3191
|
Input3,
|
|
3106
3192
|
{
|
|
3107
3193
|
className: cn("flex-1 min-w-0 text-input-value", BARE_INPUT_CLASSES),
|
|
@@ -3109,7 +3195,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3109
3195
|
...props
|
|
3110
3196
|
}
|
|
3111
3197
|
),
|
|
3112
|
-
shortcut && /* @__PURE__ */
|
|
3198
|
+
shortcut && /* @__PURE__ */ jsx53(Kbd, { children: shortcut })
|
|
3113
3199
|
]
|
|
3114
3200
|
}
|
|
3115
3201
|
);
|
|
@@ -3118,17 +3204,17 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3118
3204
|
// src/SectionHeader.tsx
|
|
3119
3205
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
3120
3206
|
import { useRender } from "@base-ui/react/use-render";
|
|
3121
|
-
import { Fragment as Fragment11, jsx as
|
|
3207
|
+
import { Fragment as Fragment11, jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3122
3208
|
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", hover = "fill", render, className }) {
|
|
3123
3209
|
const titleElement = useRender({
|
|
3124
|
-
render: render ?? (chevron ? /* @__PURE__ */
|
|
3210
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx54("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx54("span", {})),
|
|
3125
3211
|
props: {
|
|
3126
3212
|
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
3127
3213
|
// whole row up to the actions is the hit target, as it was when the
|
|
3128
3214
|
// row itself carried the click.
|
|
3129
3215
|
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
3130
|
-
children: /* @__PURE__ */
|
|
3131
|
-
chevron && /* @__PURE__ */
|
|
3216
|
+
children: /* @__PURE__ */ jsxs37(Fragment11, { children: [
|
|
3217
|
+
chevron && /* @__PURE__ */ jsx54(
|
|
3132
3218
|
IconChevronRight2,
|
|
3133
3219
|
{
|
|
3134
3220
|
size: 12,
|
|
@@ -3136,11 +3222,11 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
3136
3222
|
className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
3137
3223
|
}
|
|
3138
3224
|
),
|
|
3139
|
-
/* @__PURE__ */
|
|
3225
|
+
/* @__PURE__ */ jsx54(SectionLabel, { children: title })
|
|
3140
3226
|
] })
|
|
3141
3227
|
}
|
|
3142
3228
|
});
|
|
3143
|
-
return /* @__PURE__ */
|
|
3229
|
+
return /* @__PURE__ */ jsxs37(
|
|
3144
3230
|
"div",
|
|
3145
3231
|
{
|
|
3146
3232
|
className: cn(
|
|
@@ -3153,15 +3239,15 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
3153
3239
|
),
|
|
3154
3240
|
children: [
|
|
3155
3241
|
titleElement,
|
|
3156
|
-
trailing != null && /* @__PURE__ */
|
|
3157
|
-
actions && actions.length > 0 && /* @__PURE__ */
|
|
3242
|
+
trailing != null && /* @__PURE__ */ jsx54("div", { className: "flex shrink-0 items-center", children: trailing }),
|
|
3243
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx54(
|
|
3158
3244
|
"div",
|
|
3159
3245
|
{
|
|
3160
3246
|
className: cn(
|
|
3161
3247
|
"-mr-1 flex shrink-0 items-center gap-1",
|
|
3162
3248
|
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
3163
3249
|
),
|
|
3164
|
-
children: actions.map((action) => /* @__PURE__ */
|
|
3250
|
+
children: actions.map((action) => /* @__PURE__ */ jsx54(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
3165
3251
|
}
|
|
3166
3252
|
)
|
|
3167
3253
|
]
|
|
@@ -3170,35 +3256,35 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
3170
3256
|
}
|
|
3171
3257
|
|
|
3172
3258
|
// src/Panel.tsx
|
|
3173
|
-
import { jsx as
|
|
3259
|
+
import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3174
3260
|
function Frame({ title, chevron = false, actions, children, footer, bodyClassName, bodyRef, onBodyScroll, className, broken = false }) {
|
|
3175
|
-
return /* @__PURE__ */
|
|
3176
|
-
/* @__PURE__ */
|
|
3261
|
+
return /* @__PURE__ */ jsxs38("div", { className: cn("flex h-full min-h-0 flex-1 flex-col", className), children: [
|
|
3262
|
+
/* @__PURE__ */ jsx55(ContainerHeader, { title, chevron, actions }),
|
|
3177
3263
|
broken ? (
|
|
3178
3264
|
// The message takes the room the body had and centres itself in it.
|
|
3179
|
-
/* @__PURE__ */
|
|
3180
|
-
) : /* @__PURE__ */
|
|
3181
|
-
!broken && footer && /* @__PURE__ */
|
|
3265
|
+
/* @__PURE__ */ jsx55("div", { className: "flex min-h-0 flex-1 flex-col px-4", children })
|
|
3266
|
+
) : /* @__PURE__ */ jsx55(ScrollArea, { className: "min-h-0 flex-1", contentClassName: bodyClassName, viewportRef: bodyRef, onScroll: onBodyScroll, children }),
|
|
3267
|
+
!broken && footer && /* @__PURE__ */ jsx55("div", { className: "shrink-0", children: footer })
|
|
3182
3268
|
] });
|
|
3183
3269
|
}
|
|
3184
3270
|
function Panel(props) {
|
|
3185
|
-
return /* @__PURE__ */
|
|
3271
|
+
return /* @__PURE__ */ jsx55(
|
|
3186
3272
|
ErrorBoundary,
|
|
3187
3273
|
{
|
|
3188
3274
|
label: "panel",
|
|
3189
3275
|
frame: (message) => (
|
|
3190
3276
|
// Only the name comes back with the message: the actions and the footer may be what threw.
|
|
3191
|
-
/* @__PURE__ */
|
|
3277
|
+
/* @__PURE__ */ jsx55(Frame, { title: props.title, chevron: props.chevron, className: props.className, broken: true, children: message })
|
|
3192
3278
|
),
|
|
3193
|
-
children: /* @__PURE__ */
|
|
3279
|
+
children: /* @__PURE__ */ jsx55(Frame, { ...props })
|
|
3194
3280
|
}
|
|
3195
3281
|
);
|
|
3196
3282
|
}
|
|
3197
3283
|
|
|
3198
3284
|
// src/ListColumn.tsx
|
|
3199
|
-
import { jsx as
|
|
3285
|
+
import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3200
3286
|
function Column({ title, chevron = false, actions, above, collapsed = false, children, className, broken = false }) {
|
|
3201
|
-
return /* @__PURE__ */
|
|
3287
|
+
return /* @__PURE__ */ jsxs39(
|
|
3202
3288
|
"div",
|
|
3203
3289
|
{
|
|
3204
3290
|
className: cn(
|
|
@@ -3209,34 +3295,34 @@ function Column({ title, chevron = false, actions, above, collapsed = false, chi
|
|
|
3209
3295
|
),
|
|
3210
3296
|
"data-collapsed": collapsed || void 0,
|
|
3211
3297
|
children: [
|
|
3212
|
-
/* @__PURE__ */
|
|
3298
|
+
/* @__PURE__ */ jsx56(ContainerHeader, { title, chevron, actions }),
|
|
3213
3299
|
above,
|
|
3214
3300
|
broken ? (
|
|
3215
3301
|
// The message takes the room the list had and centres itself in it (Katerina, 19 September).
|
|
3216
|
-
/* @__PURE__ */
|
|
3217
|
-
) : /* @__PURE__ */
|
|
3302
|
+
/* @__PURE__ */ jsx56("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
|
|
3303
|
+
) : /* @__PURE__ */ jsx56(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
|
|
3218
3304
|
]
|
|
3219
3305
|
}
|
|
3220
3306
|
);
|
|
3221
3307
|
}
|
|
3222
3308
|
function ListColumn(props) {
|
|
3223
|
-
return /* @__PURE__ */
|
|
3309
|
+
return /* @__PURE__ */ jsx56(
|
|
3224
3310
|
ErrorBoundary,
|
|
3225
3311
|
{
|
|
3226
3312
|
label: "list panel",
|
|
3227
3313
|
frame: (message) => (
|
|
3228
3314
|
// Only the name comes back with the message: the actions and the row above may be what threw.
|
|
3229
|
-
/* @__PURE__ */
|
|
3315
|
+
/* @__PURE__ */ jsx56(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
|
|
3230
3316
|
),
|
|
3231
|
-
children: /* @__PURE__ */
|
|
3317
|
+
children: /* @__PURE__ */ jsx56(Column, { ...props })
|
|
3232
3318
|
}
|
|
3233
3319
|
);
|
|
3234
3320
|
}
|
|
3235
3321
|
|
|
3236
3322
|
// src/CollapsibleSection.tsx
|
|
3237
|
-
import { useState as
|
|
3323
|
+
import { useState as useState8 } from "react";
|
|
3238
3324
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
3239
|
-
import { jsx as
|
|
3325
|
+
import { jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3240
3326
|
var OPEN = "open";
|
|
3241
3327
|
var CLOSED = "closed";
|
|
3242
3328
|
function readStored(key) {
|
|
@@ -3256,21 +3342,21 @@ function writeStored(key, open) {
|
|
|
3256
3342
|
}
|
|
3257
3343
|
}
|
|
3258
3344
|
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, trailing, actions, showActions, children, className, contentClassName }) {
|
|
3259
|
-
const [openState, setOpenState] =
|
|
3345
|
+
const [openState, setOpenState] = useState8(() => readStored(storageKey) ?? defaultOpen);
|
|
3260
3346
|
const open = openProp ?? openState;
|
|
3261
3347
|
const setOpen = (next) => {
|
|
3262
3348
|
setOpenState(next);
|
|
3263
3349
|
writeStored(storageKey, next);
|
|
3264
3350
|
onOpenChange?.(next);
|
|
3265
3351
|
};
|
|
3266
|
-
return /* @__PURE__ */
|
|
3267
|
-
/* @__PURE__ */
|
|
3268
|
-
/* @__PURE__ */
|
|
3352
|
+
return /* @__PURE__ */ jsxs40(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
3353
|
+
/* @__PURE__ */ jsx57(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx57(Collapsible.Trigger, {}) }),
|
|
3354
|
+
/* @__PURE__ */ jsx57(
|
|
3269
3355
|
Collapsible.Panel,
|
|
3270
3356
|
{
|
|
3271
3357
|
hiddenUntilFound: true,
|
|
3272
3358
|
className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
|
|
3273
|
-
children: /* @__PURE__ */
|
|
3359
|
+
children: /* @__PURE__ */ jsx57("div", { className: cn("flex flex-col", contentClassName), children })
|
|
3274
3360
|
}
|
|
3275
3361
|
)
|
|
3276
3362
|
] });
|
|
@@ -3278,9 +3364,9 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
|
|
|
3278
3364
|
|
|
3279
3365
|
// src/Tabs.tsx
|
|
3280
3366
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
3281
|
-
import { jsx as
|
|
3367
|
+
import { jsx as jsx58, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3282
3368
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
3283
|
-
return /* @__PURE__ */
|
|
3369
|
+
return /* @__PURE__ */ jsx58(
|
|
3284
3370
|
BaseTabs.Root,
|
|
3285
3371
|
{
|
|
3286
3372
|
value: active,
|
|
@@ -3288,14 +3374,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3288
3374
|
if (details.reason === "none") onChange(value);
|
|
3289
3375
|
},
|
|
3290
3376
|
className,
|
|
3291
|
-
children: /* @__PURE__ */
|
|
3377
|
+
children: /* @__PURE__ */ jsx58(
|
|
3292
3378
|
BaseTabs.List,
|
|
3293
3379
|
{
|
|
3294
3380
|
activateOnFocus: true,
|
|
3295
3381
|
"aria-label": aria["aria-label"],
|
|
3296
3382
|
"aria-labelledby": aria["aria-labelledby"],
|
|
3297
3383
|
className: "flex items-center gap-2",
|
|
3298
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
3384
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs41(
|
|
3299
3385
|
BaseTabs.Tab,
|
|
3300
3386
|
{
|
|
3301
3387
|
value: tab.id,
|
|
@@ -3308,9 +3394,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3308
3394
|
),
|
|
3309
3395
|
children: [
|
|
3310
3396
|
tab.icon,
|
|
3311
|
-
/* @__PURE__ */
|
|
3397
|
+
/* @__PURE__ */ jsxs41("span", { className: "flex items-baseline", children: [
|
|
3312
3398
|
tab.label,
|
|
3313
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
3399
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx58("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
3314
3400
|
] })
|
|
3315
3401
|
]
|
|
3316
3402
|
},
|
|
@@ -3323,10 +3409,10 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3323
3409
|
}
|
|
3324
3410
|
|
|
3325
3411
|
// src/Toast.tsx
|
|
3326
|
-
import { createContext as createContext6, useContext as useContext6, useMemo as
|
|
3412
|
+
import { createContext as createContext6, useContext as useContext6, useMemo as useMemo5 } from "react";
|
|
3327
3413
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
3328
3414
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
3329
|
-
import { jsx as
|
|
3415
|
+
import { jsx as jsx59, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3330
3416
|
var SURFACE_STYLES = {
|
|
3331
3417
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
3332
3418
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
@@ -3362,23 +3448,23 @@ var pillClassName = (type, hasAction, className) => cn(
|
|
|
3362
3448
|
);
|
|
3363
3449
|
function LeadingIcon({ type }) {
|
|
3364
3450
|
const Icon = ICONS[type];
|
|
3365
|
-
return /* @__PURE__ */
|
|
3451
|
+
return /* @__PURE__ */ jsx59(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
|
|
3366
3452
|
}
|
|
3367
3453
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
3368
3454
|
const hasAction = !!(actionLabel && onAction);
|
|
3369
|
-
return /* @__PURE__ */
|
|
3370
|
-
/* @__PURE__ */
|
|
3371
|
-
leadingIcon && /* @__PURE__ */
|
|
3372
|
-
/* @__PURE__ */
|
|
3455
|
+
return /* @__PURE__ */ jsxs42("div", { className: pillClassName(type, hasAction, className), children: [
|
|
3456
|
+
/* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3457
|
+
leadingIcon && /* @__PURE__ */ jsx59(LeadingIcon, { type }),
|
|
3458
|
+
/* @__PURE__ */ jsx59("span", { className: LABEL_CLASSES, children: label })
|
|
3373
3459
|
] }),
|
|
3374
|
-
hasAction && /* @__PURE__ */
|
|
3460
|
+
hasAction && /* @__PURE__ */ jsx59(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
3375
3461
|
] });
|
|
3376
3462
|
}
|
|
3377
3463
|
var ToastContext = createContext6(null);
|
|
3378
3464
|
var VISIBLE_TOASTS = 3;
|
|
3379
3465
|
function ToastProvider({ children }) {
|
|
3380
|
-
const manager =
|
|
3381
|
-
const value =
|
|
3466
|
+
const manager = useMemo5(() => BaseToast.createToastManager(), []);
|
|
3467
|
+
const value = useMemo5(
|
|
3382
3468
|
() => ({
|
|
3383
3469
|
showToast: ({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, durationMs = 5e3 }) => manager.add({
|
|
3384
3470
|
title: label,
|
|
@@ -3392,9 +3478,9 @@ function ToastProvider({ children }) {
|
|
|
3392
3478
|
}),
|
|
3393
3479
|
[manager]
|
|
3394
3480
|
);
|
|
3395
|
-
return /* @__PURE__ */
|
|
3481
|
+
return /* @__PURE__ */ jsx59(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs42(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
|
|
3396
3482
|
children,
|
|
3397
|
-
/* @__PURE__ */
|
|
3483
|
+
/* @__PURE__ */ jsx59(BaseToast.Portal, { children: /* @__PURE__ */ jsx59(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx59(ToastList, {}) }) })
|
|
3398
3484
|
] }) });
|
|
3399
3485
|
}
|
|
3400
3486
|
function ToastList() {
|
|
@@ -3402,25 +3488,25 @@ function ToastList() {
|
|
|
3402
3488
|
return toasts.map((toast) => {
|
|
3403
3489
|
const type = toast.type ?? "neutral";
|
|
3404
3490
|
const { leadingIcon = true, actionLabel, onAction } = toast.data ?? {};
|
|
3405
|
-
return /* @__PURE__ */
|
|
3491
|
+
return /* @__PURE__ */ jsxs42(
|
|
3406
3492
|
BaseToast.Root,
|
|
3407
3493
|
{
|
|
3408
3494
|
toast,
|
|
3409
3495
|
swipeDirection: ["left", "down"],
|
|
3410
3496
|
className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
|
|
3411
3497
|
children: [
|
|
3412
|
-
/* @__PURE__ */
|
|
3413
|
-
leadingIcon && /* @__PURE__ */
|
|
3414
|
-
/* @__PURE__ */
|
|
3498
|
+
/* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3499
|
+
leadingIcon && /* @__PURE__ */ jsx59(LeadingIcon, { type }),
|
|
3500
|
+
/* @__PURE__ */ jsx59(BaseToast.Title, { render: /* @__PURE__ */ jsx59("span", {}), className: LABEL_CLASSES })
|
|
3415
3501
|
] }),
|
|
3416
|
-
actionLabel && /* @__PURE__ */
|
|
3502
|
+
actionLabel && /* @__PURE__ */ jsx59(
|
|
3417
3503
|
BaseToast.Action,
|
|
3418
3504
|
{
|
|
3419
3505
|
onClick: () => {
|
|
3420
3506
|
onAction?.();
|
|
3421
3507
|
close(toast.id);
|
|
3422
3508
|
},
|
|
3423
|
-
render: /* @__PURE__ */
|
|
3509
|
+
render: /* @__PURE__ */ jsx59(Button, { variant: "outlined", size: "small", children: actionLabel })
|
|
3424
3510
|
}
|
|
3425
3511
|
)
|
|
3426
3512
|
]
|
|
@@ -3434,6 +3520,19 @@ function useToast() {
|
|
|
3434
3520
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
3435
3521
|
return ctx;
|
|
3436
3522
|
}
|
|
3523
|
+
|
|
3524
|
+
// src/shortcuts.ts
|
|
3525
|
+
function isApplePlatform() {
|
|
3526
|
+
if (typeof navigator === "undefined") return false;
|
|
3527
|
+
return /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent || "");
|
|
3528
|
+
}
|
|
3529
|
+
function shortcutLabel(keys, apple = isApplePlatform()) {
|
|
3530
|
+
return keys.split("-").map((part, i, all) => {
|
|
3531
|
+
if (i === all.length - 1) return part.length === 1 ? part.toUpperCase() : part;
|
|
3532
|
+
if (part === "Mod") return apple ? "Cmd" : "Ctrl";
|
|
3533
|
+
return part;
|
|
3534
|
+
}).join("+");
|
|
3535
|
+
}
|
|
3437
3536
|
export {
|
|
3438
3537
|
AppShell,
|
|
3439
3538
|
AttachmentCard,
|
|
@@ -3506,6 +3605,7 @@ export {
|
|
|
3506
3605
|
SkeletonBar,
|
|
3507
3606
|
SkeletonList,
|
|
3508
3607
|
SkeletonRow,
|
|
3608
|
+
SuggestionMenu,
|
|
3509
3609
|
Tabs,
|
|
3510
3610
|
TextInput,
|
|
3511
3611
|
Textarea,
|
|
@@ -3524,7 +3624,9 @@ export {
|
|
|
3524
3624
|
hueFor,
|
|
3525
3625
|
initialsFor,
|
|
3526
3626
|
inlineChipClassName,
|
|
3627
|
+
isApplePlatform,
|
|
3527
3628
|
richTextClassName,
|
|
3629
|
+
shortcutLabel,
|
|
3528
3630
|
useToast
|
|
3529
3631
|
};
|
|
3530
3632
|
//# sourceMappingURL=index.js.map
|