@drakkar.software/octospaces-ui 0.4.0 → 0.4.2

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 ADDED
@@ -0,0 +1,34 @@
1
+ # Changelog — @drakkar.software/octospaces-ui
2
+
3
+ ## 0.4.2
4
+
5
+ ### `SpaceSwitcher` — `onTriggerPress` override
6
+
7
+ Added an optional `onTriggerPress?: () => void` prop to `SpaceSwitcher`.
8
+
9
+ When provided:
10
+ - The trigger button's `onPress` calls `onTriggerPress` instead of opening the
11
+ built-in dropdown.
12
+ - The chevron icon is hidden (the button no longer implies a picker).
13
+ - The `renderContainer` callback is never invoked.
14
+
15
+ Use this on surfaces where a dropdown is redundant (e.g. a desktop sidebar that
16
+ already has a rail for space switching) and a single tap to navigate to the
17
+ space-details page is the right UX.
18
+
19
+ Fully backward-compatible — existing consumers that do not pass `onTriggerPress`
20
+ retain identical behaviour.
21
+
22
+ ---
23
+
24
+ ## 0.4.1
25
+
26
+ - `Lightbox` component added (headless fullscreen media viewer + zoom).
27
+
28
+ ## 0.4.0
29
+
30
+ - `Sidebar`, `SidebarHeader`, `SidebarActionButton`, `SidebarItem` — shared
31
+ desktop sidebar panel shell and primitives.
32
+ - `SpaceSwitcher` — headless space picker trigger with `renderContainer` delegation.
33
+ - `sidebarPanel` added to `Palette` type (panel background distinct from rail
34
+ background `sidebar`).
package/dist/index.d.ts CHANGED
@@ -645,6 +645,133 @@ interface SidebarItemProps {
645
645
  }
646
646
  declare function SidebarItem({ label, icon, active, badge, onPress, onLongPress, trailing, indent, }: SidebarItemProps): React.JSX.Element;
647
647
 
