@arbidocs/blocks 0.4.4 → 0.4.6
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/README.md +71 -6
- package/dist/agents/index.cjs +163 -162
- package/dist/agents/index.js +6 -5
- package/dist/artifacts/ArtifactCompareBar.d.ts +33 -0
- package/dist/artifacts/ArtifactEditor.d.ts +64 -0
- package/dist/artifacts/ArtifactEditorBody.d.ts +34 -0
- package/dist/artifacts/ArtifactRedlineView.d.ts +57 -0
- package/dist/artifacts/ArtifactToolbar.d.ts +53 -0
- package/dist/artifacts/ArtifactVersionBar.d.ts +42 -0
- package/dist/{files → artifacts}/RedlineParts.d.ts +4 -0
- package/dist/artifacts/editor/ArtifactMarkdownEditor.d.ts +39 -0
- package/dist/artifacts/editor/index.cjs +89 -0
- package/dist/artifacts/editor/index.cjs.map +1 -0
- package/dist/artifacts/editor/index.d.ts +1 -0
- package/dist/artifacts/editor/index.js +86 -0
- package/dist/artifacts/editor/index.js.map +1 -0
- package/dist/artifacts/index.cjs +807 -0
- package/dist/artifacts/index.cjs.map +1 -0
- package/dist/artifacts/index.d.ts +8 -0
- package/dist/artifacts/index.js +787 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/chat/ChatMessageContent.d.ts +16 -0
- package/dist/chat/ChatPage.d.ts +11 -8
- package/dist/chat/ChatThreads.d.ts +3 -1
- package/dist/chat/CitationMark.d.ts +18 -0
- package/dist/chat/chat-page-types.d.ts +75 -1
- package/dist/chat/index.cjs +125 -116
- package/dist/chat/index.d.ts +3 -1
- package/dist/chat/index.js +4 -3
- package/dist/{chunk-XKKGGUU2.cjs → chunk-23XL6SVZ.cjs} +39 -19
- package/dist/chunk-23XL6SVZ.cjs.map +1 -0
- package/dist/{chunk-ULWRNGGE.cjs → chunk-2ZTONLT5.cjs} +4 -25
- package/dist/chunk-2ZTONLT5.cjs.map +1 -0
- package/dist/{chunk-O637DUKS.cjs → chunk-56BUD74K.cjs} +28 -28
- package/dist/{chunk-O637DUKS.cjs.map → chunk-56BUD74K.cjs.map} +1 -1
- package/dist/{chunk-ATXPAD6S.cjs → chunk-5SLLMK5K.cjs} +420 -114
- package/dist/chunk-5SLLMK5K.cjs.map +1 -0
- package/dist/{chunk-SS23F63U.cjs → chunk-5ZBP7TCD.cjs} +55 -3
- package/dist/chunk-5ZBP7TCD.cjs.map +1 -0
- package/dist/{chunk-DGVKBOY5.cjs → chunk-67HGXV4I.cjs} +6 -6
- package/dist/{chunk-DGVKBOY5.cjs.map → chunk-67HGXV4I.cjs.map} +1 -1
- package/dist/{chunk-RCP6THBS.js → chunk-7OCFHEE6.js} +3 -3
- package/dist/{chunk-RCP6THBS.js.map → chunk-7OCFHEE6.js.map} +1 -1
- package/dist/{chunk-TX2ZICS7.js → chunk-CPMNAJLF.js} +4 -24
- package/dist/chunk-CPMNAJLF.js.map +1 -0
- package/dist/{chunk-BBEMPS6C.js → chunk-CVFBSUXL.js} +5 -5
- package/dist/{chunk-BBEMPS6C.js.map → chunk-CVFBSUXL.js.map} +1 -1
- package/dist/chunk-DCDVWPMB.cjs +29 -0
- package/dist/chunk-DCDVWPMB.cjs.map +1 -0
- package/dist/{chunk-TI4UTYRL.js → chunk-EY2RJW27.js} +258 -10
- package/dist/chunk-EY2RJW27.js.map +1 -0
- package/dist/{chunk-7YADKWZT.js → chunk-G2E3O3HI.js} +3 -3
- package/dist/{chunk-7YADKWZT.js.map → chunk-G2E3O3HI.js.map} +1 -1
- package/dist/{chunk-JPO3F4J7.js → chunk-G2T3KTZ3.js} +418 -114
- package/dist/chunk-G2T3KTZ3.js.map +1 -0
- package/dist/{chunk-2NNTQLBY.js → chunk-IAKUTBPX.js} +4 -4
- package/dist/{chunk-2NNTQLBY.js.map → chunk-IAKUTBPX.js.map} +1 -1
- package/dist/{chunk-IZHWP6WQ.cjs → chunk-JG4TFS3Z.cjs} +6 -6
- package/dist/{chunk-IZHWP6WQ.cjs.map → chunk-JG4TFS3Z.cjs.map} +1 -1
- package/dist/chunk-JLOYWXRB.js +1156 -0
- package/dist/chunk-JLOYWXRB.js.map +1 -0
- package/dist/{chunk-WJZBJUPX.js → chunk-KXMDOTGW.js} +56 -4
- package/dist/chunk-KXMDOTGW.js.map +1 -0
- package/dist/{chunk-2VBJ763Y.js → chunk-KZJAG7T3.js} +37 -7
- package/dist/chunk-KZJAG7T3.js.map +1 -0
- package/dist/{chunk-RIL7G7AS.cjs → chunk-MGUHR3JI.cjs} +4 -4
- package/dist/{chunk-RIL7G7AS.cjs.map → chunk-MGUHR3JI.cjs.map} +1 -1
- package/dist/{chunk-DN3NFNIA.cjs → chunk-QMDLPO3M.cjs} +266 -10
- package/dist/chunk-QMDLPO3M.cjs.map +1 -0
- package/dist/chunk-TJMKFY5P.js +27 -0
- package/dist/chunk-TJMKFY5P.js.map +1 -0
- package/dist/{chunk-B673CCW5.js → chunk-UHVNYKV2.js} +38 -18
- package/dist/chunk-UHVNYKV2.js.map +1 -0
- package/dist/{chunk-6CHMNKXC.cjs → chunk-UTYQPVIW.cjs} +11 -11
- package/dist/chunk-UTYQPVIW.cjs.map +1 -0
- package/dist/{chunk-KHX2BX3S.cjs → chunk-VGOFFCMT.cjs} +37 -5
- package/dist/chunk-VGOFFCMT.cjs.map +1 -0
- package/dist/{chunk-67MKU5U7.js → chunk-YMHGF6R5.js} +8 -8
- package/dist/chunk-YMHGF6R5.js.map +1 -0
- package/dist/chunk-YVIOCITQ.cjs +1186 -0
- package/dist/chunk-YVIOCITQ.cjs.map +1 -0
- package/dist/collaboration/index.cjs +38 -37
- package/dist/collaboration/index.js +3 -2
- package/dist/connect/index.cjs +358 -19
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +341 -9
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedSettings.d.ts +64 -0
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/ViewerChrome.d.ts +0 -45
- package/dist/files/ViewerParts.d.ts +0 -19
- package/dist/files/index.cjs +15 -446
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.d.ts +2 -4
- package/dist/files/index.js +9 -428
- package/dist/files/index.js.map +1 -1
- package/dist/home/index.cjs +1 -1
- package/dist/home/index.js +1 -1
- package/dist/index.cjs +634 -585
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/lib/bottom-inset.d.ts +16 -0
- package/dist/lib/useElementSize.d.ts +13 -0
- package/dist/lib/useFillHeight.d.ts +10 -0
- package/dist/settings/account-views.d.ts +55 -0
- package/dist/settings/index.cjs +178 -1147
- package/dist/settings/index.cjs.map +1 -1
- package/dist/settings/index.d.ts +1 -0
- package/dist/settings/index.js +9 -1072
- package/dist/settings/index.js.map +1 -1
- package/dist/shell/InstallPrompt.d.ts +28 -0
- package/dist/shell/MobileBars.d.ts +1 -1
- package/dist/shell/index.cjs +92 -52
- package/dist/shell/index.d.ts +4 -0
- package/dist/shell/index.js +4 -4
- package/dist/shell/install-instructions.d.ts +19 -0
- package/dist/shell/types.d.ts +6 -0
- package/dist/shell/use-install-prompt.d.ts +49 -0
- package/dist/site/index.cjs +67 -67
- package/dist/site/index.js +3 -3
- package/dist/studio/index.cjs +79 -78
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.js +9 -8
- package/dist/studio/index.js.map +1 -1
- package/dist/theme/ThemeEditor.d.ts +4 -2
- package/dist/workspaces/index.cjs +4 -3
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.js +3 -2
- package/dist/workspaces/index.js.map +1 -1
- package/package.json +30 -5
- package/src/blocks.css +30 -0
- package/dist/chunk-2VBJ763Y.js.map +0 -1
- package/dist/chunk-67MKU5U7.js.map +0 -1
- package/dist/chunk-6CHMNKXC.cjs.map +0 -1
- package/dist/chunk-ATXPAD6S.cjs.map +0 -1
- package/dist/chunk-B673CCW5.js.map +0 -1
- package/dist/chunk-DN3NFNIA.cjs.map +0 -1
- package/dist/chunk-JPO3F4J7.js.map +0 -1
- package/dist/chunk-KHX2BX3S.cjs.map +0 -1
- package/dist/chunk-SS23F63U.cjs.map +0 -1
- package/dist/chunk-TI4UTYRL.js.map +0 -1
- package/dist/chunk-TX2ZICS7.js.map +0 -1
- package/dist/chunk-ULWRNGGE.cjs.map +0 -1
- package/dist/chunk-WJZBJUPX.js.map +0 -1
- package/dist/chunk-XKKGGUU2.cjs.map +0 -1
- /package/dist/{files → artifacts}/VersionTimeline.d.ts +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
|
|
6
|
+
// src/lib/useRestoreFocus.ts
|
|
7
|
+
function useRestoreFocus() {
|
|
8
|
+
const origin = react.useRef(null);
|
|
9
|
+
return react.useMemo(
|
|
10
|
+
() => ({
|
|
11
|
+
onOpenAutoFocus: () => {
|
|
12
|
+
origin.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
13
|
+
},
|
|
14
|
+
onCloseAutoFocus: (event) => {
|
|
15
|
+
const element = origin.current;
|
|
16
|
+
origin.current = null;
|
|
17
|
+
if (element && element.isConnected && element !== document.body) {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
element.focus();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
[]
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.useRestoreFocus = useRestoreFocus;
|
|
28
|
+
//# sourceMappingURL=chunk-DCDVWPMB.cjs.map
|
|
29
|
+
//# sourceMappingURL=chunk-DCDVWPMB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/useRestoreFocus.ts"],"names":["useRef","useMemo"],"mappings":";;;;;AASO,SAAS,eAAA,GAGd;AACA,EAAA,MAAM,MAAA,GAASA,aAA2B,IAAI,CAAA;AAC9C,EAAA,OAAOC,aAAA;AAAA,IACL,OAAO;AAAA,MACL,iBAAiB,MAAM;AAErB,QAAA,MAAA,CAAO,OAAA,GACL,QAAA,CAAS,aAAA,YAAyB,WAAA,GAAc,SAAS,aAAA,GAAgB,IAAA;AAAA,MAC7E,CAAA;AAAA,MACA,gBAAA,EAAkB,CAAC,KAAA,KAAiB;AAClC,QAAA,MAAM,UAAU,MAAA,CAAO,OAAA;AACvB,QAAA,MAAA,CAAO,OAAA,GAAU,IAAA;AACjB,QAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,WAAA,IAAe,OAAA,KAAY,SAAS,IAAA,EAAM;AAC/D,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,QAChB;AAAA,MACF;AAAA,KACF,CAAA;AAAA,IACA;AAAC,GACH;AACF","file":"chunk-DCDVWPMB.cjs","sourcesContent":["import { useMemo, useRef } from 'react'\n\n/**\n * Props for a Radix `DialogContent` that put focus back where it was when the dialog opened.\n *\n * Radix Dialog returns focus to its `Trigger` on close and, when the dialog is opened from state\n * (no `DialogTrigger`, as every controlled dialog in the blocks is), drops it to `<body>`:\n * a keyboard or screen-reader user loses their place. Spread the result on `DialogContent`.\n */\nexport function useRestoreFocus(): {\n onOpenAutoFocus: (event: Event) => void\n onCloseAutoFocus: (event: Event) => void\n} {\n const origin = useRef<HTMLElement | null>(null)\n return useMemo(\n () => ({\n onOpenAutoFocus: () => {\n // Runs before the dialog moves focus inside, so this is still the opener.\n origin.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null\n },\n onCloseAutoFocus: (event: Event) => {\n const element = origin.current\n origin.current = null\n if (element && element.isConnected && element !== document.body) {\n event.preventDefault()\n element.focus()\n }\n },\n }),\n []\n )\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { ActionLink } from './chunk-S7PSMMRG.js';
|
|
3
|
-
import { useDrawerBehavior, BlocksTooltipProvider } from './chunk-
|
|
3
|
+
import { useDrawerBehavior, BlocksTooltipProvider, useShellBottomInset } from './chunk-KZJAG7T3.js';
|
|
4
4
|
import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
|
|
5
|
-
import { createContext, forwardRef, useContext, useMemo, useRef, useState,
|
|
6
|
-
import { PanelLeftClose, PanelLeftOpen, X, Globe, Users, Lock, ChevronDown, LayoutGrid, Plus, Sparkles, Search, ArrowUp, Menu, TriangleAlert, CheckCircle2, Loader2, RefreshCw, WifiOff, MousePointerClick, Lightbulb, Pencil, ChevronLeft, ChevronRight, Info } from 'lucide-react';
|
|
5
|
+
import { createContext, forwardRef, useContext, useMemo, useRef, useState, useEffect, useCallback, useId } from 'react';
|
|
6
|
+
import { PanelLeftClose, PanelLeftOpen, X, Globe, Users, Lock, ChevronDown, LayoutGrid, Plus, Sparkles, Search, ArrowUp, Menu, Download, TriangleAlert, CheckCircle2, Loader2, RefreshCw, WifiOff, MousePointerClick, Lightbulb, Pencil, ChevronLeft, ChevronRight, Info } from 'lucide-react';
|
|
7
7
|
import { cn, Tooltip, TooltipTrigger, TooltipContent, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel, Button } from '@arbidocs/react/ui';
|
|
8
8
|
export { UserMenu } from '@arbidocs/react/ui';
|
|
9
9
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -119,7 +119,7 @@ function SidebarRoot({
|
|
|
119
119
|
useDrawerBehavior(isDrawer, onBackdropClick ?? noop, drawerRef);
|
|
120
120
|
const ariaLabel = ariaLabelProp ?? mergedLabels.mainNavigation;
|
|
121
121
|
const contextValue = useMemo(() => ({ expanded, labels: mergedLabels }), [expanded, mergedLabels]);
|
|
122
|
-
const navBase = "group/sidebar bg-sidebar border-r border-border text-foreground flex flex-col h-full overflow-y-auto overflow-x-hidden pb-safe pt-3 transition-all duration-300 ease-in-out";
|
|
122
|
+
const navBase = "group/sidebar bg-sidebar border-r border-border text-foreground scrollbar-themed flex flex-col h-full overflow-y-auto overflow-x-hidden pb-safe pt-3 transition-all duration-300 ease-in-out";
|
|
123
123
|
const common = {
|
|
124
124
|
"aria-label": ariaLabel,
|
|
125
125
|
"data-testid": testIdOr(testId, { testId: "sidebar" }),
|
|
@@ -1055,6 +1055,15 @@ function MobileAppBar({
|
|
|
1055
1055
|
}
|
|
1056
1056
|
);
|
|
1057
1057
|
}
|
|
1058
|
+
function TabLabel({ item }) {
|
|
1059
|
+
const wrap = "max-w-full text-balance px-0.5 text-center [overflow-wrap:normal] @max-[4.5rem]:text-[10px]";
|
|
1060
|
+
if (!item.shortLabel) return /* @__PURE__ */ jsx("span", { className: wrap, children: item.label });
|
|
1061
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1062
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "tab-short-label", "aria-hidden": "true", className: cn(wrap, "@[5.5rem]:hidden"), children: item.shortLabel }),
|
|
1063
|
+
/* @__PURE__ */ jsx("span", { className: cn(wrap, "hidden @[5.5rem]:block"), children: item.label }),
|
|
1064
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only @[5.5rem]:hidden", children: item.label })
|
|
1065
|
+
] });
|
|
1066
|
+
}
|
|
1058
1067
|
function MobileTabBar({
|
|
1059
1068
|
items,
|
|
1060
1069
|
label,
|
|
@@ -1063,14 +1072,17 @@ function MobileTabBar({
|
|
|
1063
1072
|
className,
|
|
1064
1073
|
"data-testid": testId
|
|
1065
1074
|
}) {
|
|
1075
|
+
const navRef = useRef(null);
|
|
1076
|
+
useShellBottomInset(navRef);
|
|
1066
1077
|
return /* @__PURE__ */ jsx(
|
|
1067
1078
|
"nav",
|
|
1068
1079
|
{
|
|
1080
|
+
ref: navRef,
|
|
1069
1081
|
"aria-label": label ?? labels?.workspaceSections ?? DEFAULT_MOBILE_BARS_LABELS.workspaceSections,
|
|
1070
1082
|
"data-slot": "mobile-tab-bar",
|
|
1071
1083
|
"data-testid": testIdOr(testId, { testId: "mobile-tab-bar" }),
|
|
1072
1084
|
className: cn(
|
|
1073
|
-
"flex h-16 flex-shrink-0 items-stretch bg-sidebar px-2 pb-safe sm:hidden",
|
|
1085
|
+
"flex min-h-16 flex-shrink-0 items-stretch bg-sidebar px-2 pb-safe sm:hidden",
|
|
1074
1086
|
className
|
|
1075
1087
|
),
|
|
1076
1088
|
children: items.map((item) => /* @__PURE__ */ jsxs(
|
|
@@ -1081,13 +1093,14 @@ function MobileTabBar({
|
|
|
1081
1093
|
disabled: item.disabled,
|
|
1082
1094
|
"aria-current": item.active ? "page" : void 0,
|
|
1083
1095
|
className: cn(
|
|
1084
|
-
|
|
1096
|
+
// Each tab is a size container: a `shortLabel` replaces the label when it is narrow.
|
|
1097
|
+
"@container flex min-h-12 min-w-0 flex-1 flex-col items-center justify-center gap-0.5 rounded-md text-[11px] leading-tight transition-colors",
|
|
1085
1098
|
item.active ? "font-semibold text-primary" : "font-medium text-muted-foreground hover:text-foreground"
|
|
1086
1099
|
),
|
|
1087
1100
|
"data-testid": prefixedTestId(testIdPrefix, item.id, { testId: `mobile-tab-${item.id}` }),
|
|
1088
1101
|
children: [
|
|
1089
1102
|
item.icon,
|
|
1090
|
-
/* @__PURE__ */ jsx(
|
|
1103
|
+
/* @__PURE__ */ jsx(TabLabel, { item })
|
|
1091
1104
|
]
|
|
1092
1105
|
},
|
|
1093
1106
|
item.id
|
|
@@ -1095,6 +1108,241 @@ function MobileTabBar({
|
|
|
1095
1108
|
}
|
|
1096
1109
|
);
|
|
1097
1110
|
}
|
|
1111
|
+
|
|
1112
|
+
// src/shell/install-instructions.ts
|
|
1113
|
+
function isIosDevice() {
|
|
1114
|
+
if (typeof navigator === "undefined") return false;
|
|
1115
|
+
return /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
1116
|
+
}
|
|
1117
|
+
function getInstallInstructions({
|
|
1118
|
+
appName = "this app"
|
|
1119
|
+
} = {}) {
|
|
1120
|
+
if (typeof navigator === "undefined" || typeof window === "undefined") {
|
|
1121
|
+
return {
|
|
1122
|
+
heading: `Install ${appName}`,
|
|
1123
|
+
steps: [`Open ${appName} in Chrome, Edge, or Safari to install it.`]
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
const ua = navigator.userAgent;
|
|
1127
|
+
const isChromium = "onbeforeinstallprompt" in window;
|
|
1128
|
+
const isFirefox = /firefox|fxios/i.test(ua);
|
|
1129
|
+
const isMac = /Macintosh|Mac OS X/.test(ua);
|
|
1130
|
+
if (isIosDevice()) {
|
|
1131
|
+
return {
|
|
1132
|
+
heading: "Install on iPhone or iPad",
|
|
1133
|
+
steps: [
|
|
1134
|
+
`Open ${appName} in Safari, then tap the Share button.`,
|
|
1135
|
+
"Scroll down and tap \u201CAdd to Home Screen\u201D.",
|
|
1136
|
+
`Tap \u201CAdd\u201D: ${appName} appears on your home screen.`
|
|
1137
|
+
]
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
if (isChromium) {
|
|
1141
|
+
return {
|
|
1142
|
+
heading: `Install ${appName}`,
|
|
1143
|
+
steps: [
|
|
1144
|
+
"Click the install icon at the right of the address bar (a small monitor with a down arrow).",
|
|
1145
|
+
"Choose \u201CInstall\u201D in the dialog that appears."
|
|
1146
|
+
],
|
|
1147
|
+
note: `On a phone, open the browser menu and choose \u201CInstall app\u201D / \u201CAdd to Home screen\u201D. If you don\u2019t see the option, ${appName} may already be installed.`
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
if (isMac && !isFirefox) {
|
|
1151
|
+
return {
|
|
1152
|
+
heading: "Install on macOS Safari",
|
|
1153
|
+
steps: ["In the menu bar, open the File menu.", "Choose \u201CAdd to Dock\u201D."],
|
|
1154
|
+
note: "Requires Safari 17 or later (macOS Sonoma). On older Safari, use Chrome or Edge to install."
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
if (isFirefox) {
|
|
1158
|
+
return {
|
|
1159
|
+
heading: "Firefox can\u2019t install web apps",
|
|
1160
|
+
steps: [`Open ${appName} in Chrome, Edge, or Safari to install it as an app.`]
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
return {
|
|
1164
|
+
heading: `Install ${appName}`,
|
|
1165
|
+
steps: [
|
|
1166
|
+
"Look for an \u201CInstall\u201D or \u201CAdd to Home Screen\u201D option in your browser\u2019s menu or address bar."
|
|
1167
|
+
]
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// src/shell/use-install-prompt.ts
|
|
1172
|
+
var deferredPrompt = null;
|
|
1173
|
+
var installed = false;
|
|
1174
|
+
var initialized = false;
|
|
1175
|
+
var autoPromptParam = null;
|
|
1176
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
1177
|
+
var notify = () => subscribers.forEach((fn) => fn());
|
|
1178
|
+
function isStandalone() {
|
|
1179
|
+
if (typeof window === "undefined") return false;
|
|
1180
|
+
const iosStandalone = navigator.standalone === true;
|
|
1181
|
+
return window.matchMedia?.("(display-mode: standalone)").matches === true || iosStandalone;
|
|
1182
|
+
}
|
|
1183
|
+
function wantsAutoPrompt() {
|
|
1184
|
+
if (!autoPromptParam) return false;
|
|
1185
|
+
return new URLSearchParams(window.location.search).get(autoPromptParam) === "true";
|
|
1186
|
+
}
|
|
1187
|
+
function onBeforeInstallPrompt(event) {
|
|
1188
|
+
event.preventDefault();
|
|
1189
|
+
deferredPrompt = event;
|
|
1190
|
+
notify();
|
|
1191
|
+
if (wantsAutoPrompt()) void promptAppInstall();
|
|
1192
|
+
}
|
|
1193
|
+
function onAppInstalled() {
|
|
1194
|
+
installed = true;
|
|
1195
|
+
deferredPrompt = null;
|
|
1196
|
+
notify();
|
|
1197
|
+
}
|
|
1198
|
+
function initInstallPrompt(options = {}) {
|
|
1199
|
+
if (options.autoPromptParam) autoPromptParam = options.autoPromptParam;
|
|
1200
|
+
if (initialized || typeof window === "undefined") return;
|
|
1201
|
+
initialized = true;
|
|
1202
|
+
installed = isStandalone();
|
|
1203
|
+
window.addEventListener("beforeinstallprompt", onBeforeInstallPrompt);
|
|
1204
|
+
window.addEventListener("appinstalled", onAppInstalled);
|
|
1205
|
+
}
|
|
1206
|
+
async function promptAppInstall() {
|
|
1207
|
+
if (!deferredPrompt) return false;
|
|
1208
|
+
const prompt = deferredPrompt;
|
|
1209
|
+
deferredPrompt = null;
|
|
1210
|
+
notify();
|
|
1211
|
+
try {
|
|
1212
|
+
await prompt.prompt();
|
|
1213
|
+
} catch {
|
|
1214
|
+
}
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
var INSTALL_PROMPT_DISMISSED_KEY = "arbi-blocks:install-prompt-dismissed";
|
|
1218
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
1219
|
+
function readDismissedAt(key) {
|
|
1220
|
+
try {
|
|
1221
|
+
const raw = window.localStorage.getItem(key);
|
|
1222
|
+
const at = raw ? Number(raw) : NaN;
|
|
1223
|
+
return Number.isFinite(at) ? at : null;
|
|
1224
|
+
} catch {
|
|
1225
|
+
return null;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function useInstallPrompt({
|
|
1229
|
+
storageKey = INSTALL_PROMPT_DISMISSED_KEY,
|
|
1230
|
+
dismissDays = 30,
|
|
1231
|
+
autoPromptParam: autoParam,
|
|
1232
|
+
appName
|
|
1233
|
+
} = {}) {
|
|
1234
|
+
const [, forceRender] = useState(0);
|
|
1235
|
+
const [dismissedAt, setDismissedAt] = useState(
|
|
1236
|
+
() => typeof window === "undefined" ? null : readDismissedAt(storageKey)
|
|
1237
|
+
);
|
|
1238
|
+
useEffect(() => {
|
|
1239
|
+
initInstallPrompt({ autoPromptParam: autoParam });
|
|
1240
|
+
const onChange = () => forceRender((n) => n + 1);
|
|
1241
|
+
subscribers.add(onChange);
|
|
1242
|
+
onChange();
|
|
1243
|
+
return () => {
|
|
1244
|
+
subscribers.delete(onChange);
|
|
1245
|
+
};
|
|
1246
|
+
}, [autoParam]);
|
|
1247
|
+
const dismiss = useCallback(() => {
|
|
1248
|
+
const now = Date.now();
|
|
1249
|
+
setDismissedAt(now);
|
|
1250
|
+
try {
|
|
1251
|
+
window.localStorage.setItem(storageKey, String(now));
|
|
1252
|
+
} catch {
|
|
1253
|
+
}
|
|
1254
|
+
}, [storageKey]);
|
|
1255
|
+
const isDismissed = dismissedAt !== null && Date.now() - dismissedAt < dismissDays * DAY_MS;
|
|
1256
|
+
const isInstalled = installed || isStandalone();
|
|
1257
|
+
return {
|
|
1258
|
+
canPrompt: !isInstalled && deferredPrompt !== null,
|
|
1259
|
+
isInstalled,
|
|
1260
|
+
isIos: isIosDevice(),
|
|
1261
|
+
isDismissed,
|
|
1262
|
+
promptInstall: promptAppInstall,
|
|
1263
|
+
dismiss,
|
|
1264
|
+
instructions: getInstallInstructions({ appName })
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
var DEFAULT_INSTALL_PROMPT_LABELS = {
|
|
1268
|
+
install: "Install app",
|
|
1269
|
+
dismiss: "Dismiss install prompt",
|
|
1270
|
+
installAs: "Install {app} as an app"
|
|
1271
|
+
};
|
|
1272
|
+
function InstallPrompt({
|
|
1273
|
+
placement = "start",
|
|
1274
|
+
labels,
|
|
1275
|
+
className,
|
|
1276
|
+
"data-testid": testId,
|
|
1277
|
+
...options
|
|
1278
|
+
}) {
|
|
1279
|
+
const l = { ...DEFAULT_INSTALL_PROMPT_LABELS, ...labels };
|
|
1280
|
+
const install = useInstallPrompt(options);
|
|
1281
|
+
const [showSteps, setShowSteps] = useState(false);
|
|
1282
|
+
const isOffer = install.canPrompt || install.isIos;
|
|
1283
|
+
if (install.isInstalled || install.isDismissed || !isOffer) return null;
|
|
1284
|
+
const appName = options.appName ?? "this app";
|
|
1285
|
+
const onInstall = async () => {
|
|
1286
|
+
if (install.canPrompt) await install.promptInstall();
|
|
1287
|
+
else setShowSteps((open) => !open);
|
|
1288
|
+
};
|
|
1289
|
+
return /* @__PURE__ */ jsxs(
|
|
1290
|
+
"div",
|
|
1291
|
+
{
|
|
1292
|
+
"data-slot": "install-prompt",
|
|
1293
|
+
"data-testid": testIdOr(testId, { testId: "install-app-prompt" }),
|
|
1294
|
+
className: cn(
|
|
1295
|
+
"fixed z-30 flex max-w-[calc(100vw-1.5rem)] flex-col gap-2",
|
|
1296
|
+
// Above the bottom bars (tab bar / composer) and the home indicator on a phone, a plain
|
|
1297
|
+
// corner offset from `sm` up where the tab bar is gone.
|
|
1298
|
+
"bottom-[calc(max(var(--shell-bottom-inset,0px),env(safe-area-inset-bottom,0px))+0.75rem)] sm:bottom-[calc(env(safe-area-inset-bottom,0px)+0.75rem)]",
|
|
1299
|
+
placement === "start" ? "left-3 items-start" : "right-3 items-end",
|
|
1300
|
+
className
|
|
1301
|
+
),
|
|
1302
|
+
children: [
|
|
1303
|
+
showSteps && /* @__PURE__ */ jsxs(
|
|
1304
|
+
"div",
|
|
1305
|
+
{
|
|
1306
|
+
"data-slot": "install-prompt-steps",
|
|
1307
|
+
className: "w-72 max-w-full rounded-lg border border-border bg-card p-3 text-sm text-card-foreground shadow-lg",
|
|
1308
|
+
children: [
|
|
1309
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: install.instructions.heading }),
|
|
1310
|
+
/* @__PURE__ */ jsx("ol", { className: "mt-2 list-decimal space-y-1 pl-5 text-muted-foreground", children: install.instructions.steps.map((step) => /* @__PURE__ */ jsx("li", { children: step }, step)) })
|
|
1311
|
+
]
|
|
1312
|
+
}
|
|
1313
|
+
),
|
|
1314
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center rounded-full border border-border bg-card/95 text-foreground shadow-sm backdrop-blur", children: [
|
|
1315
|
+
/* @__PURE__ */ jsxs(
|
|
1316
|
+
"button",
|
|
1317
|
+
{
|
|
1318
|
+
type: "button",
|
|
1319
|
+
onClick: () => void onInstall(),
|
|
1320
|
+
"aria-label": l.installAs.replace("{app}", appName),
|
|
1321
|
+
"aria-expanded": install.canPrompt ? void 0 : showSteps,
|
|
1322
|
+
"data-slot": "install-prompt-action",
|
|
1323
|
+
className: "inline-flex min-h-11 items-center gap-1.5 rounded-full pl-4 pr-2 text-xs font-medium transition-colors hover:bg-accent sm:min-h-9 sm:pl-3",
|
|
1324
|
+
children: [
|
|
1325
|
+
/* @__PURE__ */ jsx(Download, { className: "size-3.5", "aria-hidden": "true" }),
|
|
1326
|
+
l.install
|
|
1327
|
+
]
|
|
1328
|
+
}
|
|
1329
|
+
),
|
|
1330
|
+
/* @__PURE__ */ jsx(
|
|
1331
|
+
"button",
|
|
1332
|
+
{
|
|
1333
|
+
type: "button",
|
|
1334
|
+
onClick: install.dismiss,
|
|
1335
|
+
"aria-label": l.dismiss,
|
|
1336
|
+
"data-slot": "install-prompt-dismiss",
|
|
1337
|
+
className: "inline-flex size-11 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground sm:size-9",
|
|
1338
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5", "aria-hidden": "true" })
|
|
1339
|
+
}
|
|
1340
|
+
)
|
|
1341
|
+
] })
|
|
1342
|
+
]
|
|
1343
|
+
}
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1098
1346
|
function ActionCluster({
|
|
1099
1347
|
layout = "bar",
|
|
1100
1348
|
status,
|
|
@@ -1571,6 +1819,6 @@ function SplitLayout({
|
|
|
1571
1819
|
);
|
|
1572
1820
|
}
|
|
1573
1821
|
|
|
1574
|
-
export { ActionCluster, AskField, AskRow, AskTrigger, DEFAULT_ASK_FIELD_LABELS, DEFAULT_MOBILE_BARS_LABELS, DEFAULT_OFFLINE_PILL_LABELS, DEFAULT_REMOTE_CONTROL_PILL_LABELS, DEFAULT_SIDEBAR_LABELS, DEFAULT_TIP_CARD_LABELS, DEFAULT_WORKSPACE_KIND_LABELS, DEFAULT_WORKSPACE_SWITCHER_LABELS, InfoBar, MobileAppBar, MobileTabBar, OfflinePill, RemoteControlPill, Sidebar, SidebarBadgeRow, SidebarRowAction, SidebarRowHoverContext, SplitLayout, StatusRow, TipCard, WorkspaceIdentity, WorkspaceSwitcher, resolveSidebarLayout, useSidebarContext, useSidebarSettle, workspaceKindColor, workspaceKindMeta };
|
|
1575
|
-
//# sourceMappingURL=chunk-
|
|
1576
|
-
//# sourceMappingURL=chunk-
|
|
1822
|
+
export { ActionCluster, AskField, AskRow, AskTrigger, DEFAULT_ASK_FIELD_LABELS, DEFAULT_INSTALL_PROMPT_LABELS, DEFAULT_MOBILE_BARS_LABELS, DEFAULT_OFFLINE_PILL_LABELS, DEFAULT_REMOTE_CONTROL_PILL_LABELS, DEFAULT_SIDEBAR_LABELS, DEFAULT_TIP_CARD_LABELS, DEFAULT_WORKSPACE_KIND_LABELS, DEFAULT_WORKSPACE_SWITCHER_LABELS, INSTALL_PROMPT_DISMISSED_KEY, InfoBar, InstallPrompt, MobileAppBar, MobileTabBar, OfflinePill, RemoteControlPill, Sidebar, SidebarBadgeRow, SidebarRowAction, SidebarRowHoverContext, SplitLayout, StatusRow, TipCard, WorkspaceIdentity, WorkspaceSwitcher, getInstallInstructions, initInstallPrompt, isIosDevice, promptAppInstall, resolveSidebarLayout, useInstallPrompt, useSidebarContext, useSidebarSettle, workspaceKindColor, workspaceKindMeta };
|
|
1823
|
+
//# sourceMappingURL=chunk-EY2RJW27.js.map
|
|
1824
|
+
//# sourceMappingURL=chunk-EY2RJW27.js.map
|