648
+ /**
649
+ * Headless themed space-switcher component.
650
+ *
651
+ * Renders a trigger button (active-space avatar + name + chevron) that opens a
652
+ * dropdown listing all spaces with per-row selection, a "join or create" action,
653
+ * optional space settings, and an app-provided footer slot (account section, etc.).
654
+ *
655
+ * The popup container (Popover on desktop, Sheet on mobile) is fully delegated to
656
+ * the host via `renderContainer` so this package stays free of modal dependencies.
657
+ * Avatars and icons are delegated via render-props for the same reason.
658
+ *
659
+ * @example
660
+ * ```tsx
661
+ * // OctoVault — sidebar variant with Popover container
662
+ * <SpaceSwitcher
663
+ * spaces={spaces}
664
+ * activeId={activeId}
665
+ * onSelect={switchSpace}
666
+ * onAdd={() => router.push('/join')}
667
+ * onSettings={() => router.push(`/space/${activeId}`)}
668
+ * variant="sidebar"
669
+ * renderTriggerAvatar={(space, size) => (
670
+ * <Avatar label={space?.short ?? ''} image={space?.image} size={size} />
671
+ * )}
672
+ * renderSpaceAvatar={(space, size) => (
673
+ * <Avatar label={space.short ?? ''} image={space.image} size={size} />
674
+ * )}
675
+ * renderIcon={(name, size, color) => <Icon name={SWITCHER_ICON[name]} size={size} color={color} />}
676
+ * renderContainer={({ isOpen, onClose, anchorRef, children }) => (
677
+ * <>
678
+ * <Popover visible={isOpen} onClose={onClose} anchorRef={anchorRef} placement="bottom-start" width={240}>
679
+ * {children}
680
+ * </Popover>
681
+ * </>
682
+ * )}
683
+ * footerSlot={<AccountSwitcher onRequestClose={...} onViewProfile={...} />}
684
+ * />
685
+ * ```
686
+ */
687
+
688
+ /** Structural space item — no SDK dependency. */
689
+ interface SwitcherSpace {
690
+ id: string;
691
+ name: string;
692
+ /** 2-letter monogram used as avatar fallback. */
693
+ short?: string;
694
+ /** Uploaded space image URI; absent → host renders monogram. */
695
+ image?: string;
696
+ }
697
+ /** Icon name union for the switcher's built-in glyphs. */
698
+ type SwitcherIconName = 'chevron-down' | 'check' | 'plus' | 'gear';
699
+ interface SpaceSwitcherProps {
700
+ spaces: SwitcherSpace[];
701
+ activeId?: string | null;
702
+ /** Called when the user taps a space row. */
703
+ onSelect: (id: string) => void;
704
+ /** "Join or create a space" action. Omit to hide the row. */
705
+ onAdd?: () => void;
706
+ /** Override the add-row label. @default "Join or create a space" */
707
+ addLabel?: string;
708
+ /**
709
+ * "Space settings" action. Only shown when both `onSettings` and `activeId`
710
+ * are provided. Omit to hide.
711
+ */
712
+ onSettings?: () => void;
713
+ /** Override the settings-row label. @default "Space settings" */
714
+ settingsLabel?: string;
715
+ /**
716
+ * Visual variant:
717
+ * - `'sidebar'` — compact left-aligned trigger for the desktop sidebar header.
718
+ * - `'appbar'` — centered trigger for a phone app-bar title area.
719
+ */
720
+ variant: 'sidebar' | 'appbar';
721
+ /**
722
+ * Wraps the dropdown content in the host app's container (Popover / Sheet).
723
+ * Called with `{ isOpen, onClose, anchorRef, children }` — must render
724
+ * children inside an appropriate modal surface.
725
+ */
726
+ renderContainer: (props: {
727
+ isOpen: boolean;
728
+ onClose: () => void;
729
+ anchorRef: React.RefObject<View>;
730
+ children: React.ReactNode;
731
+ }) => React.ReactNode;
732
+ /**
733
+ * Render the active-space avatar inside the trigger button.
734
+ * Receives the active `SwitcherSpace` (or `null` when none) and a pixel size.
735
+ * Omit to render nothing in the avatar slot.
736
+ */
737
+ renderTriggerAvatar?: (space: SwitcherSpace | null, size: number) => React.ReactNode;
738
+ /**
739
+ * Render a space row's leading avatar.
740
+ * Receives the `SwitcherSpace` and a pixel size.
741
+ * Omit to render nothing in the leading slot.
742
+ */
743
+ renderSpaceAvatar?: (space: SwitcherSpace, size: number) => React.ReactNode;
744
+ /**
745
+ * Render an icon glyph. Name is one of `'chevron-down' | 'check' | 'plus' | 'gear'`.
746
+ * Omit to hide chevron, check, and action icons (spaces remain selectable).
747
+ */
748
+ renderIcon?: (name: SwitcherIconName, size: number, color: string) => React.ReactNode;
749
+ /**
750
+ * Footer rendered below the space list + action rows — use for account-switcher
751
+ * sections (with separator if needed). Fully app-owned.
752
+ */
753
+ footerSlot?: React.ReactNode;
754
+ /**
755
+ * When provided, replaces the default "open dropdown" behaviour on trigger press.
756
+ * The chevron is also hidden. Use this to navigate directly to a space-details
757
+ * page instead of opening a picker — e.g. on desktop where a rail handles
758
+ * switching and a dropdown is redundant.
759
+ *
760
+ * @example
761
+ * ```tsx
762
+ * // Navigate to space details instead of opening the picker (desktop sidebar)
763
+ * <SpaceSwitcher
764
+ * onTriggerPress={() => router.push(`/space/${activeId}`)}
765
+ * // renderContainer still required but never called when onTriggerPress is set
766
+ * renderContainer={() => null}
767
+ * ...
768
+ * />
769
+ * ```
770
+ */
771
+ onTriggerPress?: () => void;
772
+ }
773
+ declare function SpaceSwitcher({ spaces, activeId, onSelect, onAdd, addLabel, onSettings, settingsLabel, variant, renderContainer, renderTriggerAvatar, renderSpaceAvatar, renderIcon, footerSlot, onTriggerPress, }: SpaceSwitcherProps): React.JSX.Element;
774
+
648
775
  /**
649
776
  * Full-screen scrim overlay that centers its content. Tapping the backdrop, the
650
777
  * close button, the Escape key (web) or the hardware back (Android) dismisses it.
@@ -700,4 +827,4 @@ interface LightboxProps {
700
827
  */
701
828
  declare function Lightbox({ visible, onClose, children, closeLabel, renderCloseButton, renderActions, }: LightboxProps): React.JSX.Element;
702
829
 
703
- export { type ColorScheme, type DiscoverEntry, DiscoverList, type DiscoverListProps, DiscoverRow, type DiscoverRowProps, DiscoverScreen, type DiscoverScreenProps, type Easing, type Fonts, type LabelTracking, type Layers, type Layout, Lightbox, type LightboxProps, type Motion, type MotionToken, OctoSpacesThemeProvider, type OctoSpacesThemeProviderProps, type Opacity, type Palette, type Radii, type RailIconName, type RailSpace, type ShadowToken, type Shadows, Sidebar, SidebarActionButton, type SidebarActionButtonProps, SidebarHeader, type SidebarHeaderProps, SidebarItem, type SidebarItemProps, type SidebarProps, SpacesRail, type SpacesRailProps, type Spacing, type Swatches, type Theme, type TypeScale, type Typography, avatarTint, filterDiscoverEntries, focusRingStyle, glowShadow, paperBorder, presenceColor, sortDiscoverEntries, statusColor, swatch, useOctoSpacesTheme, verificationColor };
830
+ export { type ColorScheme, type DiscoverEntry, DiscoverList, type DiscoverListProps, DiscoverRow, type DiscoverRowProps, DiscoverScreen, type DiscoverScreenProps, type Easing, type Fonts, type LabelTracking, type Layers, type Layout, Lightbox, type LightboxProps, type Motion, type MotionToken, OctoSpacesThemeProvider, type OctoSpacesThemeProviderProps, type Opacity, type Palette, type Radii, type RailIconName, type RailSpace, type ShadowToken, type Shadows, Sidebar, SidebarActionButton, type SidebarActionButtonProps, SidebarHeader, type SidebarHeaderProps, SidebarItem, type SidebarItemProps, type SidebarProps, SpaceSwitcher, type SpaceSwitcherProps, SpacesRail, type SpacesRailProps, type Spacing, type Swatches, type SwitcherIconName, type SwitcherSpace, type Theme, type TypeScale, type Typography, avatarTint, filterDiscoverEntries, focusRingStyle, glowShadow, paperBorder, presenceColor, sortDiscoverEntries, statusColor, swatch, useOctoSpacesTheme, verificationColor };
package/dist/index.js CHANGED
@@ -1049,9 +1049,313 @@ var styles2 = StyleSheet2.create({
1049
1049
  iconSlot: { width: 18, alignItems: "center", justifyContent: "center" }
1050
1050
  });
1051
1051
 
1052
+ // src/sidebar/SpaceSwitcher.tsx
1053
+ import React10, { useRef as useRef2, useState as useState5 } from "react";
1054
+ import { Pressable as RNPressable4, StyleSheet as StyleSheet3, Text as Text6, View as View8 } from "react-native";
1055
+ var Pressable6 = RNPressable4;
1056
+ function SpaceSwitcher({
1057
+ spaces,
1058
+ activeId,
1059
+ onSelect,
1060
+ onAdd,
1061
+ addLabel = "Join or create a space",
1062
+ onSettings,
1063
+ settingsLabel = "Space settings",
1064
+ variant,
1065
+ renderContainer,
1066
+ renderTriggerAvatar,
1067
+ renderSpaceAvatar,
1068
+ renderIcon,
1069
+ footerSlot,
1070
+ onTriggerPress
1071
+ }) {
1072
+ const theme = useOctoSpacesTheme();
1073
+ const { colors, type: typeScale, fonts, spacing: sp, radii } = theme;
1074
+ const [open, setOpen] = useState5(false);
1075
+ const [triggerHovered, setTriggerHovered] = useState5(false);
1076
+ const anchorRef = useRef2(null);
1077
+ const active = spaces.find((s) => s.id === activeId) ?? spaces[0] ?? null;
1078
+ const close = () => setOpen(false);
1079
+ const handleSelect = (id) => {
1080
+ close();
1081
+ onSelect(id);
1082
+ };
1083
+ const handleAdd = () => {
1084
+ close();
1085
+ onAdd?.();
1086
+ };
1087
+ const handleSettings = () => {
1088
+ close();
1089
+ onSettings?.();
1090
+ };
1091
+ const sp1 = sp["1"] ?? 4;
1092
+ const sp2 = sp["2"] ?? 8;
1093
+ const sp3 = sp["3"] ?? 12;
1094
+ const sp4 = sp["4"] ?? 16;
1095
+ const radMd = radii["md"] ?? 6;
1096
+ const bodyFont = fonts["body"] ?? void 0;
1097
+ const bodySize = typeScale["callout"]?.size ?? 13;
1098
+ const bodyLine = typeScale["callout"]?.lineHeight ?? 18;
1099
+ const labelSize = typeScale["caption"]?.size ?? 11;
1100
+ const labelLine = typeScale["caption"]?.lineHeight ?? 16;
1101
+ const triggerStyle = variant === "sidebar" ? {
1102
+ flex: 1,
1103
+ flexDirection: "row",
1104
+ alignItems: "center",
1105
+ gap: sp2,
1106
+ paddingHorizontal: sp2,
1107
+ paddingVertical: sp1 + 2,
1108
+ borderRadius: radMd,
1109
+ minWidth: 0,
1110
+ backgroundColor: triggerHovered ? colors.primarySubtle ?? "rgba(0,0,0,0.05)" : "transparent"
1111
+ } : {
1112
+ flexDirection: "row",
1113
+ alignItems: "center",
1114
+ justifyContent: "center",
1115
+ gap: sp2,
1116
+ paddingHorizontal: sp2,
1117
+ paddingVertical: sp1,
1118
+ borderRadius: radMd,
1119
+ backgroundColor: triggerHovered ? colors.primarySubtle ?? "rgba(0,0,0,0.05)" : "transparent"
1120
+ };
1121
+ const dropdownContent = /* @__PURE__ */ React10.createElement(View8, { style: { paddingVertical: sp1 } }, spaces.length > 0 ? /* @__PURE__ */ React10.createElement(
1122
+ SectionLabel,
1123
+ {
1124
+ label: "Spaces",
1125
+ color: colors.textTertiary,
1126
+ size: labelSize,
1127
+ lineHeight: labelLine,
1128
+ font: bodyFont,
1129
+ paddingH: sp4,
1130
+ paddingV: sp1
1131
+ }
1132
+ ) : null, spaces.map((s) => /* @__PURE__ */ React10.createElement(
1133
+ SpaceRow,
1134
+ {
1135
+ key: s.id,
1136
+ space: s,
1137
+ active: s.id === (active?.id ?? null),
1138
+ onPress: () => handleSelect(s.id),
1139
+ renderAvatar: renderSpaceAvatar,
1140
+ renderIcon,
1141
+ colors,
1142
+ bodyFont,
1143
+ bodySize,
1144
+ bodyLine,
1145
+ sp2,
1146
+ sp3,
1147
+ sp4,
1148
+ radMd
1149
+ }
1150
+ )), onAdd ? /* @__PURE__ */ React10.createElement(
1151
+ ActionRow,
1152
+ {
1153
+ label: spaces.length > 0 ? addLabel : "Create your first space",
1154
+ iconName: "plus",
1155
+ onPress: handleAdd,
1156
+ renderIcon,
1157
+ colors,
1158
+ bodyFont,
1159
+ bodySize,
1160
+ bodyLine,
1161
+ sp2,
1162
+ sp3,
1163
+ sp4,
1164
+ radMd
1165
+ }
1166
+ ) : null, onSettings && active ? /* @__PURE__ */ React10.createElement(
1167
+ ActionRow,
1168
+ {
1169
+ label: settingsLabel,
1170
+ iconName: "gear",
1171
+ onPress: handleSettings,
1172
+ renderIcon,
1173
+ colors,
1174
+ bodyFont,
1175
+ bodySize,
1176
+ bodyLine,
1177
+ sp2,
1178
+ sp3,
1179
+ sp4,
1180
+ radMd
1181
+ }
1182
+ ) : null, footerSlot != null ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
1183
+ View8,
1184
+ {
1185
+ style: {
1186
+ height: StyleSheet3.hairlineWidth,
1187
+ backgroundColor: colors.borderSubtle,
1188
+ marginVertical: sp1,
1189
+ marginHorizontal: sp2
1190
+ }
1191
+ }
1192
+ ), footerSlot) : null);
1193
+ return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
1194
+ Pressable6,
1195
+ {
1196
+ ref: anchorRef,
1197
+ accessibilityRole: "button",
1198
+ accessibilityLabel: active ? `${active.name} \u2014 switch space` : "Switch space",
1199
+ accessibilityState: { expanded: open },
1200
+ hitSlop: 6,
1201
+ onPress: onTriggerPress ?? (() => setOpen(true)),
1202
+ onMouseEnter: () => setTriggerHovered(true),
1203
+ onMouseLeave: () => setTriggerHovered(false),
1204
+ style: triggerStyle
1205
+ },
1206
+ renderTriggerAvatar ? renderTriggerAvatar(active, 22) : null,
1207
+ /* @__PURE__ */ React10.createElement(
1208
+ Text6,
1209
+ {
1210
+ numberOfLines: 1,
1211
+ style: {
1212
+ flex: variant === "sidebar" ? 1 : void 0,
1213
+ minWidth: 0,
1214
+ flexShrink: 1,
1215
+ fontSize: typeScale["heading"]?.size ?? 15,
1216
+ lineHeight: typeScale["heading"]?.lineHeight ?? 20,
1217
+ fontWeight: "600",
1218
+ color: colors.text,
1219
+ fontFamily: bodyFont
1220
+ }
1221
+ },
1222
+ active?.name ?? "Spaces"
1223
+ ),
1224
+ !onTriggerPress && renderIcon ? renderIcon("chevron-down", 14, colors.textTertiary) : null
1225
+ ), onTriggerPress ? null : renderContainer({ isOpen: open, onClose: close, anchorRef, children: dropdownContent }));
1226
+ }
1227
+ function SectionLabel({ label, color, size, lineHeight, font, paddingH, paddingV }) {
1228
+ return /* @__PURE__ */ React10.createElement(
1229
+ Text6,
1230
+ {
1231
+ style: {
1232
+ fontSize: size,
1233
+ lineHeight,
1234
+ fontWeight: "600",
1235
+ color,
1236
+ fontFamily: font,
1237
+ textTransform: "uppercase",
1238
+ letterSpacing: 0.5,
1239
+ paddingHorizontal: paddingH,
1240
+ paddingVertical: paddingV
1241
+ }
1242
+ },
1243
+ label
1244
+ );
1245
+ }
1246
+ function SpaceRow({
1247
+ space,
1248
+ active,
1249
+ onPress,
1250
+ renderAvatar,
1251
+ renderIcon,
1252
+ colors,
1253
+ bodyFont,
1254
+ bodySize,
1255
+ bodyLine,
1256
+ sp2,
1257
+ sp3,
1258
+ sp4,
1259
+ radMd
1260
+ }) {
1261
+ const [hovered, setHovered] = useState5(false);
1262
+ const bg = hovered ? colors.primarySubtle ?? "rgba(0,0,0,0.04)" : "transparent";
1263
+ return /* @__PURE__ */ React10.createElement(
1264
+ Pressable6,
1265
+ {
1266
+ accessibilityRole: "menuitem",
1267
+ accessibilityLabel: active ? `${space.name} (current)` : `Switch to ${space.name}`,
1268
+ accessibilityState: { selected: active },
1269
+ onPress,
1270
+ onMouseEnter: () => setHovered(true),
1271
+ onMouseLeave: () => setHovered(false),
1272
+ style: {
1273
+ flexDirection: "row",
1274
+ alignItems: "center",
1275
+ gap: sp3,
1276
+ paddingHorizontal: sp4,
1277
+ paddingVertical: sp2,
1278
+ borderRadius: radMd,
1279
+ backgroundColor: bg
1280
+ }
1281
+ },
1282
+ renderAvatar ? renderAvatar(space, 24) : null,
1283
+ /* @__PURE__ */ React10.createElement(
1284
+ Text6,
1285
+ {
1286
+ numberOfLines: 1,
1287
+ style: {
1288
+ flex: 1,
1289
+ minWidth: 0,
1290
+ fontSize: bodySize,
1291
+ lineHeight: bodyLine,
1292
+ fontWeight: active ? "600" : "400",
1293
+ color: active ? colors.primary : colors.text,
1294
+ fontFamily: bodyFont
1295
+ }
1296
+ },
1297
+ space.name
1298
+ ),
1299
+ active && renderIcon ? renderIcon("check", 15, colors.primary) : null
1300
+ );
1301
+ }
1302
+ function ActionRow({
1303
+ label,
1304
+ iconName,
1305
+ onPress,
1306
+ renderIcon,
1307
+ colors,
1308
+ bodyFont,
1309
+ bodySize,
1310
+ bodyLine,
1311
+ sp2,
1312
+ sp3,
1313
+ sp4,
1314
+ radMd
1315
+ }) {
1316
+ const [hovered, setHovered] = useState5(false);
1317
+ const bg = hovered ? colors.primarySubtle ?? "rgba(0,0,0,0.04)" : "transparent";
1318
+ return /* @__PURE__ */ React10.createElement(
1319
+ Pressable6,
1320
+ {
1321
+ accessibilityRole: "menuitem",
1322
+ accessibilityLabel: label,
1323
+ onPress,
1324
+ onMouseEnter: () => setHovered(true),
1325
+ onMouseLeave: () => setHovered(false),
1326
+ style: {
1327
+ flexDirection: "row",
1328
+ alignItems: "center",
1329
+ gap: sp3,
1330
+ paddingHorizontal: sp4,
1331
+ paddingVertical: sp2,
1332
+ borderRadius: radMd,
1333
+ backgroundColor: bg
1334
+ }
1335
+ },
1336
+ renderIcon ? /* @__PURE__ */ React10.createElement(View8, { style: { width: 24, alignItems: "center", justifyContent: "center" } }, renderIcon(iconName, 15, colors.textSecondary)) : null,
1337
+ /* @__PURE__ */ React10.createElement(
1338
+ Text6,
1339
+ {
1340
+ numberOfLines: 1,
1341
+ style: {
1342
+ flex: 1,
1343
+ minWidth: 0,
1344
+ fontSize: bodySize,
1345
+ lineHeight: bodyLine,
1346
+ fontWeight: "400",
1347
+ color: colors.text,
1348
+ fontFamily: bodyFont
1349
+ }
1350
+ },
1351
+ label
1352
+ )
1353
+ );
1354
+ }
1355
+
1052
1356
  // src/lightbox/Lightbox.tsx
1053
- import React10, { useEffect as useEffect2 } from "react";
1054
- import { Modal, Platform, Pressable as Pressable6, View as View8 } from "react-native";
1357
+ import React11, { useEffect as useEffect2 } from "react";
1358
+ import { Modal, Platform, Pressable as Pressable7, View as View9 } from "react-native";
1055
1359
  function Lightbox({
1056
1360
  visible,
1057
1361
  onClose,
@@ -1072,7 +1376,7 @@ function Lightbox({
1072
1376
  const pad = theme.spacing["6"] ?? 24;
1073
1377
  const insetV = theme.spacing["8"] ?? 32;
1074
1378
  const insetH = theme.spacing["4"] ?? 16;
1075
- return /* @__PURE__ */ React10.createElement(
1379
+ return /* @__PURE__ */ React11.createElement(
1076
1380
  Modal,
1077
1381
  {
1078
1382
  visible,
@@ -1081,8 +1385,8 @@ function Lightbox({
1081
1385
  onRequestClose: onClose,
1082
1386
  statusBarTranslucent: true
1083
1387
  },
1084
- /* @__PURE__ */ React10.createElement(
1085
- Pressable6,
1388
+ /* @__PURE__ */ React11.createElement(
1389
+ Pressable7,
1086
1390
  {
1087
1391
  style: {
1088
1392
  flex: 1,
@@ -1094,16 +1398,16 @@ function Lightbox({
1094
1398
  onPress: onClose,
1095
1399
  accessibilityLabel: closeLabel
1096
1400
  },
1097
- /* @__PURE__ */ React10.createElement(
1098
- View8,
1401
+ /* @__PURE__ */ React11.createElement(
1402
+ View9,
1099
1403
  {
1100
1404
  style: { alignItems: "center", justifyContent: "center" },
1101
1405
  pointerEvents: "box-none"
1102
1406
  },
1103
1407
  children
1104
1408
  ),
1105
- renderCloseButton ? /* @__PURE__ */ React10.createElement(View8, { style: { position: "absolute", top: insetV, right: insetH } }, renderCloseButton(onClose)) : null,
1106
- renderActions ? /* @__PURE__ */ React10.createElement(View8, { style: { position: "absolute", bottom: insetV, right: insetH } }, renderActions()) : null
1409
+ renderCloseButton ? /* @__PURE__ */ React11.createElement(View9, { style: { position: "absolute", top: insetV, right: insetH } }, renderCloseButton(onClose)) : null,
1410
+ renderActions ? /* @__PURE__ */ React11.createElement(View9, { style: { position: "absolute", bottom: insetV, right: insetH } }, renderActions()) : null
1107
1411
  )
1108
1412
  );
1109
1413
  }
@@ -1117,6 +1421,7 @@ export {
1117
1421
  SidebarActionButton,
1118
1422
  SidebarHeader,
1119
1423
  SidebarItem,
1424
+ SpaceSwitcher,
1120
1425
  SpacesRail,
1121
1426
  avatarTint,
1122
1427
  filterDiscoverEntries,