@swiftbrowser/react 0.28.3 → 0.28.5
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 +28 -1
- package/dist/components/containers.d.ts.map +1 -1
- package/dist/components/controls.d.ts +14 -0
- package/dist/components/controls.d.ts.map +1 -1
- package/dist/components/hostElement.d.ts +20 -0
- package/dist/components/hostElement.d.ts.map +1 -0
- package/dist/components/remoteTree.d.ts +42 -1
- package/dist/components/remoteTree.d.ts.map +1 -1
- package/dist/components/shapes.d.ts +3 -1
- package/dist/components/shapes.d.ts.map +1 -1
- package/dist/components/split.d.ts.map +1 -1
- package/dist/components/stacks.d.ts +16 -0
- package/dist/components/stacks.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1561 -1438
- package/dist/index.js.map +1 -1
- package/dist/lazy.d.ts +16 -4
- package/dist/lazy.d.ts.map +1 -1
- package/dist/mount.d.ts +1 -1
- package/dist/mount.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4,10 +4,10 @@ import Reconciler from "react-reconciler";
|
|
|
4
4
|
import { base64Decode, base64Encode } from "@swiftbrowser/web/src/base64";
|
|
5
5
|
import { addLiveBitmap, forgetLiveBitmap } from "@swiftbrowser/web/src/bitmaps";
|
|
6
6
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
7
|
+
import { browserEnvironment, exportFiles, loadableURL, performHostRequest } from "@swiftbrowser/web/src/hostRequests";
|
|
7
8
|
import { horizontalSizeClassFor } from "@swiftbrowser/web/src/protocol";
|
|
8
9
|
import { BrowserHistory } from "@swiftbrowser/web/src/browserHistory";
|
|
9
10
|
import { watchKeyboard } from "@swiftbrowser/web/src/deviceMode";
|
|
10
|
-
import { browserEnvironment, exportFiles, loadableURL, performHostRequest } from "@swiftbrowser/web/src/hostRequests";
|
|
11
11
|
import { Renderer } from "@swiftbrowser/web/src/renderer";
|
|
12
12
|
import { currentScenePhase, watchScenePhase } from "@swiftbrowser/web/src/scenePhase";
|
|
13
13
|
import { applyTypeSizeVariables } from "@swiftbrowser/web/src/typography";
|
|
@@ -989,41 +989,136 @@ function findStack(node) {
|
|
|
989
989
|
for (const child of node.children) {
|
|
990
990
|
if (child.kind === "sheet" || child.kind === "alert") continue;
|
|
991
991
|
if (child.kind === "navstack") return child;
|
|
992
|
+
if (child.kind === "navsplit") return splitDetailStack(child);
|
|
992
993
|
const found = findStack(child);
|
|
993
994
|
if (found) return found;
|
|
994
995
|
}
|
|
995
996
|
return null;
|
|
996
997
|
}
|
|
998
|
+
function findSplit(node) {
|
|
999
|
+
for (const child of node.children) {
|
|
1000
|
+
if (child.kind === "sheet" || child.kind === "alert" || child.kind === "navstack") continue;
|
|
1001
|
+
if (child.kind === "navsplit") return child;
|
|
1002
|
+
const found = findSplit(child);
|
|
1003
|
+
if (found) return found;
|
|
1004
|
+
}
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
const splitSidebarStack = (split) => split.children[0]?.kind === "navstack" ? split.children[0] : null;
|
|
1008
|
+
const splitDetailStack = (split) => split.children[1]?.kind === "navstack" ? split.children[1] : null;
|
|
997
1009
|
const screensOf = (stack) => stack ? stack.children.filter((child) => child.kind === "navscreen") : [];
|
|
998
|
-
function renderNode(root, node, stack) {
|
|
1010
|
+
function renderNode(root, node, stack, elements) {
|
|
999
1011
|
if (node.kind === "host") return null;
|
|
1000
1012
|
if (node === stack) {
|
|
1001
1013
|
const first = screensOf(stack)[0];
|
|
1002
|
-
return createElement(Fragment, { key: node.id }, first ? renderScreen(root, first, stack) : null);
|
|
1014
|
+
return createElement(Fragment, { key: node.id }, first ? renderScreen(root, first, stack, elements) : null);
|
|
1003
1015
|
}
|
|
1004
|
-
|
|
1016
|
+
if (node.kind === "navsplit" && stack && splitDetailStack(node) === stack) return createElement(Fragment, { key: node.id }, renderNode(root, stack, stack, elements));
|
|
1017
|
+
const children = node.children.length ? node.children.map((child) => renderNode(root, child, stack, elements)) : void 0;
|
|
1018
|
+
const own = elements && Object.prototype.hasOwnProperty.call(elements, node.kind) ? elements[node.kind] : void 0;
|
|
1019
|
+
if (own) return createElement(Fragment, { key: node.id }, own(node.props, children));
|
|
1005
1020
|
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), children));
|
|
1006
1021
|
}
|
|
1007
|
-
function renderSheet(root, node, stack, inherited) {
|
|
1008
|
-
const children = node.children.map((child) => renderNode(root, child, stack));
|
|
1022
|
+
function renderSheet(root, node, stack, inherited, elements) {
|
|
1023
|
+
const children = node.children.map((child) => renderNode(root, child, stack, elements));
|
|
1009
1024
|
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), replayStyles(inherited, children)));
|
|
1010
1025
|
}
|
|
1011
|
-
function renderScreen(root, screen, stack) {
|
|
1026
|
+
function renderScreen(root, screen, stack, elements) {
|
|
1012
1027
|
const out = [screenPrefs(screen.props, "$screen")];
|
|
1013
1028
|
for (const child of screen.children) {
|
|
1014
|
-
const drawn = renderNode(root, child, stack);
|
|
1029
|
+
const drawn = renderNode(root, child, stack, elements);
|
|
1015
1030
|
if (child.kind === "toolbar" || child.kind === "searchfield") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "navscreen")));
|
|
1016
1031
|
else out.push(drawn);
|
|
1017
1032
|
}
|
|
1018
1033
|
return createElement(Fragment, null, ...out);
|
|
1019
1034
|
}
|
|
1020
|
-
function RemoteScreen({ root, id }) {
|
|
1035
|
+
function RemoteScreen({ root, id, elements }) {
|
|
1021
1036
|
useSyncExternalStore(root.subscribe, root.getVersion, root.getVersion);
|
|
1022
1037
|
const screen = root.node(id);
|
|
1023
1038
|
if (!screen?.parent) return null;
|
|
1024
|
-
return renderScreen(root, screen, findStack(root.root));
|
|
1039
|
+
return renderScreen(root, screen, findStack(root.root), elements);
|
|
1040
|
+
}
|
|
1041
|
+
function useScreenValues(root, elements) {
|
|
1042
|
+
const values = useRef(/* @__PURE__ */ new Map());
|
|
1043
|
+
const ours = useRef(/* @__PURE__ */ new WeakSet());
|
|
1044
|
+
const keyOf2 = (screen) => `${screen.id}:${JSON.stringify(screen.props["route"] ?? null)}`;
|
|
1045
|
+
const valueFor = (screen) => {
|
|
1046
|
+
const key = keyOf2(screen);
|
|
1047
|
+
let value = values.current.get(key);
|
|
1048
|
+
if (!value) {
|
|
1049
|
+
value = "route" in screen.props ? { view: /* @__PURE__ */ jsx(RemoteScreen, { root, id: screen.id, elements }), route: screen.props["route"] } : { view: /* @__PURE__ */ jsx(RemoteScreen, { root, id: screen.id, elements }) };
|
|
1050
|
+
values.current.set(key, value);
|
|
1051
|
+
ours.current.add(value);
|
|
1052
|
+
}
|
|
1053
|
+
return value;
|
|
1054
|
+
};
|
|
1055
|
+
const isOurs = (value) => typeof value === "object" && value !== null && ours.current.has(value);
|
|
1056
|
+
const forget = (keys) => {
|
|
1057
|
+
for (const key of values.current.keys()) if (!keys.includes(key)) values.current.delete(key);
|
|
1058
|
+
};
|
|
1059
|
+
return { valueFor, keyOf: keyOf2, isOurs, forget };
|
|
1060
|
+
}
|
|
1061
|
+
function useRemoteSidebar(root, path, setPath, options = {}) {
|
|
1062
|
+
const shown = options.shown ?? true;
|
|
1063
|
+
useSyncExternalStore(root ? root.subscribe : noSubscribe, root ? root.getVersion : zero, root ? root.getVersion : zero);
|
|
1064
|
+
const { valueFor, keyOf: keyOf2, isOurs, forget } = useScreenValues(root ?? NO_ROOT, options.elements);
|
|
1065
|
+
const split = root ? findSplit(root.root) : null;
|
|
1066
|
+
const screens = split ? screensOf(splitSidebarStack(split)) : [];
|
|
1067
|
+
const dismissed = useRef(false);
|
|
1068
|
+
const lastKeys = useRef([]);
|
|
1069
|
+
const lastMine = useRef(0);
|
|
1070
|
+
const last = useRef({ root: null, shown: false, generation: void 0 });
|
|
1071
|
+
useLayoutEffect(() => {
|
|
1072
|
+
if (last.current.root !== root || !last.current.shown && shown || last.current.generation !== options.generation) dismissed.current = false;
|
|
1073
|
+
last.current = { root, shown, generation: options.generation };
|
|
1074
|
+
const keys = screens.map(keyOf2);
|
|
1075
|
+
const wanted = shown && !dismissed.current ? screens.map(valueFor) : [];
|
|
1076
|
+
forget(keys);
|
|
1077
|
+
const hosts = path.filter((value) => !isOurs(value));
|
|
1078
|
+
const mine = path.filter(isOurs);
|
|
1079
|
+
const childMoved = keys.length !== lastKeys.current.length || keys.some((key, i) => key !== lastKeys.current[i]);
|
|
1080
|
+
lastKeys.current = keys;
|
|
1081
|
+
const popped = mine.length < lastMine.current;
|
|
1082
|
+
lastMine.current = mine.length;
|
|
1083
|
+
if (root && wanted.length > 0 && !childMoved && popped && mine.length < wanted.length && mine.every((value, i) => value === wanted[i])) {
|
|
1084
|
+
if (mine.length === 0) {
|
|
1085
|
+
dismissed.current = true;
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
root.dispatch({ type: "tap", id: screens[mine.length].id });
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
if (mine.length === wanted.length && mine.every((value, i) => value === wanted[i])) return;
|
|
1092
|
+
lastMine.current = wanted.length;
|
|
1093
|
+
setPath([...hosts, ...wanted]);
|
|
1094
|
+
});
|
|
1025
1095
|
}
|
|
1026
|
-
|
|
1096
|
+
const noSubscribe = () => () => {
|
|
1097
|
+
};
|
|
1098
|
+
const zero = () => 0;
|
|
1099
|
+
const NO_ROOT = {
|
|
1100
|
+
applyOps() {
|
|
1101
|
+
},
|
|
1102
|
+
onEvent() {
|
|
1103
|
+
},
|
|
1104
|
+
onEnvironment() {
|
|
1105
|
+
},
|
|
1106
|
+
dispatch() {
|
|
1107
|
+
},
|
|
1108
|
+
setEnvironment() {
|
|
1109
|
+
},
|
|
1110
|
+
subscribe: noSubscribe,
|
|
1111
|
+
getVersion: zero,
|
|
1112
|
+
root: { id: 0, kind: "root", props: {}, children: [], parent: null },
|
|
1113
|
+
node: () => void 0,
|
|
1114
|
+
rootProps: {},
|
|
1115
|
+
handlersFor: () => ({}),
|
|
1116
|
+
attach() {
|
|
1117
|
+
},
|
|
1118
|
+
dispose() {
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
function RemoteTree({ root, initialPath, elements }) {
|
|
1027
1122
|
useSyncExternalStore(root.subscribe, root.getVersion, root.getVersion);
|
|
1028
1123
|
const environment = useContext(EnvironmentContext);
|
|
1029
1124
|
const inherited = useInheritedStyles();
|
|
@@ -1039,20 +1134,8 @@ function RemoteTree({ root, initialPath }) {
|
|
|
1039
1134
|
}, [root, environment]);
|
|
1040
1135
|
const stack = navigation ? findStack(root.root) : null;
|
|
1041
1136
|
const pushed = screensOf(stack).slice(1);
|
|
1042
|
-
const
|
|
1043
|
-
const ours = useRef(/* @__PURE__ */ new WeakSet());
|
|
1137
|
+
const { valueFor, keyOf: keyOf2, isOurs, forget } = useScreenValues(root, elements);
|
|
1044
1138
|
const lastPushed = useRef([]);
|
|
1045
|
-
const keyOf2 = (screen) => `${screen.id}:${JSON.stringify(screen.props["route"] ?? null)}`;
|
|
1046
|
-
const valueFor = (screen) => {
|
|
1047
|
-
const key = keyOf2(screen);
|
|
1048
|
-
let value = values.current.get(key);
|
|
1049
|
-
if (!value) {
|
|
1050
|
-
value = "route" in screen.props ? { view: /* @__PURE__ */ jsx(RemoteScreen, { root, id: screen.id }), route: screen.props["route"] } : { view: /* @__PURE__ */ jsx(RemoteScreen, { root, id: screen.id }) };
|
|
1051
|
-
values.current.set(key, value);
|
|
1052
|
-
ours.current.add(value);
|
|
1053
|
-
}
|
|
1054
|
-
return value;
|
|
1055
|
-
};
|
|
1056
1139
|
const restored = useRef(false);
|
|
1057
1140
|
useLayoutEffect(() => {
|
|
1058
1141
|
if (restored.current) return;
|
|
@@ -1065,10 +1148,10 @@ function RemoteTree({ root, initialPath }) {
|
|
|
1065
1148
|
if (!navigation) return;
|
|
1066
1149
|
const keys = pushed.map(keyOf2);
|
|
1067
1150
|
const wanted = pushed.map(valueFor);
|
|
1068
|
-
|
|
1151
|
+
forget(keys);
|
|
1069
1152
|
const tail = navigation.path.slice(depth);
|
|
1070
1153
|
let shown = 0;
|
|
1071
|
-
while (shown < tail.length &&
|
|
1154
|
+
while (shown < tail.length && isOurs(tail[shown])) shown += 1;
|
|
1072
1155
|
const childMoved = keys.length !== lastPushed.current.length || keys.some((key, i) => key !== lastPushed.current[i]);
|
|
1073
1156
|
lastPushed.current = keys;
|
|
1074
1157
|
if (!childMoved && shown < wanted.length && tail.slice(0, shown).every((value, i) => value === wanted[i])) {
|
|
@@ -1082,13 +1165,192 @@ function RemoteTree({ root, initialPath }) {
|
|
|
1082
1165
|
if ("colorScheme" in root.rootProps)
|
|
1083
1166
|
out.push(createElement(Fragment, { key: "$scheme" }, sb(PREF_KIND, { colorScheme: root.rootProps["colorScheme"] }, void 0, void 0, "root")));
|
|
1084
1167
|
for (const child of root.root.children) {
|
|
1085
|
-
const drawn = child.kind === "sheet" && inherited.length > 0 ? renderSheet(root, child, stack, inherited) : renderNode(root, child, stack);
|
|
1168
|
+
const drawn = child.kind === "sheet" && inherited.length > 0 ? renderSheet(root, child, stack, inherited, elements) : renderNode(root, child, stack, elements);
|
|
1086
1169
|
if (child.kind === "sheet" || child.kind === "alert") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "root")));
|
|
1087
1170
|
else if (child.kind === "toolbar" || child.kind === "searchfield") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "navscreen")));
|
|
1088
1171
|
else out.push(drawn);
|
|
1089
1172
|
}
|
|
1090
1173
|
return createElement(Fragment, null, ...out);
|
|
1091
1174
|
}
|
|
1175
|
+
function readBinding(value, onChange) {
|
|
1176
|
+
if (Array.isArray(value) && value.length === 2 && typeof value[1] === "function") {
|
|
1177
|
+
const [current, set] = value;
|
|
1178
|
+
return [current, set];
|
|
1179
|
+
}
|
|
1180
|
+
return [value, onChange ?? (() => {
|
|
1181
|
+
})];
|
|
1182
|
+
}
|
|
1183
|
+
let active = null;
|
|
1184
|
+
function Draggable({ payload, children }) {
|
|
1185
|
+
return sb(
|
|
1186
|
+
"draggable",
|
|
1187
|
+
{},
|
|
1188
|
+
{
|
|
1189
|
+
dragstart: (event) => {
|
|
1190
|
+
active = { id: event.id, payload };
|
|
1191
|
+
},
|
|
1192
|
+
dragend: (event) => {
|
|
1193
|
+
if (active?.id === event.id) active = null;
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
children
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
function itemValue(item) {
|
|
1200
|
+
if (item.text !== void 0) {
|
|
1201
|
+
if (item.type === "text/uri-list") {
|
|
1202
|
+
try {
|
|
1203
|
+
return new URL(item.text.split(/\r?\n/)[0].trim());
|
|
1204
|
+
} catch {
|
|
1205
|
+
return item.text;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return item.text;
|
|
1209
|
+
}
|
|
1210
|
+
const name = item.path ?? item.name ?? "file";
|
|
1211
|
+
if (item.file) {
|
|
1212
|
+
const file = item.file;
|
|
1213
|
+
return item.path !== void 0 && item.path !== file.name ? new File([file], item.path, { type: file.type, lastModified: file.lastModified }) : file;
|
|
1214
|
+
}
|
|
1215
|
+
if (item.url !== void 0 && item.data === void 0) {
|
|
1216
|
+
const fromReference = browserEnvironment.fileFromReference;
|
|
1217
|
+
if (fromReference) {
|
|
1218
|
+
return fromReference({ type: item.type, name, url: item.url, ...item.path !== void 0 ? { path: item.path } : {}, ...item.size !== void 0 ? { size: item.size } : {} });
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
const binary = atob(item.data ?? "");
|
|
1222
|
+
const bytes = new Uint8Array(binary.length);
|
|
1223
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1224
|
+
return typeof File !== "undefined" ? new File([bytes], name, { type: item.type }) : bytes;
|
|
1225
|
+
}
|
|
1226
|
+
function DropDestination({ action, isTargeted, accepts, children }) {
|
|
1227
|
+
return sb(
|
|
1228
|
+
"dropdestination",
|
|
1229
|
+
{ accepts: accepts ?? [] },
|
|
1230
|
+
{
|
|
1231
|
+
drop: (event) => {
|
|
1232
|
+
if (event.phase === "entered") {
|
|
1233
|
+
isTargeted?.(true);
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
isTargeted?.(false);
|
|
1237
|
+
if (event.phase !== "performed") return;
|
|
1238
|
+
let items;
|
|
1239
|
+
if (event.source !== void 0) items = active && active.id === event.source ? [active.payload] : [];
|
|
1240
|
+
else items = (event.items ?? []).map(itemValue);
|
|
1241
|
+
if (items.length > 0) action(items, { x: event.x, y: event.y });
|
|
1242
|
+
}
|
|
1243
|
+
},
|
|
1244
|
+
children
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
function FileImporterPresenter(spec) {
|
|
1248
|
+
const [presented, setPresented] = readBinding(spec.isPresented);
|
|
1249
|
+
const latest = useRef(spec);
|
|
1250
|
+
latest.current = spec;
|
|
1251
|
+
const choosing = useRef(false);
|
|
1252
|
+
useLayoutEffect(() => {
|
|
1253
|
+
if (!presented || choosing.current) return;
|
|
1254
|
+
const { allowedContentTypes, allowsMultipleSelection } = latest.current;
|
|
1255
|
+
const pick = browserEnvironment.pickFiles;
|
|
1256
|
+
if (!pick) {
|
|
1257
|
+
setPresented(false);
|
|
1258
|
+
latest.current.onCancellation?.();
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
choosing.current = true;
|
|
1262
|
+
void pick({ accept: allowedContentTypes.join(","), multiple: allowsMultipleSelection === true }).then((files) => {
|
|
1263
|
+
choosing.current = false;
|
|
1264
|
+
setPresented(false);
|
|
1265
|
+
if (files.length > 0) latest.current.onCompletion(files);
|
|
1266
|
+
else latest.current.onCancellation?.();
|
|
1267
|
+
});
|
|
1268
|
+
}, [presented, setPresented]);
|
|
1269
|
+
return null;
|
|
1270
|
+
}
|
|
1271
|
+
const EXTENSIONS = {
|
|
1272
|
+
"text/plain": "txt",
|
|
1273
|
+
"text/csv": "csv",
|
|
1274
|
+
"text/markdown": "md",
|
|
1275
|
+
"text/html": "html",
|
|
1276
|
+
"application/json": "json",
|
|
1277
|
+
"application/pdf": "pdf",
|
|
1278
|
+
"image/png": "png",
|
|
1279
|
+
"image/jpeg": "jpg",
|
|
1280
|
+
"image/svg+xml": "svg",
|
|
1281
|
+
"audio/mp4": "m4a",
|
|
1282
|
+
"video/mp4": "mp4"
|
|
1283
|
+
};
|
|
1284
|
+
function exportFile(document2, contentType, defaultFilename, index = 0) {
|
|
1285
|
+
const type = document2 instanceof Blob && document2.type || contentType || "application/octet-stream";
|
|
1286
|
+
let name = defaultFilename ?? (document2 instanceof File ? document2.name : index === 0 ? "Untitled" : `Untitled ${index + 1}`);
|
|
1287
|
+
name = name.replace(/[\\/:*?"<>|]+/g, "-").trim() || "Untitled";
|
|
1288
|
+
const extension = EXTENSIONS[type.split(";")[0].trim()];
|
|
1289
|
+
if (extension && !/\.[A-Za-z0-9]{1,8}$/.test(name)) name = `${name}.${extension}`;
|
|
1290
|
+
if (document2 instanceof File && document2.name === name && document2.type === type) return document2;
|
|
1291
|
+
const bytes = typeof document2 === "string" ? new TextEncoder().encode(document2) : document2;
|
|
1292
|
+
return new File([bytes], name, { type });
|
|
1293
|
+
}
|
|
1294
|
+
function FileExporterPresenter(spec) {
|
|
1295
|
+
const [presented, setPresented] = readBinding(spec.isPresented);
|
|
1296
|
+
const latest = useRef(spec);
|
|
1297
|
+
latest.current = spec;
|
|
1298
|
+
const exporting = useRef(false);
|
|
1299
|
+
useLayoutEffect(() => {
|
|
1300
|
+
if (!presented || exporting.current) return;
|
|
1301
|
+
const { document: document2, contentType, defaultFilename } = latest.current;
|
|
1302
|
+
const documents = document2 === null ? [] : Array.isArray(document2) ? document2 : [document2];
|
|
1303
|
+
if (documents.length === 0) {
|
|
1304
|
+
setPresented(false);
|
|
1305
|
+
latest.current.onCancellation?.();
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
exporting.current = true;
|
|
1309
|
+
const files = documents.map((item, index) => exportFile(item, contentType, defaultFilename, index));
|
|
1310
|
+
exportFiles(files).then(
|
|
1311
|
+
(result) => {
|
|
1312
|
+
exporting.current = false;
|
|
1313
|
+
setPresented(false);
|
|
1314
|
+
if (result.outcome === "cancelled") latest.current.onCancellation?.();
|
|
1315
|
+
else latest.current.onCompletion?.(result);
|
|
1316
|
+
},
|
|
1317
|
+
(error) => {
|
|
1318
|
+
exporting.current = false;
|
|
1319
|
+
setPresented(false);
|
|
1320
|
+
latest.current.onError?.(error);
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
}, [presented, setPresented]);
|
|
1324
|
+
return null;
|
|
1325
|
+
}
|
|
1326
|
+
const ListSelectionContext = createContext(null);
|
|
1327
|
+
function Row({ tag, onDelete, deletable, onMove, movable, index, containerIndex, children }) {
|
|
1328
|
+
const selection = useContext(ListSelectionContext);
|
|
1329
|
+
const selectable = selection !== null && tag !== void 0;
|
|
1330
|
+
const canDelete = onDelete !== void 0 && deletable !== false;
|
|
1331
|
+
const canMove = onMove !== void 0 && movable !== false;
|
|
1332
|
+
if (!selectable && !canDelete && !canMove) return children;
|
|
1333
|
+
const props = {};
|
|
1334
|
+
if (selectable) {
|
|
1335
|
+
props["selectable"] = true;
|
|
1336
|
+
props["selected"] = selection.isSelected(tag);
|
|
1337
|
+
}
|
|
1338
|
+
if (canDelete) props["deletable"] = true;
|
|
1339
|
+
if (canMove) props["movable"] = true;
|
|
1340
|
+
return sb(
|
|
1341
|
+
"listrow",
|
|
1342
|
+
props,
|
|
1343
|
+
{
|
|
1344
|
+
tap: () => selectable && selection.select(tag),
|
|
1345
|
+
delete: () => onDelete?.(),
|
|
1346
|
+
move: (event) => {
|
|
1347
|
+
const start = (containerIndex ?? index ?? 0) - (index ?? 0);
|
|
1348
|
+
onMove?.(Math.max(0, event.to - start));
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
children
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1092
1354
|
const HIERARCHY = { primary: 1, secondary: 2, tertiary: 3, quaternary: 4 };
|
|
1093
1355
|
function rgb(r2, g, b, a = 1) {
|
|
1094
1356
|
return { r: r2, g, b, a };
|
|
@@ -1235,608 +1497,15 @@ function insets(edges, amount) {
|
|
|
1235
1497
|
}
|
|
1236
1498
|
return result;
|
|
1237
1499
|
}
|
|
1238
|
-
|
|
1239
|
-
function
|
|
1240
|
-
|
|
1241
|
-
if (installed === measurer) installed = null;
|
|
1242
|
-
return;
|
|
1243
|
-
}
|
|
1244
|
-
installed = measurer;
|
|
1245
|
-
}
|
|
1246
|
-
function canMeasureText() {
|
|
1247
|
-
return installed !== null;
|
|
1248
|
-
}
|
|
1249
|
-
function measureText(text, font$1 = "body", width) {
|
|
1250
|
-
if (!installed) throw new Error("measureText: nothing measures text here yet (mount the app, or run it in a SwiftBrowser Native host)");
|
|
1251
|
-
const constrained = typeof width === "number" && Number.isFinite(width) && width > 0 ? width : null;
|
|
1252
|
-
return installed(text, font(font$1), constrained);
|
|
1500
|
+
const isPoint = (value) => typeof value === "object" && value !== null && ("x" in value || "y" in value);
|
|
1501
|
+
function command(request) {
|
|
1502
|
+
return request.axes ? { anchor: request.anchor, serial: request.serial, axes: request.axes } : { anchor: request.anchor, serial: request.serial };
|
|
1253
1503
|
}
|
|
1254
|
-
function
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
return
|
|
1259
|
-
}
|
|
1260
|
-
function mount(screen, element, options = {}) {
|
|
1261
|
-
let renderer = null;
|
|
1262
|
-
const root = createSwiftUIRoot((ops) => renderer?.applyOps(ops));
|
|
1263
|
-
renderer = new Renderer(screen, (event) => root.dispatch(event));
|
|
1264
|
-
renderer.fileDrops = "reference";
|
|
1265
|
-
const measurer = (text, font2, width2) => renderer.measureText(text, font2, width2);
|
|
1266
|
-
installTextMeasurer(measurer);
|
|
1267
|
-
let pageScheme = options.colorScheme ?? "light";
|
|
1268
|
-
let preferred = null;
|
|
1269
|
-
const width = screen.clientWidth || 393;
|
|
1270
|
-
const environment = {
|
|
1271
|
-
colorScheme: pageScheme,
|
|
1272
|
-
dynamicTypeSize: options.dynamicTypeSize ?? "large",
|
|
1273
|
-
horizontalSizeClass: horizontalSizeClassFor(width),
|
|
1274
|
-
scenePhase: typeof document !== "undefined" ? currentScenePhase() : "active",
|
|
1275
|
-
platform: options.platform === void 0 || options.platform === "auto" ? decidePlatform(width) : options.platform
|
|
1276
|
-
};
|
|
1277
|
-
renderer.contentHeight = options.contentHeight ?? false;
|
|
1278
|
-
if (options.sidebarTitleBar === false) renderer.sidebarTitleBar = false;
|
|
1279
|
-
if (options.assets) renderer.setAssetCatalog(options.assets);
|
|
1280
|
-
if (options.app) browserEnvironment.files?.setApp?.(options.app);
|
|
1281
|
-
renderer.setEnvironment({ colorScheme: environment.colorScheme, dynamicTypeSize: environment.dynamicTypeSize, platform: environment.platform });
|
|
1282
|
-
if (options.safeArea !== void 0) renderer.setSafeArea(options.safeArea);
|
|
1283
|
-
root.setEnvironment(environment);
|
|
1284
|
-
const browserHistory = (options.history ?? true) && typeof window !== "undefined" ? new BrowserHistory(renderer, screen) : null;
|
|
1285
|
-
browserHistory?.enable();
|
|
1286
|
-
const stopKeyboard = options.keyboard && typeof window !== "undefined" ? watchKeyboard((height) => renderer?.setKeyboard(height), { root: screen }) : null;
|
|
1287
|
-
const applyScheme = () => {
|
|
1288
|
-
const scheme = preferred ?? pageScheme;
|
|
1289
|
-
const device = screen.closest(".device");
|
|
1290
|
-
if (device) device.dataset["theme"] = scheme;
|
|
1291
|
-
renderer?.setEnvironment({ colorScheme: scheme });
|
|
1292
|
-
root.setEnvironment({ colorScheme: scheme });
|
|
1293
|
-
};
|
|
1294
|
-
const onPreferredScheme = (event) => {
|
|
1295
|
-
const scheme = event.detail.colorScheme;
|
|
1296
|
-
preferred = scheme;
|
|
1297
|
-
queueMicrotask(applyScheme);
|
|
1298
|
-
};
|
|
1299
|
-
screen.addEventListener("sb:color-scheme", onPreferredScheme);
|
|
1300
|
-
let sizeClass = environment.horizontalSizeClass;
|
|
1301
|
-
const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
1302
|
-
const next = horizontalSizeClassFor(screen.clientWidth);
|
|
1303
|
-
if (next === sizeClass) return;
|
|
1304
|
-
sizeClass = next;
|
|
1305
|
-
root.setEnvironment({ horizontalSizeClass: next });
|
|
1306
|
-
}) : null;
|
|
1307
|
-
observer?.observe(screen);
|
|
1308
|
-
const stopScenePhase = typeof document !== "undefined" ? watchScenePhase((scenePhase) => root.setEnvironment({ scenePhase })) : null;
|
|
1309
|
-
root.render(element);
|
|
1310
|
-
const mounted = {
|
|
1311
|
-
root,
|
|
1312
|
-
renderer,
|
|
1313
|
-
setEnvironment(next) {
|
|
1314
|
-
if (next.colorScheme !== void 0) pageScheme = next.colorScheme;
|
|
1315
|
-
const scheme = preferred ?? pageScheme;
|
|
1316
|
-
renderer?.setEnvironment({ ...next, colorScheme: scheme });
|
|
1317
|
-
root.setEnvironment({ ...next, colorScheme: scheme });
|
|
1318
|
-
},
|
|
1319
|
-
setSafeArea(insets2) {
|
|
1320
|
-
renderer?.setSafeArea(insets2);
|
|
1321
|
-
},
|
|
1322
|
-
viewportChanged() {
|
|
1323
|
-
renderer?.viewportChanged();
|
|
1324
|
-
},
|
|
1325
|
-
unmount() {
|
|
1326
|
-
observer?.disconnect();
|
|
1327
|
-
stopScenePhase?.();
|
|
1328
|
-
stopKeyboard?.();
|
|
1329
|
-
browserHistory?.dispose();
|
|
1330
|
-
screen.removeEventListener("sb:color-scheme", onPreferredScheme);
|
|
1331
|
-
installTextMeasurer(measurer, true);
|
|
1332
|
-
root.unmount();
|
|
1333
|
-
renderer?.dispose();
|
|
1334
|
-
}
|
|
1335
|
-
};
|
|
1336
|
-
return mounted;
|
|
1337
|
-
}
|
|
1338
|
-
const EMPTY = { canUndo: false, canRedo: false, undoActionName: "", redoActionName: "" };
|
|
1339
|
-
const defaultSchedule = (close) => {
|
|
1340
|
-
if (typeof queueMicrotask === "function") queueMicrotask(close);
|
|
1341
|
-
else void Promise.resolve().then(close);
|
|
1342
|
-
};
|
|
1343
|
-
class UndoManager {
|
|
1344
|
-
/** Whether registrations in one event (one task of the event loop) form one group; true, as `groupsByEvent`. */
|
|
1345
|
-
groupsByEvent = true;
|
|
1346
|
-
/** How many groups the undo stack keeps; 0 for no limit, as `levelsOfUndo`. */
|
|
1347
|
-
levelsOfUndo = 0;
|
|
1348
|
-
undoStack = [];
|
|
1349
|
-
redoStack = [];
|
|
1350
|
-
/** The group registrations go in: an explicit group, the event's group, or the inverse of what is being undone or redone. */
|
|
1351
|
-
open = null;
|
|
1352
|
-
/** How deep `beginGrouping` is; 0 when `open` is the event's group or an inverse. */
|
|
1353
|
-
depth = 0;
|
|
1354
|
-
/** Whether `open` is the event's group, which `schedule` closes. */
|
|
1355
|
-
byEvent = false;
|
|
1356
|
-
/** The last keyed group closed onto the undo stack, which a registration with its key joins. */
|
|
1357
|
-
coalescing = null;
|
|
1358
|
-
undoing = false;
|
|
1359
|
-
redoing = false;
|
|
1360
|
-
snapshot = EMPTY;
|
|
1361
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1362
|
-
schedule;
|
|
1363
|
-
host;
|
|
1364
|
-
stopListening = null;
|
|
1365
|
-
constructor(options = {}) {
|
|
1366
|
-
this.schedule = options.schedule ?? defaultSchedule;
|
|
1367
|
-
this.host = options.host === void 0 ? browserEnvironment.undoManager ?? null : options.host;
|
|
1368
|
-
if (this.host) {
|
|
1369
|
-
this.stopListening = this.host.listen({ undo: () => this.undo(), redo: () => this.redo() });
|
|
1370
|
-
this.host.update(this.snapshot);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
get canUndo() {
|
|
1374
|
-
return this.undoStack.length > 0;
|
|
1375
|
-
}
|
|
1376
|
-
get canRedo() {
|
|
1377
|
-
return this.redoStack.length > 0;
|
|
1378
|
-
}
|
|
1379
|
-
/** The name of what `undo` takes back ('' for none): "Move" for an Edit menu's "Undo Move". */
|
|
1380
|
-
get undoActionName() {
|
|
1381
|
-
return this.undoStack[this.undoStack.length - 1]?.name ?? "";
|
|
1382
|
-
}
|
|
1383
|
-
get redoActionName() {
|
|
1384
|
-
return this.redoStack[this.redoStack.length - 1]?.name ?? "";
|
|
1385
|
-
}
|
|
1386
|
-
get isUndoing() {
|
|
1387
|
-
return this.undoing;
|
|
1388
|
-
}
|
|
1389
|
-
get isRedoing() {
|
|
1390
|
-
return this.redoing;
|
|
1391
|
-
}
|
|
1392
|
-
/** What the stacks can do, one object per change (for `useSyncExternalStore`). */
|
|
1393
|
-
get state() {
|
|
1394
|
-
return this.snapshot;
|
|
1395
|
-
}
|
|
1396
|
-
/**
|
|
1397
|
-
* Registers what undoes the change just made, under `name`. Run by `undo`,
|
|
1398
|
-
* the closure registers its own inverse the same way, which lands on the
|
|
1399
|
-
* redo stack because the manager is undoing.
|
|
1400
|
-
*/
|
|
1401
|
-
registerUndo(name, undo, options = {}) {
|
|
1402
|
-
const action = { name, undo, target: options.target };
|
|
1403
|
-
if (this.undoing || this.redoing) {
|
|
1404
|
-
this.open.actions.push(action);
|
|
1405
|
-
this.changed();
|
|
1406
|
-
return;
|
|
1407
|
-
}
|
|
1408
|
-
this.redoStack = [];
|
|
1409
|
-
this.coalescing = this.coalescing && this.undoStack[this.undoStack.length - 1] === this.coalescing ? this.coalescing : null;
|
|
1410
|
-
if (this.open) {
|
|
1411
|
-
if (!this.undoStack.includes(this.open)) this.push(this.open);
|
|
1412
|
-
this.open.actions.push(action);
|
|
1413
|
-
if (!this.open.named) this.open.name = name;
|
|
1414
|
-
} else if (this.coalescing && options.key !== void 0 && this.coalescing.key === options.key) {
|
|
1415
|
-
this.coalescing.actions.push(action);
|
|
1416
|
-
this.coalescing.name = name;
|
|
1417
|
-
} else {
|
|
1418
|
-
const group = { name, named: false, actions: [action], key: options.key };
|
|
1419
|
-
this.push(group);
|
|
1420
|
-
this.coalescing = null;
|
|
1421
|
-
if (this.groupsByEvent) {
|
|
1422
|
-
this.open = group;
|
|
1423
|
-
this.byEvent = true;
|
|
1424
|
-
this.schedule(() => {
|
|
1425
|
-
if (this.open === group && this.byEvent) this.close();
|
|
1426
|
-
});
|
|
1427
|
-
} else {
|
|
1428
|
-
this.coalescing = group.key !== void 0 ? group : null;
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
this.changed();
|
|
1432
|
-
}
|
|
1433
|
-
/** Takes back the top group of changes; its inverses become the top of the redo stack. */
|
|
1434
|
-
undo() {
|
|
1435
|
-
this.endOpenGroups();
|
|
1436
|
-
const group = this.undoStack.pop();
|
|
1437
|
-
if (!group) return;
|
|
1438
|
-
this.coalescing = null;
|
|
1439
|
-
this.run(group, "undo");
|
|
1440
|
-
}
|
|
1441
|
-
redo() {
|
|
1442
|
-
this.endOpenGroups();
|
|
1443
|
-
const group = this.redoStack.pop();
|
|
1444
|
-
if (!group) return;
|
|
1445
|
-
this.run(group, "redo");
|
|
1446
|
-
}
|
|
1447
|
-
/**
|
|
1448
|
-
* Starts a group: every registration until `endGrouping` undoes as one
|
|
1449
|
-
* (`beginUndoGrouping`). Nested calls join the outer group. The group is
|
|
1450
|
-
* named `name`, else after its last registration.
|
|
1451
|
-
*/
|
|
1452
|
-
beginGrouping(name) {
|
|
1453
|
-
if (this.undoing || this.redoing) return;
|
|
1454
|
-
this.depth += 1;
|
|
1455
|
-
if (this.depth > 1) return;
|
|
1456
|
-
if (this.open) this.close();
|
|
1457
|
-
this.open = { name: name ?? "", named: name !== void 0, actions: [], key: void 0 };
|
|
1458
|
-
this.byEvent = false;
|
|
1459
|
-
this.coalescing = null;
|
|
1460
|
-
}
|
|
1461
|
-
/** Ends the group `beginGrouping` started; one that registered nothing is dropped. */
|
|
1462
|
-
endGrouping() {
|
|
1463
|
-
if (this.depth === 0) return;
|
|
1464
|
-
this.depth -= 1;
|
|
1465
|
-
if (this.depth === 0) this.close();
|
|
1466
|
-
}
|
|
1467
|
-
/** `body` as one group named `name`. */
|
|
1468
|
-
group(name, body) {
|
|
1469
|
-
this.beginGrouping(name);
|
|
1470
|
-
try {
|
|
1471
|
-
return body();
|
|
1472
|
-
} finally {
|
|
1473
|
-
this.endGrouping();
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
/** Forgets every registration, or those `target` made (`removeAllActions(withTarget:)`), on both stacks and in the open group. */
|
|
1477
|
-
removeAllActions(target) {
|
|
1478
|
-
const mine = (action) => target === void 0 || action.target === target;
|
|
1479
|
-
const strip = (groups) => groups.filter((group) => {
|
|
1480
|
-
group.actions = group.actions.filter((action) => !mine(action));
|
|
1481
|
-
return group.actions.length > 0;
|
|
1482
|
-
});
|
|
1483
|
-
this.undoStack = strip(this.undoStack);
|
|
1484
|
-
this.redoStack = strip(this.redoStack);
|
|
1485
|
-
if (this.open) this.open.actions = this.open.actions.filter((action) => !mine(action));
|
|
1486
|
-
if (this.coalescing && !this.undoStack.includes(this.coalescing)) this.coalescing = null;
|
|
1487
|
-
this.changed();
|
|
1488
|
-
}
|
|
1489
|
-
/** Calls `listener` after each change to `state`; returns what stops it. */
|
|
1490
|
-
subscribe = (listener) => {
|
|
1491
|
-
this.listeners.add(listener);
|
|
1492
|
-
return () => {
|
|
1493
|
-
this.listeners.delete(listener);
|
|
1494
|
-
};
|
|
1495
|
-
};
|
|
1496
|
-
/** Stops listening to the host, for a manager made in a test. */
|
|
1497
|
-
dispose() {
|
|
1498
|
-
this.stopListening?.();
|
|
1499
|
-
this.stopListening = null;
|
|
1500
|
-
}
|
|
1501
|
-
push(group) {
|
|
1502
|
-
this.undoStack.push(group);
|
|
1503
|
-
if (this.levelsOfUndo > 0 && this.undoStack.length > this.levelsOfUndo) this.undoStack.splice(0, this.undoStack.length - this.levelsOfUndo);
|
|
1504
|
-
}
|
|
1505
|
-
/** Closes `open`; a keyed group on top stays open to its key. */
|
|
1506
|
-
close() {
|
|
1507
|
-
const group = this.open;
|
|
1508
|
-
this.open = null;
|
|
1509
|
-
this.byEvent = false;
|
|
1510
|
-
if (group && group.key !== void 0 && this.undoStack[this.undoStack.length - 1] === group) this.coalescing = group;
|
|
1511
|
-
}
|
|
1512
|
-
endOpenGroups() {
|
|
1513
|
-
this.depth = 0;
|
|
1514
|
-
if (this.open) this.close();
|
|
1515
|
-
}
|
|
1516
|
-
run(group, direction) {
|
|
1517
|
-
const inverse = { name: group.name, named: true, actions: [], key: void 0 };
|
|
1518
|
-
this.open = inverse;
|
|
1519
|
-
this.byEvent = false;
|
|
1520
|
-
if (direction === "undo") this.undoing = true;
|
|
1521
|
-
else this.redoing = true;
|
|
1522
|
-
try {
|
|
1523
|
-
for (let i = group.actions.length - 1; i >= 0; i -= 1) group.actions[i].undo();
|
|
1524
|
-
} finally {
|
|
1525
|
-
this.undoing = false;
|
|
1526
|
-
this.redoing = false;
|
|
1527
|
-
this.open = null;
|
|
1528
|
-
if (inverse.actions.length > 0) {
|
|
1529
|
-
if (direction === "undo") this.redoStack.push(inverse);
|
|
1530
|
-
else this.push(inverse);
|
|
1531
|
-
}
|
|
1532
|
-
this.changed();
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
changed() {
|
|
1536
|
-
const next = { canUndo: this.canUndo, canRedo: this.canRedo, undoActionName: this.undoActionName, redoActionName: this.redoActionName };
|
|
1537
|
-
const last = this.snapshot;
|
|
1538
|
-
if (next.canUndo === last.canUndo && next.canRedo === last.canRedo && next.undoActionName === last.undoActionName && next.redoActionName === last.redoActionName) return;
|
|
1539
|
-
this.snapshot = next;
|
|
1540
|
-
this.host?.update(next);
|
|
1541
|
-
for (const listener of [...this.listeners]) listener();
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
const UndoManagerContext = createContext(null);
|
|
1545
|
-
let shared = null;
|
|
1546
|
-
function sharedUndoManager() {
|
|
1547
|
-
shared ??= new UndoManager();
|
|
1548
|
-
return shared;
|
|
1549
|
-
}
|
|
1550
|
-
function useUndoManager() {
|
|
1551
|
-
const manager = useContext(UndoManagerContext) ?? sharedUndoManager();
|
|
1552
|
-
useSyncExternalStore(
|
|
1553
|
-
manager.subscribe,
|
|
1554
|
-
() => manager.state,
|
|
1555
|
-
() => manager.state
|
|
1556
|
-
);
|
|
1557
|
-
return manager;
|
|
1558
|
-
}
|
|
1559
|
-
const OWN = [
|
|
1560
|
-
EnvironmentContext,
|
|
1561
|
-
ViewEnvironmentContext,
|
|
1562
|
-
NavigationContext,
|
|
1563
|
-
DismissContext,
|
|
1564
|
-
UndoManagerContext
|
|
1565
|
-
];
|
|
1566
|
-
function useContextBridge(contexts = [], options = {}) {
|
|
1567
|
-
const own = options.environment === false ? OWN.filter((context) => context !== EnvironmentContext) : OWN;
|
|
1568
|
-
const all = [...own, ...contexts];
|
|
1569
|
-
const values = all.map((context) => useContext(context));
|
|
1570
|
-
return (children) => all.reduceRight((inner, context, index) => createElement(context.Provider, { value: values[index] }, inner), children);
|
|
1571
|
-
}
|
|
1572
|
-
const WINDOW_TOP_INSET = 10;
|
|
1573
|
-
function insetsOf(safeArea, fit) {
|
|
1574
|
-
const given = typeof safeArea === "number" ? { top: safeArea } : safeArea ?? { top: fit === "fill" ? WINDOW_TOP_INSET : 0 };
|
|
1575
|
-
return { top: given.top ?? 0, leading: given.leading ?? 0, bottom: given.bottom ?? 0, trailing: given.trailing ?? 0 };
|
|
1576
|
-
}
|
|
1577
|
-
function SwiftUIView({
|
|
1578
|
-
children,
|
|
1579
|
-
fit = "fill",
|
|
1580
|
-
colorScheme = "light",
|
|
1581
|
-
dynamicTypeSize = "large",
|
|
1582
|
-
contexts,
|
|
1583
|
-
assets,
|
|
1584
|
-
safeArea,
|
|
1585
|
-
history = true,
|
|
1586
|
-
keyboard = fit === "fill",
|
|
1587
|
-
sidebarTitleBar = true,
|
|
1588
|
-
className,
|
|
1589
|
-
style
|
|
1590
|
-
}) {
|
|
1591
|
-
const device = useRef(null);
|
|
1592
|
-
const screen = useRef(null);
|
|
1593
|
-
const mounted = useRef(null);
|
|
1594
|
-
const bridge = useContextBridge(contexts, { environment: false });
|
|
1595
|
-
const tree = bridge(children);
|
|
1596
|
-
const latest = useRef(tree);
|
|
1597
|
-
latest.current = tree;
|
|
1598
|
-
useLayoutEffect(() => {
|
|
1599
|
-
if (!screen.current) return;
|
|
1600
|
-
const instance = mount(screen.current, latest.current, {
|
|
1601
|
-
colorScheme,
|
|
1602
|
-
dynamicTypeSize,
|
|
1603
|
-
safeArea: insetsOf(safeArea, fit),
|
|
1604
|
-
contentHeight: fit === "content",
|
|
1605
|
-
history,
|
|
1606
|
-
keyboard,
|
|
1607
|
-
...assets ? { assets } : {}
|
|
1608
|
-
});
|
|
1609
|
-
mounted.current = instance;
|
|
1610
|
-
return () => {
|
|
1611
|
-
mounted.current = null;
|
|
1612
|
-
instance.unmount();
|
|
1613
|
-
};
|
|
1614
|
-
}, [fit, history, keyboard]);
|
|
1615
|
-
useLayoutEffect(() => {
|
|
1616
|
-
if (mounted.current) mounted.current.renderer.sidebarTitleBar = sidebarTitleBar;
|
|
1617
|
-
}, [sidebarTitleBar, fit, history, keyboard]);
|
|
1618
|
-
useLayoutEffect(() => {
|
|
1619
|
-
mounted.current?.root.render(tree);
|
|
1620
|
-
});
|
|
1621
|
-
const insets2 = insetsOf(safeArea, fit);
|
|
1622
|
-
const insetsKey = `${insets2.top},${insets2.leading},${insets2.bottom},${insets2.trailing}`;
|
|
1623
|
-
useLayoutEffect(() => {
|
|
1624
|
-
mounted.current?.renderer.setSafeArea(insets2);
|
|
1625
|
-
}, [insetsKey]);
|
|
1626
|
-
useLayoutEffect(() => {
|
|
1627
|
-
if (device.current) applyTypeSizeVariables(device.current, dynamicTypeSize, mounted.current?.renderer.platform);
|
|
1628
|
-
mounted.current?.setEnvironment({ colorScheme, dynamicTypeSize });
|
|
1629
|
-
}, [colorScheme, dynamicTypeSize]);
|
|
1630
|
-
const classes = ["device", "sb-island", className].filter(Boolean).join(" ");
|
|
1631
|
-
return /* @__PURE__ */ jsx("div", { ref: device, className: classes, "data-theme": colorScheme, "data-type-size": dynamicTypeSize, "data-state": "ready", "data-sb-fit": fit, style, children: /* @__PURE__ */ jsx("div", { className: "device-screen", children: /* @__PURE__ */ jsx("div", { ref: screen, className: "screen" }) }) });
|
|
1632
|
-
}
|
|
1633
|
-
function readBinding(value, onChange) {
|
|
1634
|
-
if (Array.isArray(value) && value.length === 2 && typeof value[1] === "function") {
|
|
1635
|
-
const [current, set] = value;
|
|
1636
|
-
return [current, set];
|
|
1637
|
-
}
|
|
1638
|
-
return [value, onChange ?? (() => {
|
|
1639
|
-
})];
|
|
1640
|
-
}
|
|
1641
|
-
const CoordinateSpacesContext = createContext({});
|
|
1642
|
-
function useCoordinateSpaces() {
|
|
1643
|
-
return useContext(CoordinateSpacesContext);
|
|
1644
|
-
}
|
|
1645
|
-
function CoordinateSpace({ name, children }) {
|
|
1646
|
-
const spaces = useContext(CoordinateSpacesContext);
|
|
1647
|
-
const [frame2, setFrame] = useState(null);
|
|
1648
|
-
return /* @__PURE__ */ jsx(CoordinateSpacesContext.Provider, { value: { ...spaces, [name]: frame2 }, children: sb(
|
|
1649
|
-
"zstack",
|
|
1650
|
-
{ alignment: "center", reportsSize: true, reportsFrame: true },
|
|
1651
|
-
{
|
|
1652
|
-
geometry: (event) => {
|
|
1653
|
-
const next = { x: event.x ?? 0, y: event.y ?? 0, width: event.width, height: event.height };
|
|
1654
|
-
if (!frame2 || frame2.x !== next.x || frame2.y !== next.y || frame2.width !== next.width || frame2.height !== next.height) setFrame(next);
|
|
1655
|
-
}
|
|
1656
|
-
},
|
|
1657
|
-
children
|
|
1658
|
-
) });
|
|
1659
|
-
}
|
|
1660
|
-
let active = null;
|
|
1661
|
-
function Draggable({ payload, children }) {
|
|
1662
|
-
return sb(
|
|
1663
|
-
"draggable",
|
|
1664
|
-
{},
|
|
1665
|
-
{
|
|
1666
|
-
dragstart: (event) => {
|
|
1667
|
-
active = { id: event.id, payload };
|
|
1668
|
-
},
|
|
1669
|
-
dragend: (event) => {
|
|
1670
|
-
if (active?.id === event.id) active = null;
|
|
1671
|
-
}
|
|
1672
|
-
},
|
|
1673
|
-
children
|
|
1674
|
-
);
|
|
1675
|
-
}
|
|
1676
|
-
function itemValue(item) {
|
|
1677
|
-
if (item.text !== void 0) {
|
|
1678
|
-
if (item.type === "text/uri-list") {
|
|
1679
|
-
try {
|
|
1680
|
-
return new URL(item.text.split(/\r?\n/)[0].trim());
|
|
1681
|
-
} catch {
|
|
1682
|
-
return item.text;
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
return item.text;
|
|
1686
|
-
}
|
|
1687
|
-
const name = item.path ?? item.name ?? "file";
|
|
1688
|
-
if (item.file) {
|
|
1689
|
-
const file = item.file;
|
|
1690
|
-
return item.path !== void 0 && item.path !== file.name ? new File([file], item.path, { type: file.type, lastModified: file.lastModified }) : file;
|
|
1691
|
-
}
|
|
1692
|
-
if (item.url !== void 0 && item.data === void 0) {
|
|
1693
|
-
const fromReference = browserEnvironment.fileFromReference;
|
|
1694
|
-
if (fromReference) {
|
|
1695
|
-
return fromReference({ type: item.type, name, url: item.url, ...item.path !== void 0 ? { path: item.path } : {}, ...item.size !== void 0 ? { size: item.size } : {} });
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
const binary = atob(item.data ?? "");
|
|
1699
|
-
const bytes = new Uint8Array(binary.length);
|
|
1700
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1701
|
-
return typeof File !== "undefined" ? new File([bytes], name, { type: item.type }) : bytes;
|
|
1702
|
-
}
|
|
1703
|
-
function DropDestination({ action, isTargeted, accepts, children }) {
|
|
1704
|
-
return sb(
|
|
1705
|
-
"dropdestination",
|
|
1706
|
-
{ accepts: accepts ?? [] },
|
|
1707
|
-
{
|
|
1708
|
-
drop: (event) => {
|
|
1709
|
-
if (event.phase === "entered") {
|
|
1710
|
-
isTargeted?.(true);
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
isTargeted?.(false);
|
|
1714
|
-
if (event.phase !== "performed") return;
|
|
1715
|
-
let items;
|
|
1716
|
-
if (event.source !== void 0) items = active && active.id === event.source ? [active.payload] : [];
|
|
1717
|
-
else items = (event.items ?? []).map(itemValue);
|
|
1718
|
-
if (items.length > 0) action(items, { x: event.x, y: event.y });
|
|
1719
|
-
}
|
|
1720
|
-
},
|
|
1721
|
-
children
|
|
1722
|
-
);
|
|
1723
|
-
}
|
|
1724
|
-
function FileImporterPresenter(spec) {
|
|
1725
|
-
const [presented, setPresented] = readBinding(spec.isPresented);
|
|
1726
|
-
const latest = useRef(spec);
|
|
1727
|
-
latest.current = spec;
|
|
1728
|
-
const choosing = useRef(false);
|
|
1729
|
-
useLayoutEffect(() => {
|
|
1730
|
-
if (!presented || choosing.current) return;
|
|
1731
|
-
const { allowedContentTypes, allowsMultipleSelection } = latest.current;
|
|
1732
|
-
const pick = browserEnvironment.pickFiles;
|
|
1733
|
-
if (!pick) {
|
|
1734
|
-
setPresented(false);
|
|
1735
|
-
latest.current.onCancellation?.();
|
|
1736
|
-
return;
|
|
1737
|
-
}
|
|
1738
|
-
choosing.current = true;
|
|
1739
|
-
void pick({ accept: allowedContentTypes.join(","), multiple: allowsMultipleSelection === true }).then((files) => {
|
|
1740
|
-
choosing.current = false;
|
|
1741
|
-
setPresented(false);
|
|
1742
|
-
if (files.length > 0) latest.current.onCompletion(files);
|
|
1743
|
-
else latest.current.onCancellation?.();
|
|
1744
|
-
});
|
|
1745
|
-
}, [presented, setPresented]);
|
|
1746
|
-
return null;
|
|
1747
|
-
}
|
|
1748
|
-
const EXTENSIONS = {
|
|
1749
|
-
"text/plain": "txt",
|
|
1750
|
-
"text/csv": "csv",
|
|
1751
|
-
"text/markdown": "md",
|
|
1752
|
-
"text/html": "html",
|
|
1753
|
-
"application/json": "json",
|
|
1754
|
-
"application/pdf": "pdf",
|
|
1755
|
-
"image/png": "png",
|
|
1756
|
-
"image/jpeg": "jpg",
|
|
1757
|
-
"image/svg+xml": "svg",
|
|
1758
|
-
"audio/mp4": "m4a",
|
|
1759
|
-
"video/mp4": "mp4"
|
|
1760
|
-
};
|
|
1761
|
-
function exportFile(document2, contentType, defaultFilename, index = 0) {
|
|
1762
|
-
const type = document2 instanceof Blob && document2.type || contentType || "application/octet-stream";
|
|
1763
|
-
let name = defaultFilename ?? (document2 instanceof File ? document2.name : index === 0 ? "Untitled" : `Untitled ${index + 1}`);
|
|
1764
|
-
name = name.replace(/[\\/:*?"<>|]+/g, "-").trim() || "Untitled";
|
|
1765
|
-
const extension = EXTENSIONS[type.split(";")[0].trim()];
|
|
1766
|
-
if (extension && !/\.[A-Za-z0-9]{1,8}$/.test(name)) name = `${name}.${extension}`;
|
|
1767
|
-
if (document2 instanceof File && document2.name === name && document2.type === type) return document2;
|
|
1768
|
-
const bytes = typeof document2 === "string" ? new TextEncoder().encode(document2) : document2;
|
|
1769
|
-
return new File([bytes], name, { type });
|
|
1770
|
-
}
|
|
1771
|
-
function FileExporterPresenter(spec) {
|
|
1772
|
-
const [presented, setPresented] = readBinding(spec.isPresented);
|
|
1773
|
-
const latest = useRef(spec);
|
|
1774
|
-
latest.current = spec;
|
|
1775
|
-
const exporting = useRef(false);
|
|
1776
|
-
useLayoutEffect(() => {
|
|
1777
|
-
if (!presented || exporting.current) return;
|
|
1778
|
-
const { document: document2, contentType, defaultFilename } = latest.current;
|
|
1779
|
-
const documents = document2 === null ? [] : Array.isArray(document2) ? document2 : [document2];
|
|
1780
|
-
if (documents.length === 0) {
|
|
1781
|
-
setPresented(false);
|
|
1782
|
-
latest.current.onCancellation?.();
|
|
1783
|
-
return;
|
|
1784
|
-
}
|
|
1785
|
-
exporting.current = true;
|
|
1786
|
-
const files = documents.map((item, index) => exportFile(item, contentType, defaultFilename, index));
|
|
1787
|
-
exportFiles(files).then(
|
|
1788
|
-
(result) => {
|
|
1789
|
-
exporting.current = false;
|
|
1790
|
-
setPresented(false);
|
|
1791
|
-
if (result.outcome === "cancelled") latest.current.onCancellation?.();
|
|
1792
|
-
else latest.current.onCompletion?.(result);
|
|
1793
|
-
},
|
|
1794
|
-
(error) => {
|
|
1795
|
-
exporting.current = false;
|
|
1796
|
-
setPresented(false);
|
|
1797
|
-
latest.current.onError?.(error);
|
|
1798
|
-
}
|
|
1799
|
-
);
|
|
1800
|
-
}, [presented, setPresented]);
|
|
1801
|
-
return null;
|
|
1802
|
-
}
|
|
1803
|
-
const ListSelectionContext = createContext(null);
|
|
1804
|
-
function Row({ tag, onDelete, deletable, onMove, movable, index, containerIndex, children }) {
|
|
1805
|
-
const selection = useContext(ListSelectionContext);
|
|
1806
|
-
const selectable = selection !== null && tag !== void 0;
|
|
1807
|
-
const canDelete = onDelete !== void 0 && deletable !== false;
|
|
1808
|
-
const canMove = onMove !== void 0 && movable !== false;
|
|
1809
|
-
if (!selectable && !canDelete && !canMove) return children;
|
|
1810
|
-
const props = {};
|
|
1811
|
-
if (selectable) {
|
|
1812
|
-
props["selectable"] = true;
|
|
1813
|
-
props["selected"] = selection.isSelected(tag);
|
|
1814
|
-
}
|
|
1815
|
-
if (canDelete) props["deletable"] = true;
|
|
1816
|
-
if (canMove) props["movable"] = true;
|
|
1817
|
-
return sb(
|
|
1818
|
-
"listrow",
|
|
1819
|
-
props,
|
|
1820
|
-
{
|
|
1821
|
-
tap: () => selectable && selection.select(tag),
|
|
1822
|
-
delete: () => onDelete?.(),
|
|
1823
|
-
move: (event) => {
|
|
1824
|
-
const start = (containerIndex ?? index ?? 0) - (index ?? 0);
|
|
1825
|
-
onMove?.(Math.max(0, event.to - start));
|
|
1826
|
-
}
|
|
1827
|
-
},
|
|
1828
|
-
children
|
|
1829
|
-
);
|
|
1830
|
-
}
|
|
1831
|
-
const isPoint = (value) => typeof value === "object" && value !== null && ("x" in value || "y" in value);
|
|
1832
|
-
function command(request) {
|
|
1833
|
-
return request.axes ? { anchor: request.anchor, serial: request.serial, axes: request.axes } : { anchor: request.anchor, serial: request.serial };
|
|
1834
|
-
}
|
|
1835
|
-
function offsetCommand(request) {
|
|
1836
|
-
const out = { serial: request.serial };
|
|
1837
|
-
if (typeof request.point.x === "number") out.x = request.point.x;
|
|
1838
|
-
if (typeof request.point.y === "number") out.y = request.point.y;
|
|
1839
|
-
return out;
|
|
1504
|
+
function offsetCommand(request) {
|
|
1505
|
+
const out = { serial: request.serial };
|
|
1506
|
+
if (typeof request.point.x === "number") out.x = request.point.x;
|
|
1507
|
+
if (typeof request.point.y === "number") out.y = request.point.y;
|
|
1508
|
+
return out;
|
|
1840
1509
|
}
|
|
1841
1510
|
const ScrollRequestContext = createContext(null);
|
|
1842
1511
|
let nextSerial = 1;
|
|
@@ -1956,29 +1625,49 @@ function marginedContent(children, margins, axis) {
|
|
|
1956
1625
|
}
|
|
1957
1626
|
const LAZY_BATCH = 12;
|
|
1958
1627
|
const LazyContext = createContext(null);
|
|
1628
|
+
const LazyBatchContext = createContext(LAZY_BATCH);
|
|
1629
|
+
const LAZY_GRID_BATCH = 48;
|
|
1630
|
+
const LazyWindowContext = createContext(false);
|
|
1631
|
+
const LazyStackContext = createContext(false);
|
|
1959
1632
|
function LazyGroup({ rows, start = 0, wrap: wrap2 }) {
|
|
1960
1633
|
const axis = useContext(LazyContext);
|
|
1634
|
+
const batch = useContext(LazyBatchContext);
|
|
1961
1635
|
const request = useContext(ScrollRequestContext);
|
|
1962
|
-
const
|
|
1636
|
+
const windowed = useContext(LazyWindowContext) && useContext(LazyStackContext) && axis !== null;
|
|
1637
|
+
const [count, setCount] = useState(batch);
|
|
1638
|
+
const [front, setFront] = useState({ from: 0, extents: [] });
|
|
1963
1639
|
const target = request && "id" in request ? rows.findIndex((row) => rowMatches(row, request.id)) : -1;
|
|
1964
|
-
const needed = target >= 0 ? Math.ceil((target + 1) /
|
|
1640
|
+
const needed = target >= 0 ? Math.ceil((target + 1) / batch) * batch : 0;
|
|
1965
1641
|
useEffect(() => {
|
|
1966
1642
|
if (needed > count) setCount(needed);
|
|
1967
|
-
|
|
1643
|
+
if (target >= 0 && target < front.from) setFront({ from: Math.floor(target / batch) * batch, extents: front.extents.slice(0, Math.floor(target / batch)) });
|
|
1644
|
+
}, [needed, count, target, front, batch]);
|
|
1968
1645
|
const visible = Math.max(count, needed);
|
|
1969
|
-
const
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
return
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
{
|
|
1977
|
-
)
|
|
1978
|
-
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1646
|
+
const from = windowed ? Math.min(front.from, Math.max(0, visible - batch)) : 0;
|
|
1647
|
+
const shown = axis === null ? rows : rows.slice(from, visible);
|
|
1648
|
+
const built = shown.map((row, index) => wrap2 ? wrap2(row, start + from + index) : row);
|
|
1649
|
+
if (axis === null || !windowed && shown.length >= rows.length) return built;
|
|
1650
|
+
const ask = (event) => {
|
|
1651
|
+
if (event.drop && event.drop > 0) {
|
|
1652
|
+
const drop = Math.min(event.drop, shown.length - batch);
|
|
1653
|
+
if (drop > 0) setFront({ from: from + drop, extents: [...front.extents, ...(event.extents ?? []).slice(0, Math.ceil(drop / batch))] });
|
|
1654
|
+
} else if (event.dropEnd && event.dropEnd > 0) {
|
|
1655
|
+
setCount(Math.max(from + batch, visible - event.dropEnd));
|
|
1656
|
+
} else if (from > 0) {
|
|
1657
|
+
setFront({ from: Math.max(0, from - batch), extents: front.extents.slice(0, -1) });
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
const leading = windowed ? [createElement(LazySpacer, { key: `lazy-lead-${from}`, axis, remaining: from, edge: "leading", extent: front.extents.reduce((a, b) => a + b, 0), built: shown.length, batch, ask })] : [];
|
|
1661
|
+
const trailing = visible < rows.length ? [createElement(LazySpacer, { key: `lazy-${visible}`, axis, remaining: rows.length - visible, ask: () => setCount(visible + batch) })] : [];
|
|
1662
|
+
return [...leading, ...built, ...trailing];
|
|
1663
|
+
}
|
|
1664
|
+
function LazySpacer({
|
|
1665
|
+
axis,
|
|
1666
|
+
remaining,
|
|
1667
|
+
ask,
|
|
1668
|
+
...leading
|
|
1669
|
+
}) {
|
|
1670
|
+
return sb("lazyspacer", { axis, remaining, ...leading }, { lazy: ask });
|
|
1982
1671
|
}
|
|
1983
1672
|
function rowMatches(row, id) {
|
|
1984
1673
|
if (row.key !== null && row.key === String(id)) return true;
|
|
@@ -2008,6 +1697,11 @@ function HStack(props) {
|
|
|
2008
1697
|
if (own.pinnedViews && own.pinnedViews.length > 0) stack["pinned"] = own.pinnedViews;
|
|
2009
1698
|
return applyModifiers(sb("hstack", stack, void 0, pinning(own.pinnedViews, own.children)), modifiers);
|
|
2010
1699
|
}
|
|
1700
|
+
function FlowStack(props) {
|
|
1701
|
+
const { own, modifiers } = splitProps(props);
|
|
1702
|
+
const stack = { spacing: own.spacing ?? null, lineSpacing: own.lineSpacing ?? null, alignment: own.alignment ?? "center" };
|
|
1703
|
+
return applyModifiers(sb("flowstack", stack, void 0, own.children), modifiers);
|
|
1704
|
+
}
|
|
2011
1705
|
function ZStack(props) {
|
|
2012
1706
|
const { own, modifiers } = splitProps(props);
|
|
2013
1707
|
return applyModifiers(sb("zstack", { alignment: own.alignment ?? "center" }, void 0, own.children), modifiers);
|
|
@@ -2140,547 +1834,910 @@ function keyOf(element, index) {
|
|
|
2140
1834
|
const id = element.id;
|
|
2141
1835
|
if (typeof id === "string" || typeof id === "number") return id;
|
|
2142
1836
|
}
|
|
2143
|
-
return index;
|
|
1837
|
+
return index;
|
|
1838
|
+
}
|
|
1839
|
+
function flattenChildren(children, options = {}) {
|
|
1840
|
+
const result = [];
|
|
1841
|
+
const visit = (node) => {
|
|
1842
|
+
if (node === null || node === void 0 || typeof node === "boolean") return;
|
|
1843
|
+
if (Array.isArray(node)) {
|
|
1844
|
+
node.forEach(visit);
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
if (!isValidElement(node)) return;
|
|
1848
|
+
const element = node;
|
|
1849
|
+
if (element.type === Fragment) {
|
|
1850
|
+
const inner = element.props["children"];
|
|
1851
|
+
if (element.key !== null && isValidElement(inner) && inner.key === null && inner.type !== Fragment) {
|
|
1852
|
+
visit({ ...inner, key: element.key });
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1855
|
+
visit(inner);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
if (element.type === ForEach) {
|
|
1859
|
+
visit(ForEach(element.props));
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
if (element.type === LazyGroup && !options.keepLazy) {
|
|
1863
|
+
visit(element.props.rows);
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
result.push(element);
|
|
1867
|
+
};
|
|
1868
|
+
visit(children);
|
|
1869
|
+
return result;
|
|
1870
|
+
}
|
|
1871
|
+
function GridItem(spec = {}) {
|
|
1872
|
+
const dimension = (n) => n === void 0 || n === Infinity ? "infinity" : n;
|
|
1873
|
+
let size;
|
|
1874
|
+
if (spec.size && "fixed" in spec.size) size = { kind: "fixed", value: spec.size.fixed };
|
|
1875
|
+
else if (spec.size && "adaptive" in spec.size) {
|
|
1876
|
+
size = { kind: "adaptive", minimum: spec.size.adaptive.minimum, maximum: dimension(spec.size.adaptive.maximum) };
|
|
1877
|
+
} else {
|
|
1878
|
+
const flexible = spec.size && "flexible" in spec.size ? spec.size.flexible : {};
|
|
1879
|
+
size = { kind: "flexible", minimum: flexible.minimum ?? 10, maximum: dimension(flexible.maximum) };
|
|
1880
|
+
}
|
|
1881
|
+
return { size, spacing: spec.spacing ?? null, alignment: spec.alignment ?? null };
|
|
1882
|
+
}
|
|
1883
|
+
GridItem.flexible = (options = {}) => GridItem({ size: { flexible: options }, spacing: options.spacing, alignment: options.alignment });
|
|
1884
|
+
GridItem.fixed = (value, options = {}) => GridItem({ size: { fixed: value }, spacing: options.spacing, alignment: options.alignment });
|
|
1885
|
+
GridItem.adaptive = (options) => GridItem({ size: { adaptive: options }, spacing: options.spacing, alignment: options.alignment });
|
|
1886
|
+
function lazyCells(axis, children) {
|
|
1887
|
+
return createElement(LazyContext.Provider, { value: axis }, createElement(LazyStackContext.Provider, { value: false }, createElement(LazyBatchContext.Provider, { value: LAZY_GRID_BATCH }, children)));
|
|
1888
|
+
}
|
|
1889
|
+
function LazyVGrid(props) {
|
|
1890
|
+
const { own, modifiers } = splitProps(props);
|
|
1891
|
+
const grid = { columns: own.columns, spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
1892
|
+
if (own.pinnedViews && own.pinnedViews.length > 0) grid["pinned"] = own.pinnedViews;
|
|
1893
|
+
return applyModifiers(sb("lazyvgrid", grid, void 0, lazyCells("vertical", pinning(own.pinnedViews, own.children))), modifiers);
|
|
1894
|
+
}
|
|
1895
|
+
function LazyHGrid(props) {
|
|
1896
|
+
const { own, modifiers } = splitProps(props);
|
|
1897
|
+
const grid = { rows: own.rows, spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
1898
|
+
if (own.pinnedViews && own.pinnedViews.length > 0) grid["pinned"] = own.pinnedViews;
|
|
1899
|
+
return applyModifiers(sb("lazyhgrid", grid, void 0, lazyCells("horizontal", pinning(own.pinnedViews, own.children))), modifiers);
|
|
1900
|
+
}
|
|
1901
|
+
function Grid(props) {
|
|
1902
|
+
const { own, modifiers } = splitProps(props);
|
|
1903
|
+
return applyModifiers(
|
|
1904
|
+
sb(
|
|
1905
|
+
"grid",
|
|
1906
|
+
{ horizontalSpacing: own.horizontalSpacing ?? null, verticalSpacing: own.verticalSpacing ?? null, alignment: own.alignment ?? "center" },
|
|
1907
|
+
void 0,
|
|
1908
|
+
own.children
|
|
1909
|
+
),
|
|
1910
|
+
modifiers
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
function GridRow(props) {
|
|
1914
|
+
const { own, modifiers } = splitProps(props);
|
|
1915
|
+
return applyModifiers(sb("gridrow", { alignment: own.alignment ?? null }, void 0, own.children), modifiers);
|
|
1916
|
+
}
|
|
1917
|
+
function runStyleOf(props, inherited, nested) {
|
|
1918
|
+
const style = { ...inherited };
|
|
1919
|
+
if (props.italic) style.italic = true;
|
|
1920
|
+
if (props.underline) style.underline = typeof props.underline === "object" && props.underline.color ? { color: color(props.underline.color) } : {};
|
|
1921
|
+
if (props.strikethrough) {
|
|
1922
|
+
style.strikethrough = typeof props.strikethrough === "object" && props.strikethrough.color ? { color: color(props.strikethrough.color) } : {};
|
|
1923
|
+
}
|
|
1924
|
+
const kerning = props.tracking ?? props.kerning;
|
|
1925
|
+
if (kerning !== void 0) style.kerning = kerning;
|
|
1926
|
+
if (props.baselineOffset !== void 0) style.baselineOffset = props.baselineOffset;
|
|
1927
|
+
if (props.link) style.link = props.link;
|
|
1928
|
+
if (nested) {
|
|
1929
|
+
let runFont2 = props.font !== void 0 ? font(props.font) : void 0;
|
|
1930
|
+
if (props.bold) runFont2 = { ...runFont2 ?? {}, weight: "bold" };
|
|
1931
|
+
if (props.fontWeight) runFont2 = { ...runFont2 ?? {}, weight: props.fontWeight };
|
|
1932
|
+
if (props.monospacedDigit) runFont2 = { ...runFont2 ?? {}, monospacedDigit: true };
|
|
1933
|
+
if (runFont2) style.font = { ...style.font ?? {}, ...runFont2 };
|
|
1934
|
+
if (props.foregroundStyle !== void 0) {
|
|
1935
|
+
style.foreground = shapeStyle(Array.isArray(props.foregroundStyle) ? props.foregroundStyle[0] : props.foregroundStyle);
|
|
1936
|
+
}
|
|
1937
|
+
const background = runBackground(props.background);
|
|
1938
|
+
if (background) style.background = background;
|
|
1939
|
+
}
|
|
1940
|
+
return style;
|
|
1941
|
+
}
|
|
1942
|
+
function runBackground(value) {
|
|
1943
|
+
if (typeof value === "string") {
|
|
1944
|
+
const made = color(value);
|
|
1945
|
+
return "hierarchical" in made ? void 0 : made;
|
|
1946
|
+
}
|
|
1947
|
+
if (typeof value !== "object" || value === null || isValidElement(value) || "in" in value) return void 0;
|
|
1948
|
+
return "r" in value || "name" in value || "named" in value ? value : void 0;
|
|
1949
|
+
}
|
|
1950
|
+
function segmentsOf(children, style, into) {
|
|
1951
|
+
const visit = (node) => {
|
|
1952
|
+
if (node === null || node === void 0 || typeof node === "boolean") return;
|
|
1953
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
1954
|
+
const last = into[into.length - 1];
|
|
1955
|
+
if (last && "text" in last && last.style === style) last.text += String(node);
|
|
1956
|
+
else into.push({ text: String(node), style });
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
if (Array.isArray(node)) {
|
|
1960
|
+
node.forEach(visit);
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
if (!isValidElement(node)) return;
|
|
1964
|
+
const element = node;
|
|
1965
|
+
if (element.type === Fragment) {
|
|
1966
|
+
visit(element.props["children"]);
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
if (element.type === Text) {
|
|
1970
|
+
const props = element.props;
|
|
1971
|
+
segmentsOf(props.children, runStyleOf(props, style, true), into);
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
if (element.type === Image$1) {
|
|
1975
|
+
const props = element.props;
|
|
1976
|
+
into.push({ image: imageProps$1(props), style });
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
visit(children);
|
|
1981
|
+
}
|
|
1982
|
+
function isPlainStyle(style) {
|
|
1983
|
+
return Object.keys(style).length === 0;
|
|
1984
|
+
}
|
|
1985
|
+
function Text(props) {
|
|
1986
|
+
const { own, modifiers } = splitProps(props);
|
|
1987
|
+
const environment = useViewEnvironment();
|
|
1988
|
+
const style = runStyleOf(props, {}, false);
|
|
1989
|
+
const segments = [];
|
|
1990
|
+
segmentsOf(own.children, style, segments);
|
|
1991
|
+
const textCase = takeModifier(modifiers, "textCase") ?? environment.textCase;
|
|
1992
|
+
if (textCase) {
|
|
1993
|
+
for (const segment of segments) {
|
|
1994
|
+
if ("text" in segment) segment.text = textCase === "uppercase" ? segment.text.toUpperCase() : segment.text.toLowerCase();
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
const redacted = takeModifier(modifiers, "redacted") ?? environment.redacted;
|
|
1998
|
+
const content = segments.map((segment) => "text" in segment ? segment.text : "").join("");
|
|
1999
|
+
const plain2 = segments.length <= 1 && (segments.length === 0 || "text" in segments[0] && isPlainStyle(segments[0].style));
|
|
2000
|
+
if (plain2) return applyModifiers(placeholder(sb("text", { text: content }), redacted), modifiers);
|
|
2001
|
+
const runs = segments.map((segment) => {
|
|
2002
|
+
const run = { ...segment.style };
|
|
2003
|
+
if ("text" in segment) run["text"] = segment.text;
|
|
2004
|
+
else run["image"] = segment.image;
|
|
2005
|
+
return run;
|
|
2006
|
+
});
|
|
2007
|
+
const hasLinks = segments.some((segment) => segment.style.link);
|
|
2008
|
+
const handlers = hasLinks ? { link: (event) => openURL(event.value) } : void 0;
|
|
2009
|
+
return applyModifiers(placeholder(sb("text", { text: content, runs }, handlers), redacted), modifiers);
|
|
2010
|
+
}
|
|
2011
|
+
function placeholder(node, redacted) {
|
|
2012
|
+
if (!redacted) return node;
|
|
2013
|
+
return styled({ background: { hierarchical: 3 }, backgroundCornerRadius: 4 }, styled({ foreground: { name: "clear" } }, node));
|
|
2014
|
+
}
|
|
2015
|
+
function openURL(url) {
|
|
2016
|
+
const native = globalThis.__sbNative;
|
|
2017
|
+
if (native?.openURL) {
|
|
2018
|
+
native.openURL(url);
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
if (typeof window !== "undefined") window.open(url, "_blank", "noopener");
|
|
2022
|
+
}
|
|
2023
|
+
function imageProps$1(props) {
|
|
2024
|
+
if (props.systemName !== void 0) return { systemName: props.systemName };
|
|
2025
|
+
if (props.bitmap !== void 0) {
|
|
2026
|
+
const { source, steps = [], version } = props.bitmap;
|
|
2027
|
+
const extent = bitmapExtent(source, steps);
|
|
2028
|
+
const finite = Number.isFinite(extent.width) && Number.isFinite(extent.height);
|
|
2029
|
+
const width = finite ? Math.max(0, Math.round(extent.width)) : 0;
|
|
2030
|
+
const height = finite ? Math.max(0, Math.round(extent.height)) : 0;
|
|
2031
|
+
const scale = props.scale !== void 0 && props.scale > 0 ? props.scale : 1;
|
|
2032
|
+
return {
|
|
2033
|
+
bitmap: { source: source?.key ?? null, steps, width, height, ...version !== void 0 ? { version } : {} },
|
|
2034
|
+
resizable: props.resizable ?? false,
|
|
2035
|
+
width: width / scale,
|
|
2036
|
+
height: height / scale,
|
|
2037
|
+
...props.interpolation === "none" ? { interpolation: "none" } : {}
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
if (props.url !== void 0) return { url: props.url, resizable: props.resizable ?? false, width: props.width ?? 0, height: props.height ?? 0 };
|
|
2041
|
+
return { name: props.name ?? "", resizable: props.resizable ?? false };
|
|
2144
2042
|
}
|
|
2145
|
-
function
|
|
2146
|
-
const
|
|
2147
|
-
const
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
const element = node;
|
|
2155
|
-
if (element.type === Fragment) {
|
|
2156
|
-
const inner = element.props["children"];
|
|
2157
|
-
if (element.key !== null && isValidElement(inner) && inner.key === null && inner.type !== Fragment) {
|
|
2158
|
-
visit({ ...inner, key: element.key });
|
|
2159
|
-
return;
|
|
2160
|
-
}
|
|
2161
|
-
visit(inner);
|
|
2162
|
-
return;
|
|
2163
|
-
}
|
|
2164
|
-
if (element.type === ForEach) {
|
|
2165
|
-
visit(ForEach(element.props));
|
|
2166
|
-
return;
|
|
2167
|
-
}
|
|
2168
|
-
if (element.type === LazyGroup && !options.keepLazy) {
|
|
2169
|
-
visit(element.props.rows);
|
|
2170
|
-
return;
|
|
2171
|
-
}
|
|
2172
|
-
result.push(element);
|
|
2173
|
-
};
|
|
2174
|
-
visit(children);
|
|
2175
|
-
return result;
|
|
2043
|
+
function Image$1(props) {
|
|
2044
|
+
const { modifiers } = splitProps(props);
|
|
2045
|
+
const environment = useViewEnvironment();
|
|
2046
|
+
const redacted = takeModifier(modifiers, "redacted") ?? environment.redacted;
|
|
2047
|
+
const mode = takeModifier(modifiers, "symbolRenderingMode") ?? environment.symbolRenderingMode;
|
|
2048
|
+
const own = imageProps$1(props);
|
|
2049
|
+
const element = props.systemName !== void 0 && mode === "palette" ? { ...own, renderingMode: "palette" } : own;
|
|
2050
|
+
if (props.accessibilityLabel) element["accessibilityLabel"] = props.accessibilityLabel;
|
|
2051
|
+
return applyModifiers(placeholder(sb("image", element), redacted), modifiers);
|
|
2176
2052
|
}
|
|
2177
|
-
function
|
|
2178
|
-
const
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
const
|
|
2185
|
-
|
|
2053
|
+
function Label(props) {
|
|
2054
|
+
const { own, modifiers } = splitProps(props);
|
|
2055
|
+
const environment = useViewEnvironment();
|
|
2056
|
+
const style = takeModifier(modifiers, "labelStyle") ?? environment.labelStyle ?? "automatic";
|
|
2057
|
+
const icon = own.icon ?? (own.systemImage !== void 0 ? /* @__PURE__ */ jsx(Image$1, { systemName: own.systemImage }) : own.image !== void 0 ? /* @__PURE__ */ jsx(Image$1, { name: own.image }) : null);
|
|
2058
|
+
const title = typeof own.title === "string" || typeof own.title === "number" ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.title;
|
|
2059
|
+
if (style === "iconOnly") {
|
|
2060
|
+
const name = typeof own.title === "string" || typeof own.title === "number" ? String(own.title) : void 0;
|
|
2061
|
+
const named = own.icon === void 0 && name !== void 0 ? own.systemImage !== void 0 ? /* @__PURE__ */ jsx(Image$1, { systemName: own.systemImage, accessibilityLabel: name }) : own.image !== void 0 ? /* @__PURE__ */ jsx(Image$1, { name: own.image, accessibilityLabel: name }) : icon : icon;
|
|
2062
|
+
return applyModifiers(named, modifiers);
|
|
2186
2063
|
}
|
|
2187
|
-
|
|
2064
|
+
if (style === "titleOnly") return applyModifiers(title, modifiers);
|
|
2065
|
+
return applyModifiers(
|
|
2066
|
+
/* @__PURE__ */ jsxs(HStack, { spacing: 8, children: [
|
|
2067
|
+
style === "titleAndIcon" ? icon : styled({ labelIcon: true }, icon),
|
|
2068
|
+
title
|
|
2069
|
+
] }),
|
|
2070
|
+
modifiers
|
|
2071
|
+
);
|
|
2188
2072
|
}
|
|
2189
|
-
|
|
2190
|
-
GridItem.fixed = (value, options = {}) => GridItem({ size: { fixed: value }, spacing: options.spacing, alignment: options.alignment });
|
|
2191
|
-
GridItem.adaptive = (options) => GridItem({ size: { adaptive: options }, spacing: options.spacing, alignment: options.alignment });
|
|
2192
|
-
function LazyVGrid(props) {
|
|
2073
|
+
function LabeledContent(props) {
|
|
2193
2074
|
const { own, modifiers } = splitProps(props);
|
|
2194
|
-
const
|
|
2195
|
-
|
|
2196
|
-
|
|
2075
|
+
const label = typeof own.label === "string" || typeof own.label === "number" ? /* @__PURE__ */ jsx(Text, { children: own.label }) : own.label;
|
|
2076
|
+
const content = own.children ?? own.value;
|
|
2077
|
+
const value = typeof content === "string" || typeof content === "number" ? /* @__PURE__ */ jsx(Text, { children: content }) : content;
|
|
2078
|
+
return applyModifiers(
|
|
2079
|
+
/* @__PURE__ */ jsxs(HStack, { children: [
|
|
2080
|
+
label,
|
|
2081
|
+
sb("spacer", { minLength: null }),
|
|
2082
|
+
styled({ foreground: { hierarchical: 2 } }, value)
|
|
2083
|
+
] }),
|
|
2084
|
+
modifiers
|
|
2085
|
+
);
|
|
2197
2086
|
}
|
|
2198
|
-
function
|
|
2087
|
+
function Link(props) {
|
|
2199
2088
|
const { own, modifiers } = splitProps(props);
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
return applyModifiers(sb("lazyhgrid", grid, void 0, pinning(own.pinnedViews, own.children)), modifiers);
|
|
2089
|
+
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.children;
|
|
2090
|
+
return applyModifiers(sb("button", { role: null, style: "automatic" }, { tap: () => openURL(own.destination) }, label), modifiers);
|
|
2203
2091
|
}
|
|
2204
|
-
|
|
2092
|
+
const isPushedView = (value) => typeof value === "object" && value !== null && "view" in value && isValidElement(value.view);
|
|
2093
|
+
function routeOf(value, depth = 0) {
|
|
2094
|
+
if (depth > 8) return void 0;
|
|
2095
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
2096
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
2097
|
+
if (Array.isArray(value)) {
|
|
2098
|
+
const items = value.map((item) => routeOf(item, depth + 1));
|
|
2099
|
+
return items.every((item) => item !== void 0) ? items : void 0;
|
|
2100
|
+
}
|
|
2101
|
+
if (typeof value === "object" && !isPushedView(value)) {
|
|
2102
|
+
const proto = Object.getPrototypeOf(value);
|
|
2103
|
+
if (proto !== Object.prototype && proto !== null) return void 0;
|
|
2104
|
+
const out = {};
|
|
2105
|
+
for (const [key, item] of Object.entries(value)) {
|
|
2106
|
+
if (item === void 0) continue;
|
|
2107
|
+
const plain2 = routeOf(item, depth + 1);
|
|
2108
|
+
if (plain2 === void 0) return void 0;
|
|
2109
|
+
out[key] = plain2;
|
|
2110
|
+
}
|
|
2111
|
+
return out;
|
|
2112
|
+
}
|
|
2113
|
+
return void 0;
|
|
2114
|
+
}
|
|
2115
|
+
function NavigationStack(props) {
|
|
2116
|
+
const enclosing = useNavigation();
|
|
2117
|
+
if (enclosing) return /* @__PURE__ */ jsx(FlattenedStack, { ...props });
|
|
2118
|
+
return /* @__PURE__ */ jsx(OwnStack, { ...props });
|
|
2119
|
+
}
|
|
2120
|
+
function FlattenedStack(props) {
|
|
2205
2121
|
const { own, modifiers } = splitProps(props);
|
|
2206
2122
|
return applyModifiers(
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
{ horizontalSpacing: own.horizontalSpacing ?? null, verticalSpacing: own.verticalSpacing ?? null, alignment: own.alignment ?? "center" },
|
|
2210
|
-
void 0,
|
|
2123
|
+
/* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2124
|
+
own.destination && /* @__PURE__ */ jsx(RegisterDestination, { destination: own.destination }),
|
|
2211
2125
|
own.children
|
|
2212
|
-
),
|
|
2126
|
+
] }),
|
|
2213
2127
|
modifiers
|
|
2214
2128
|
);
|
|
2215
2129
|
}
|
|
2216
|
-
function
|
|
2130
|
+
function OwnStack(props) {
|
|
2217
2131
|
const { own, modifiers } = splitProps(props);
|
|
2218
|
-
|
|
2132
|
+
const remote = useContext(HostTreeContext)?.remote ?? false;
|
|
2133
|
+
const [internalPath, setInternalPath] = useState([]);
|
|
2134
|
+
const [path, setPath] = own.path !== void 0 ? readBinding(own.path, own.onPathChange) : [internalPath, setInternalPath];
|
|
2135
|
+
const destination = useRef(null);
|
|
2136
|
+
destination.current = own.destination ?? null;
|
|
2137
|
+
const context = {
|
|
2138
|
+
push: (value) => setPath([...path, value]),
|
|
2139
|
+
pop: () => setPath(path.slice(0, -1)),
|
|
2140
|
+
path,
|
|
2141
|
+
setPath: (next) => setPath(next),
|
|
2142
|
+
registerDestination: (builder) => {
|
|
2143
|
+
destination.current = builder;
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
const screens = [
|
|
2147
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb("navscreen", { title: "", displayMode: "automatic", depth: 0 }, { tap: context.pop }, /* @__PURE__ */ jsx(ScreenDepthContext.Provider, { value: 0, children: own.children })) }, "root")
|
|
2148
|
+
];
|
|
2149
|
+
path.forEach((value, index) => {
|
|
2150
|
+
const pop = () => setPath(path.slice(0, index));
|
|
2151
|
+
const route = remote ? routeOf(value) : void 0;
|
|
2152
|
+
screens.push(
|
|
2153
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb(
|
|
2154
|
+
"navscreen",
|
|
2155
|
+
{ title: "", displayMode: "automatic", depth: index + 1, ...route === void 0 ? {} : { route } },
|
|
2156
|
+
{ tap: pop },
|
|
2157
|
+
/* @__PURE__ */ jsx(DismissContext.Provider, { value: pop, children: /* @__PURE__ */ jsx(ScreenDepthContext.Provider, { value: index + 1, children: /* @__PURE__ */ jsx(PathScreen, { value, destination }) }) })
|
|
2158
|
+
) }, index + 1)
|
|
2159
|
+
);
|
|
2160
|
+
});
|
|
2161
|
+
return applyModifiers(
|
|
2162
|
+
sb("navstack", {}, { setpath: (event) => setPath(Array.isArray(event.path) ? event.path : []) }, /* @__PURE__ */ jsx(NavigationContext.Provider, { value: context, children: screens })),
|
|
2163
|
+
modifiers
|
|
2164
|
+
);
|
|
2219
2165
|
}
|
|
2220
|
-
function
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
const
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
if (props.monospacedDigit) runFont2 = { ...runFont2 ?? {}, monospacedDigit: true };
|
|
2236
|
-
if (runFont2) style.font = { ...style.font ?? {}, ...runFont2 };
|
|
2237
|
-
if (props.foregroundStyle !== void 0) {
|
|
2238
|
-
style.foreground = shapeStyle(Array.isArray(props.foregroundStyle) ? props.foregroundStyle[0] : props.foregroundStyle);
|
|
2166
|
+
function PathScreen({ value, destination }) {
|
|
2167
|
+
if (isPushedView(value)) return value.view;
|
|
2168
|
+
return destination.current ? destination.current(value) : null;
|
|
2169
|
+
}
|
|
2170
|
+
function NavigationLink(props) {
|
|
2171
|
+
const { own, modifiers } = splitProps(props);
|
|
2172
|
+
const navigation = useNavigation();
|
|
2173
|
+
const environment = useViewEnvironment();
|
|
2174
|
+
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.children;
|
|
2175
|
+
const listSelection = useContext(ListSelectionContext);
|
|
2176
|
+
const sidebar = useContext(SplitSelectionContext) !== null && listSelection !== null && own.destination === void 0 && own.value !== void 0;
|
|
2177
|
+
const tap = () => {
|
|
2178
|
+
if (sidebar) {
|
|
2179
|
+
listSelection.select(own.value);
|
|
2180
|
+
return;
|
|
2239
2181
|
}
|
|
2240
|
-
|
|
2241
|
-
if (
|
|
2242
|
-
|
|
2243
|
-
|
|
2182
|
+
if (!navigation) return;
|
|
2183
|
+
if (own.destination !== void 0) navigation.push({ view: own.destination });
|
|
2184
|
+
else navigation.push(own.value);
|
|
2185
|
+
};
|
|
2186
|
+
const style = takeModifier(modifiers, "buttonStyle") ?? environment.buttonStyle;
|
|
2187
|
+
const linkProps = style === "plain" ? { style: "plain" } : {};
|
|
2188
|
+
if (sidebar) linkProps["selects"] = true;
|
|
2189
|
+
return applyModifiers(sb("navlink", linkProps, { tap }, label), modifiers);
|
|
2244
2190
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2191
|
+
const SplitSelectionContext = createContext(null);
|
|
2192
|
+
function splitColumnWidthHint(width) {
|
|
2193
|
+
if (typeof width === "number") return { min: width, ideal: width, max: width };
|
|
2194
|
+
return { ...width.min !== void 0 ? { min: width.min } : {}, ideal: width.ideal, ...width.max !== void 0 ? { max: width.max } : {} };
|
|
2195
|
+
}
|
|
2196
|
+
function NavigationSplitView(props) {
|
|
2197
|
+
const { own, modifiers } = splitProps(props);
|
|
2198
|
+
const sizeClass = useHorizontalSizeClass();
|
|
2199
|
+
const [selected, setSelected] = useState(false);
|
|
2200
|
+
const reporters = useRef(/* @__PURE__ */ new Map());
|
|
2201
|
+
const settle = () => setSelected([...reporters.current.values()].some((entry) => entry.selected));
|
|
2202
|
+
const [report] = useState(() => {
|
|
2203
|
+
return {
|
|
2204
|
+
report: (key, nowSelected, clear2) => {
|
|
2205
|
+
reporters.current.set(key, { selected: nowSelected, clear: clear2 });
|
|
2206
|
+
settle();
|
|
2207
|
+
},
|
|
2208
|
+
retract: (key) => {
|
|
2209
|
+
if (reporters.current.delete(key)) settle();
|
|
2210
|
+
}
|
|
2211
|
+
};
|
|
2212
|
+
});
|
|
2213
|
+
const clear = () => {
|
|
2214
|
+
for (const entry of reporters.current.values()) {
|
|
2215
|
+
if (!entry.selected) continue;
|
|
2216
|
+
entry.clear();
|
|
2217
|
+
entry.selected = false;
|
|
2218
|
+
}
|
|
2219
|
+
settle();
|
|
2220
|
+
};
|
|
2221
|
+
const [internal, setInternal] = useState("automatic");
|
|
2222
|
+
const [visibility, setVisibility] = own.columnVisibility !== void 0 ? readBinding(own.columnVisibility, own.onColumnVisibilityChange) : [internal, setInternal];
|
|
2223
|
+
if (sizeClass === "compact") {
|
|
2224
|
+
return applyModifiers(/* @__PURE__ */ jsx(CompactSplit, { sidebar: own.sidebar, detail: own.detail, report, selected, clear }), modifiers);
|
|
2249
2225
|
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2226
|
+
const sidebarVisible = visibility !== "detailOnly";
|
|
2227
|
+
const toggle = () => withAnimation(() => setVisibility(sidebarVisible ? "detailOnly" : "all"));
|
|
2228
|
+
const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
|
|
2229
|
+
const hinted = (content) => own.sidebarWidth !== void 0 ? sb("styled", { style: { splitColumnWidth: splitColumnWidthHint(own.sidebarWidth) } }, void 0, content) : content;
|
|
2230
|
+
const sidebar = isValidElement(own.sidebar) && own.sidebar.type === NavigationStack ? hinted(own.sidebar) : /* @__PURE__ */ jsx(NavigationStack, { children: hinted(own.sidebar) });
|
|
2231
|
+
return applyModifiers(
|
|
2232
|
+
sb("navsplit", { sidebarVisible }, { tap: toggle, columnwidth: (event) => own.onSidebarWidthChange?.(event.width) }, [
|
|
2233
|
+
/* @__PURE__ */ jsx(SplitColumn, { report, children: sidebar }, "sidebar"),
|
|
2234
|
+
/* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
|
|
2235
|
+
]),
|
|
2236
|
+
modifiers
|
|
2237
|
+
);
|
|
2252
2238
|
}
|
|
2253
|
-
function
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
if (element.type === Text) {
|
|
2273
|
-
const props = element.props;
|
|
2274
|
-
segmentsOf(props.children, runStyleOf(props, style, true), into);
|
|
2275
|
-
return;
|
|
2276
|
-
}
|
|
2277
|
-
if (element.type === Image$1) {
|
|
2278
|
-
const props = element.props;
|
|
2279
|
-
into.push({ image: imageProps$1(props), style });
|
|
2239
|
+
function SplitColumn({ report, children }) {
|
|
2240
|
+
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children }) });
|
|
2241
|
+
}
|
|
2242
|
+
function CompactSplit({
|
|
2243
|
+
sidebar,
|
|
2244
|
+
detail,
|
|
2245
|
+
report,
|
|
2246
|
+
selected,
|
|
2247
|
+
clear
|
|
2248
|
+
}) {
|
|
2249
|
+
const [internal, setInternal] = useState([]);
|
|
2250
|
+
const detailStack = isValidElement(detail) && detail.type === NavigationStack ? detail.props : null;
|
|
2251
|
+
const [extra, setExtra] = detailStack?.path !== void 0 ? readBinding(detailStack.path, detailStack.onPathChange) : [internal, setInternal];
|
|
2252
|
+
const base = selected ? [{ view: detail }] : [];
|
|
2253
|
+
const path = [...base, ...extra];
|
|
2254
|
+
const setPath = (next) => {
|
|
2255
|
+
if (selected && next.length === 0) {
|
|
2256
|
+
setExtra([]);
|
|
2257
|
+
clear();
|
|
2280
2258
|
return;
|
|
2281
2259
|
}
|
|
2260
|
+
setExtra(next.slice(base.length));
|
|
2282
2261
|
};
|
|
2283
|
-
|
|
2284
|
-
}
|
|
2285
|
-
function isPlainStyle(style) {
|
|
2286
|
-
return Object.keys(style).length === 0;
|
|
2262
|
+
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children: /* @__PURE__ */ jsx(NavigationStack, { path: [path, setPath], children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children: sidebar }) }) }) });
|
|
2287
2263
|
}
|
|
2288
|
-
function
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
segmentsOf(own.children, style, segments);
|
|
2294
|
-
const textCase = takeModifier(modifiers, "textCase") ?? environment.textCase;
|
|
2295
|
-
if (textCase) {
|
|
2296
|
-
for (const segment of segments) {
|
|
2297
|
-
if ("text" in segment) segment.text = textCase === "uppercase" ? segment.text.toUpperCase() : segment.text.toLowerCase();
|
|
2298
|
-
}
|
|
2299
|
-
}
|
|
2300
|
-
const redacted = takeModifier(modifiers, "redacted") ?? environment.redacted;
|
|
2301
|
-
const content = segments.map((segment) => "text" in segment ? segment.text : "").join("");
|
|
2302
|
-
const plain2 = segments.length <= 1 && (segments.length === 0 || "text" in segments[0] && isPlainStyle(segments[0].style));
|
|
2303
|
-
if (plain2) return applyModifiers(placeholder(sb("text", { text: content }), redacted), modifiers);
|
|
2304
|
-
const runs = segments.map((segment) => {
|
|
2305
|
-
const run = { ...segment.style };
|
|
2306
|
-
if ("text" in segment) run["text"] = segment.text;
|
|
2307
|
-
else run["image"] = segment.image;
|
|
2308
|
-
return run;
|
|
2264
|
+
function useReportSplitSelection(split, selected, clear, active2 = true) {
|
|
2265
|
+
const key = useRef({}).current;
|
|
2266
|
+
useLayoutEffect(() => {
|
|
2267
|
+
if (active2) split?.report(key, selected, clear);
|
|
2268
|
+
else split?.retract(key);
|
|
2309
2269
|
});
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2270
|
+
useLayoutEffect(() => () => split?.retract(key), [split, key]);
|
|
2271
|
+
return (nowSelected, nowClear) => {
|
|
2272
|
+
if (active2) split?.report(key, nowSelected, nowClear);
|
|
2273
|
+
};
|
|
2313
2274
|
}
|
|
2314
|
-
function
|
|
2315
|
-
|
|
2316
|
-
return styled({ background: { hierarchical: 3 }, backgroundCornerRadius: 4 }, styled({ foreground: { name: "clear" } }, node));
|
|
2275
|
+
function OutsideSplit({ children }) {
|
|
2276
|
+
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
2317
2277
|
}
|
|
2318
|
-
function
|
|
2319
|
-
const
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2278
|
+
function SheetPresenter({ isPresented, onDismiss, content, fullScreen, inherited }) {
|
|
2279
|
+
const around = useInheritedStyles();
|
|
2280
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
2281
|
+
if (!presented) return null;
|
|
2282
|
+
const dismiss = () => {
|
|
2283
|
+
setPresented(false);
|
|
2284
|
+
onDismiss?.();
|
|
2285
|
+
};
|
|
2286
|
+
const detents = fullScreen ? ["full"] : ["large"];
|
|
2287
|
+
return sb(
|
|
2288
|
+
HOIST_KIND,
|
|
2289
|
+
void 0,
|
|
2290
|
+
void 0,
|
|
2291
|
+
sb(
|
|
2292
|
+
"sheet",
|
|
2293
|
+
{ detents },
|
|
2294
|
+
{ tap: dismiss },
|
|
2295
|
+
replayStyles(
|
|
2296
|
+
inherited && inherited.length > 0 ? [...around, ...inherited] : around,
|
|
2297
|
+
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(OutsideSplit, { children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) }) })
|
|
2298
|
+
)
|
|
2299
|
+
),
|
|
2300
|
+
"root"
|
|
2301
|
+
);
|
|
2325
2302
|
}
|
|
2326
|
-
function
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
const finite = Number.isFinite(extent.width) && Number.isFinite(extent.height);
|
|
2332
|
-
const width = finite ? Math.max(0, Math.round(extent.width)) : 0;
|
|
2333
|
-
const height = finite ? Math.max(0, Math.round(extent.height)) : 0;
|
|
2334
|
-
const scale = props.scale !== void 0 && props.scale > 0 ? props.scale : 1;
|
|
2335
|
-
return {
|
|
2336
|
-
bitmap: { source: source?.key ?? null, steps, width, height, ...version !== void 0 ? { version } : {} },
|
|
2337
|
-
resizable: props.resizable ?? false,
|
|
2338
|
-
width: width / scale,
|
|
2339
|
-
height: height / scale,
|
|
2340
|
-
...props.interpolation === "none" ? { interpolation: "none" } : {}
|
|
2341
|
-
};
|
|
2342
|
-
}
|
|
2343
|
-
if (props.url !== void 0) return { url: props.url, resizable: props.resizable ?? false, width: props.width ?? 0, height: props.height ?? 0 };
|
|
2344
|
-
return { name: props.name ?? "", resizable: props.resizable ?? false };
|
|
2303
|
+
function presentationDetents(detents) {
|
|
2304
|
+
const encoded = detents.map(
|
|
2305
|
+
(detent) => typeof detent === "string" ? detent : "height" in detent ? `height:${detent.height}` : `fraction:${detent.fraction}`
|
|
2306
|
+
);
|
|
2307
|
+
return sb(PREF_KIND, { detents: encoded }, void 0, void 0, "sheet");
|
|
2345
2308
|
}
|
|
2346
|
-
function
|
|
2347
|
-
const
|
|
2348
|
-
|
|
2349
|
-
const
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2309
|
+
function AlertPresenter({ title, isPresented, message, actions, style }) {
|
|
2310
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
2311
|
+
if (!presented) return null;
|
|
2312
|
+
const dismiss = () => setPresented(false);
|
|
2313
|
+
return sb(
|
|
2314
|
+
HOIST_KIND,
|
|
2315
|
+
void 0,
|
|
2316
|
+
void 0,
|
|
2317
|
+
sb(
|
|
2318
|
+
"alert",
|
|
2319
|
+
{ title, message: message ?? null, style: style ?? "alert" },
|
|
2320
|
+
{ tap: dismiss },
|
|
2321
|
+
withEnvironment({ dismissAlert: dismiss }, actions)
|
|
2322
|
+
),
|
|
2323
|
+
"root"
|
|
2324
|
+
);
|
|
2355
2325
|
}
|
|
2356
|
-
function
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2326
|
+
function Lifecycle({ onAppear, onDisappear }) {
|
|
2327
|
+
useEffect(() => {
|
|
2328
|
+
onAppear?.();
|
|
2329
|
+
return () => onDisappear?.();
|
|
2330
|
+
}, []);
|
|
2331
|
+
return null;
|
|
2332
|
+
}
|
|
2333
|
+
function Inspector({ isPresented, content, columnWidth, children }) {
|
|
2334
|
+
const sizeClass = useHorizontalSizeClass();
|
|
2335
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
2336
|
+
if (sizeClass === "compact") {
|
|
2337
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2338
|
+
children,
|
|
2339
|
+
/* @__PURE__ */ jsx(SheetPresenter, { isPresented: [presented, setPresented], content })
|
|
2340
|
+
] });
|
|
2366
2341
|
}
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2342
|
+
const outside = /* @__PURE__ */ jsx(OutsideSplit, { children: content });
|
|
2343
|
+
const panelContent = columnWidth !== void 0 ? sb("styled", { style: { inspectorColumnWidth: columnWidth } }, void 0, outside) : outside;
|
|
2344
|
+
return sb("inspector", { presented }, void 0, [
|
|
2345
|
+
/* @__PURE__ */ jsx(InspectorPart, { children }, "content"),
|
|
2346
|
+
/* @__PURE__ */ jsx(InspectorPart, { children: sb("inspectorpanel", {}, void 0, panelContent) }, "panel")
|
|
2347
|
+
]);
|
|
2348
|
+
}
|
|
2349
|
+
function InspectorPart({ children }) {
|
|
2350
|
+
return children;
|
|
2351
|
+
}
|
|
2352
|
+
function Task({ id, action }) {
|
|
2353
|
+
const latest = useRef(action);
|
|
2354
|
+
latest.current = action;
|
|
2355
|
+
useEffect(() => {
|
|
2356
|
+
const controller = new AbortController();
|
|
2357
|
+
Promise.resolve().then(() => latest.current(controller.signal)).catch((error) => {
|
|
2358
|
+
if (!controller.signal.aborted) console.error(error);
|
|
2359
|
+
});
|
|
2360
|
+
return () => controller.abort();
|
|
2361
|
+
}, [id]);
|
|
2362
|
+
return null;
|
|
2363
|
+
}
|
|
2364
|
+
function OnChange({
|
|
2365
|
+
value,
|
|
2366
|
+
action,
|
|
2367
|
+
initial
|
|
2368
|
+
}) {
|
|
2369
|
+
const previous = useRef(null);
|
|
2370
|
+
const latest = useRef(action);
|
|
2371
|
+
latest.current = action;
|
|
2372
|
+
useEffect(() => {
|
|
2373
|
+
const last = previous.current;
|
|
2374
|
+
previous.current = { value };
|
|
2375
|
+
if (last === null) {
|
|
2376
|
+
if (initial) latest.current(value, value);
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
if (!Object.is(last.value, value)) latest.current(last.value, value);
|
|
2380
|
+
}, [value, initial]);
|
|
2381
|
+
return null;
|
|
2382
|
+
}
|
|
2383
|
+
const CoordinateSpacesContext = createContext({});
|
|
2384
|
+
function useCoordinateSpaces() {
|
|
2385
|
+
return useContext(CoordinateSpacesContext);
|
|
2375
2386
|
}
|
|
2376
|
-
function
|
|
2377
|
-
const
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2387
|
+
function CoordinateSpace({ name, children }) {
|
|
2388
|
+
const spaces = useContext(CoordinateSpacesContext);
|
|
2389
|
+
const [frame2, setFrame] = useState(null);
|
|
2390
|
+
return /* @__PURE__ */ jsx(CoordinateSpacesContext.Provider, { value: { ...spaces, [name]: frame2 }, children: sb(
|
|
2391
|
+
"zstack",
|
|
2392
|
+
{ alignment: "center", reportsSize: true, reportsFrame: true },
|
|
2393
|
+
{
|
|
2394
|
+
geometry: (event) => {
|
|
2395
|
+
const next = { x: event.x ?? 0, y: event.y ?? 0, width: event.width, height: event.height };
|
|
2396
|
+
if (!frame2 || frame2.x !== next.x || frame2.y !== next.y || frame2.width !== next.width || frame2.height !== next.height) setFrame(next);
|
|
2397
|
+
}
|
|
2398
|
+
},
|
|
2399
|
+
children
|
|
2400
|
+
) });
|
|
2389
2401
|
}
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2402
|
+
const NO_INSETS = { top: 0, leading: 0, bottom: 0, trailing: 0 };
|
|
2403
|
+
const NO_GEOMETRY = { size: { width: 0, height: 0 }, origin: null, safeArea: NO_INSETS, scrollView: null };
|
|
2404
|
+
function nextGeometry(event, reported) {
|
|
2405
|
+
const hasOrigin = event.x !== void 0 && event.y !== void 0;
|
|
2406
|
+
return {
|
|
2407
|
+
size: { width: event.width, height: event.height },
|
|
2408
|
+
origin: hasOrigin ? { x: event.x, y: event.y } : reported.origin,
|
|
2409
|
+
safeArea: event.safeArea ?? reported.safeArea,
|
|
2410
|
+
// A frame report without a scroll view means the reader is in none.
|
|
2411
|
+
scrollView: hasOrigin ? event.scrollView ?? null : reported.scrollView
|
|
2412
|
+
};
|
|
2394
2413
|
}
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
if (
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2414
|
+
function geometryProxy(reported, spaces, onReadFrame) {
|
|
2415
|
+
return {
|
|
2416
|
+
size: reported.size,
|
|
2417
|
+
frame: (space = "local") => {
|
|
2418
|
+
if (space === "local") return { x: 0, y: 0, ...reported.size };
|
|
2419
|
+
onReadFrame();
|
|
2420
|
+
const origin = reported.origin ?? { x: 0, y: 0 };
|
|
2421
|
+
if (space === "global") return { ...origin, ...reported.size };
|
|
2422
|
+
const named = spaces[space.named];
|
|
2423
|
+
return { x: origin.x - (named?.x ?? 0), y: origin.y - (named?.y ?? 0), ...reported.size };
|
|
2424
|
+
},
|
|
2425
|
+
bounds: () => {
|
|
2426
|
+
onReadFrame();
|
|
2427
|
+
const view = reported.scrollView;
|
|
2428
|
+
if (!view || !reported.origin) return null;
|
|
2429
|
+
return { x: view.x - reported.origin.x, y: view.y - reported.origin.y, width: view.width, height: view.height };
|
|
2430
|
+
},
|
|
2431
|
+
get safeAreaInsets() {
|
|
2432
|
+
onReadFrame();
|
|
2433
|
+
return reported.safeArea;
|
|
2413
2434
|
}
|
|
2414
|
-
|
|
2415
|
-
}
|
|
2416
|
-
return void 0;
|
|
2417
|
-
}
|
|
2418
|
-
function NavigationStack(props) {
|
|
2419
|
-
const enclosing = useNavigation();
|
|
2420
|
-
if (enclosing) return /* @__PURE__ */ jsx(FlattenedStack, { ...props });
|
|
2421
|
-
return /* @__PURE__ */ jsx(OwnStack, { ...props });
|
|
2435
|
+
};
|
|
2422
2436
|
}
|
|
2423
|
-
function
|
|
2437
|
+
function GeometryReader(props) {
|
|
2424
2438
|
const { own, modifiers } = splitProps(props);
|
|
2439
|
+
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
2440
|
+
const [needsFrame, setNeedsFrame] = useState(false);
|
|
2441
|
+
let readFrame = false;
|
|
2442
|
+
const proxy = geometryProxy(reported, useCoordinateSpaces(), () => {
|
|
2443
|
+
readFrame = true;
|
|
2444
|
+
});
|
|
2445
|
+
const content = own.children(proxy);
|
|
2446
|
+
useEffect(() => {
|
|
2447
|
+
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2448
|
+
});
|
|
2425
2449
|
return applyModifiers(
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2450
|
+
sb(
|
|
2451
|
+
"geometry",
|
|
2452
|
+
needsFrame ? { reportsFrame: true } : {},
|
|
2453
|
+
{
|
|
2454
|
+
geometry: (event) => {
|
|
2455
|
+
const next = nextGeometry(event, reported);
|
|
2456
|
+
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2457
|
+
}
|
|
2458
|
+
},
|
|
2459
|
+
content
|
|
2460
|
+
),
|
|
2430
2461
|
modifiers
|
|
2431
2462
|
);
|
|
2432
2463
|
}
|
|
2433
|
-
function
|
|
2434
|
-
const
|
|
2435
|
-
const
|
|
2436
|
-
const
|
|
2437
|
-
const
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2464
|
+
function GeometryChangeView({ handler, children }) {
|
|
2465
|
+
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
2466
|
+
const [needsFrame, setNeedsFrame] = useState(false);
|
|
2467
|
+
const last = useRef(null);
|
|
2468
|
+
const spaces = useCoordinateSpaces();
|
|
2469
|
+
let readFrame = false;
|
|
2470
|
+
const proxy = geometryProxy(reported, spaces, () => {
|
|
2471
|
+
readFrame = true;
|
|
2472
|
+
});
|
|
2473
|
+
const heard = reported !== NO_GEOMETRY;
|
|
2474
|
+
const value = heard && typeof handler !== "function" ? handler.of(proxy) : void 0;
|
|
2475
|
+
useLayoutEffect(() => {
|
|
2476
|
+
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2477
|
+
});
|
|
2478
|
+
useLayoutEffect(() => {
|
|
2479
|
+
if (!heard) return;
|
|
2480
|
+
if (typeof handler === "function") {
|
|
2481
|
+
handler(proxy);
|
|
2482
|
+
return;
|
|
2447
2483
|
}
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
path.forEach((value, index) => {
|
|
2453
|
-
const pop = () => setPath(path.slice(0, index));
|
|
2454
|
-
const route = remote ? routeOf(value) : void 0;
|
|
2455
|
-
screens.push(
|
|
2456
|
-
/* @__PURE__ */ jsx(Fragment, { children: sb(
|
|
2457
|
-
"navscreen",
|
|
2458
|
-
{ title: "", displayMode: "automatic", depth: index + 1, ...route === void 0 ? {} : { route } },
|
|
2459
|
-
{ tap: pop },
|
|
2460
|
-
/* @__PURE__ */ jsx(DismissContext.Provider, { value: pop, children: /* @__PURE__ */ jsx(ScreenDepthContext.Provider, { value: index + 1, children: /* @__PURE__ */ jsx(PathScreen, { value, destination }) }) })
|
|
2461
|
-
) }, index + 1)
|
|
2462
|
-
);
|
|
2484
|
+
const previous = last.current;
|
|
2485
|
+
if (previous && JSON.stringify(previous.value) === JSON.stringify(value)) return;
|
|
2486
|
+
last.current = { value };
|
|
2487
|
+
handler.action(value, previous ? previous.value : value);
|
|
2463
2488
|
});
|
|
2464
|
-
return
|
|
2465
|
-
|
|
2466
|
-
|
|
2489
|
+
return sb(
|
|
2490
|
+
"zstack",
|
|
2491
|
+
{ alignment: "center", reportsSize: true, ...needsFrame ? { reportsFrame: true } : {} },
|
|
2492
|
+
{
|
|
2493
|
+
geometry: (event) => {
|
|
2494
|
+
const next = nextGeometry(event, reported);
|
|
2495
|
+
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2496
|
+
}
|
|
2497
|
+
},
|
|
2498
|
+
children
|
|
2467
2499
|
);
|
|
2468
2500
|
}
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
return
|
|
2501
|
+
const DEFAULT_VIEW_SPACING = { distance: () => 8 };
|
|
2502
|
+
function subviewTraits(children) {
|
|
2503
|
+
return flattenChildren(children).map((element) => {
|
|
2504
|
+
const props = element.props;
|
|
2505
|
+
return { priority: props.layoutPriority ?? 0, values: props.layoutValue ?? {} };
|
|
2506
|
+
});
|
|
2472
2507
|
}
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2508
|
+
const fromDimension = (value) => value === "infinity" ? Infinity : value;
|
|
2509
|
+
const toDimension = (value) => Number.isFinite(value) ? Math.round(value * 100) / 100 : "infinity";
|
|
2510
|
+
const toSize = (size) => ({
|
|
2511
|
+
width: fromDimension(size.width) ?? 0,
|
|
2512
|
+
height: fromDimension(size.height) ?? 0
|
|
2513
|
+
});
|
|
2514
|
+
const GUIDES = ["leading", "horizontalCenter", "trailing", "top", "verticalCenter", "bottom", "firstTextBaseline", "lastTextBaseline"];
|
|
2515
|
+
function clamp(value, min, max) {
|
|
2516
|
+
return Math.min(Math.max(value, min), max);
|
|
2517
|
+
}
|
|
2518
|
+
function answerLayout(layout, record, traits = []) {
|
|
2519
|
+
const frames = record.children.map(() => null);
|
|
2520
|
+
const subviews = record.children.map((measurement, index) => {
|
|
2521
|
+
const min = toSize(measurement.min);
|
|
2522
|
+
const ideal = toSize(measurement.ideal);
|
|
2523
|
+
const max = toSize(measurement.max);
|
|
2524
|
+
const sizeThatFits = (proposal) => ({
|
|
2525
|
+
width: proposal.width === null ? ideal.width : clamp(proposal.width, min.width, max.width),
|
|
2526
|
+
height: proposal.height === null ? ideal.height : clamp(proposal.height, min.height, max.height)
|
|
2527
|
+
});
|
|
2528
|
+
return {
|
|
2529
|
+
min,
|
|
2530
|
+
ideal,
|
|
2531
|
+
max,
|
|
2532
|
+
priority: traits[index]?.priority ?? 0,
|
|
2533
|
+
values: traits[index]?.values ?? {},
|
|
2534
|
+
spacing: DEFAULT_VIEW_SPACING,
|
|
2535
|
+
sizeThatFits,
|
|
2536
|
+
place: ({ x, y, anchor, proposal }) => {
|
|
2537
|
+
const size2 = sizeThatFits(proposal ?? { width: null, height: null });
|
|
2538
|
+
const point = unitPoint(anchor ?? "topLeading");
|
|
2539
|
+
frames[index] = { x: x - point.x * size2.width, y: y - point.y * size2.height, ...size2 };
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
});
|
|
2543
|
+
const cache = layout.makeCache ? layout.makeCache(subviews) : void 0;
|
|
2544
|
+
const measure = (proposal) => layout.sizeThatFits(proposal, subviews, cache);
|
|
2545
|
+
const size = measure(record.proposal);
|
|
2546
|
+
layout.placeSubviews({ x: 0, y: 0, ...size }, record.proposal, subviews, cache);
|
|
2547
|
+
const placed = frames.map((frame2, index) => {
|
|
2548
|
+
if (frame2) return frame2;
|
|
2549
|
+
const own = subviews[index].sizeThatFits({ width: size.width, height: size.height });
|
|
2550
|
+
return { x: (size.width - own.width) / 2, y: (size.height - own.height) / 2, ...own };
|
|
2551
|
+
});
|
|
2552
|
+
const guides = {};
|
|
2553
|
+
if (layout.explicitAlignment) {
|
|
2554
|
+
const bounds = { x: 0, y: 0, ...size };
|
|
2555
|
+
for (const guide of GUIDES) {
|
|
2556
|
+
const value = layout.explicitAlignment(guide, bounds, record.proposal, subviews, cache);
|
|
2557
|
+
if (value !== null && value !== void 0 && Number.isFinite(value)) guides[guide] = value;
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
const sizes = {
|
|
2561
|
+
min: measure({ width: 0, height: 0 }),
|
|
2562
|
+
ideal: measure({ width: null, height: null }),
|
|
2563
|
+
max: measure({ width: Infinity, height: Infinity })
|
|
2488
2564
|
};
|
|
2489
|
-
const
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
return applyModifiers(sb("navlink", linkProps, { tap }, label), modifiers);
|
|
2493
|
-
}
|
|
2494
|
-
const SplitSelectionContext = createContext(null);
|
|
2495
|
-
function splitColumnWidthHint(width) {
|
|
2496
|
-
if (typeof width === "number") return { min: width, ideal: width, max: width };
|
|
2497
|
-
return { ...width.min !== void 0 ? { min: width.min } : {}, ideal: width.ideal, ...width.max !== void 0 ? { max: width.max } : {} };
|
|
2565
|
+
const { width, height } = record.proposal;
|
|
2566
|
+
if (width !== null && Number.isFinite(width) && height !== null) sizes.atWidth = measure({ width, height: null });
|
|
2567
|
+
return { size, frames: placed, guides, sizes };
|
|
2498
2568
|
}
|
|
2499
|
-
function
|
|
2569
|
+
function Layout(props) {
|
|
2500
2570
|
const { own, modifiers } = splitProps(props);
|
|
2501
|
-
const
|
|
2502
|
-
|
|
2503
|
-
const
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2571
|
+
const [record, setRecord] = useState(null);
|
|
2572
|
+
let layoutProps = { proposal: null, size: null, frames: null };
|
|
2573
|
+
const guideModifiers = [];
|
|
2574
|
+
if (record) {
|
|
2575
|
+
const answer = answerLayout(own.layout, record, subviewTraits(own.children));
|
|
2576
|
+
for (const [guide, value] of Object.entries(answer.guides)) guideModifiers.push(["alignmentGuide", { guide, value: () => value }]);
|
|
2577
|
+
const encode = (size) => ({ width: toDimension(size.width), height: toDimension(size.height) });
|
|
2578
|
+
const round2 = (value) => Math.round(value * 100) / 100;
|
|
2579
|
+
layoutProps = {
|
|
2580
|
+
proposal: {
|
|
2581
|
+
width: record.proposal.width === null ? null : toDimension(record.proposal.width),
|
|
2582
|
+
height: record.proposal.height === null ? null : toDimension(record.proposal.height)
|
|
2510
2583
|
},
|
|
2511
|
-
|
|
2512
|
-
|
|
2584
|
+
size: { width: round2(answer.size.width), height: round2(answer.size.height) },
|
|
2585
|
+
frames: answer.frames.map((frame2) => ({ x: round2(frame2.x), y: round2(frame2.y), width: round2(frame2.width), height: round2(frame2.height) })),
|
|
2586
|
+
sizes: {
|
|
2587
|
+
min: encode(answer.sizes.min),
|
|
2588
|
+
ideal: encode(answer.sizes.ideal),
|
|
2589
|
+
max: encode(answer.sizes.max),
|
|
2590
|
+
...answer.sizes.atWidth ? { atWidth: encode(answer.sizes.atWidth) } : {}
|
|
2513
2591
|
}
|
|
2514
2592
|
};
|
|
2515
|
-
});
|
|
2516
|
-
const clear = () => {
|
|
2517
|
-
for (const entry of reporters.current.values()) {
|
|
2518
|
-
if (!entry.selected) continue;
|
|
2519
|
-
entry.clear();
|
|
2520
|
-
entry.selected = false;
|
|
2521
|
-
}
|
|
2522
|
-
settle();
|
|
2523
|
-
};
|
|
2524
|
-
const [internal, setInternal] = useState("automatic");
|
|
2525
|
-
const [visibility, setVisibility] = own.columnVisibility !== void 0 ? readBinding(own.columnVisibility, own.onColumnVisibilityChange) : [internal, setInternal];
|
|
2526
|
-
if (sizeClass === "compact") {
|
|
2527
|
-
return applyModifiers(/* @__PURE__ */ jsx(CompactSplit, { sidebar: own.sidebar, detail: own.detail, report, selected, clear }), modifiers);
|
|
2528
2593
|
}
|
|
2529
|
-
const sidebarVisible = visibility !== "detailOnly";
|
|
2530
|
-
const toggle = () => withAnimation(() => setVisibility(sidebarVisible ? "detailOnly" : "all"));
|
|
2531
|
-
const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
|
|
2532
|
-
const sidebar = own.sidebarWidth !== void 0 ? sb("styled", { style: { splitColumnWidth: splitColumnWidthHint(own.sidebarWidth) } }, void 0, own.sidebar) : own.sidebar;
|
|
2533
2594
|
return applyModifiers(
|
|
2534
|
-
sb("navsplit", { sidebarVisible }, { tap: toggle, columnwidth: (event) => own.onSidebarWidthChange?.(event.width) }, [
|
|
2535
|
-
/* @__PURE__ */ jsx(SplitColumn, { report, children: /* @__PURE__ */ jsx(NavigationStack, { children: sidebar }) }, "sidebar"),
|
|
2536
|
-
/* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
|
|
2537
|
-
]),
|
|
2538
|
-
modifiers
|
|
2539
|
-
);
|
|
2540
|
-
}
|
|
2541
|
-
function SplitColumn({ report, children }) {
|
|
2542
|
-
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children }) });
|
|
2543
|
-
}
|
|
2544
|
-
function CompactSplit({
|
|
2545
|
-
sidebar,
|
|
2546
|
-
detail,
|
|
2547
|
-
report,
|
|
2548
|
-
selected,
|
|
2549
|
-
clear
|
|
2550
|
-
}) {
|
|
2551
|
-
const [internal, setInternal] = useState([]);
|
|
2552
|
-
const detailStack = isValidElement(detail) && detail.type === NavigationStack ? detail.props : null;
|
|
2553
|
-
const [extra, setExtra] = detailStack?.path !== void 0 ? readBinding(detailStack.path, detailStack.onPathChange) : [internal, setInternal];
|
|
2554
|
-
const base = selected ? [{ view: detail }] : [];
|
|
2555
|
-
const path = [...base, ...extra];
|
|
2556
|
-
const setPath = (next) => {
|
|
2557
|
-
if (selected && next.length === 0) {
|
|
2558
|
-
setExtra([]);
|
|
2559
|
-
clear();
|
|
2560
|
-
return;
|
|
2561
|
-
}
|
|
2562
|
-
setExtra(next.slice(base.length));
|
|
2563
|
-
};
|
|
2564
|
-
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children: /* @__PURE__ */ jsx(NavigationStack, { path: [path, setPath], children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children: sidebar }) }) }) });
|
|
2565
|
-
}
|
|
2566
|
-
function useReportSplitSelection(split, selected, clear, active2 = true) {
|
|
2567
|
-
const key = useRef({}).current;
|
|
2568
|
-
useLayoutEffect(() => {
|
|
2569
|
-
if (active2) split?.report(key, selected, clear);
|
|
2570
|
-
else split?.retract(key);
|
|
2571
|
-
});
|
|
2572
|
-
useLayoutEffect(() => () => split?.retract(key), [split, key]);
|
|
2573
|
-
return (nowSelected, nowClear) => {
|
|
2574
|
-
if (active2) split?.report(key, nowSelected, nowClear);
|
|
2575
|
-
};
|
|
2576
|
-
}
|
|
2577
|
-
function OutsideSplit({ children }) {
|
|
2578
|
-
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
2579
|
-
}
|
|
2580
|
-
function SheetPresenter({ isPresented, onDismiss, content, fullScreen, inherited }) {
|
|
2581
|
-
const around = useInheritedStyles();
|
|
2582
|
-
const [presented, setPresented] = readBinding(isPresented);
|
|
2583
|
-
if (!presented) return null;
|
|
2584
|
-
const dismiss = () => {
|
|
2585
|
-
setPresented(false);
|
|
2586
|
-
onDismiss?.();
|
|
2587
|
-
};
|
|
2588
|
-
const detents = fullScreen ? ["full"] : ["large"];
|
|
2589
|
-
return sb(
|
|
2590
|
-
HOIST_KIND,
|
|
2591
|
-
void 0,
|
|
2592
|
-
void 0,
|
|
2593
|
-
sb(
|
|
2594
|
-
"sheet",
|
|
2595
|
-
{ detents },
|
|
2596
|
-
{ tap: dismiss },
|
|
2597
|
-
replayStyles(
|
|
2598
|
-
inherited && inherited.length > 0 ? [...around, ...inherited] : around,
|
|
2599
|
-
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(OutsideSplit, { children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) }) })
|
|
2600
|
-
)
|
|
2601
|
-
),
|
|
2602
|
-
"root"
|
|
2603
|
-
);
|
|
2604
|
-
}
|
|
2605
|
-
function presentationDetents(detents) {
|
|
2606
|
-
const encoded = detents.map(
|
|
2607
|
-
(detent) => typeof detent === "string" ? detent : "height" in detent ? `height:${detent.height}` : `fraction:${detent.fraction}`
|
|
2608
|
-
);
|
|
2609
|
-
return sb(PREF_KIND, { detents: encoded }, void 0, void 0, "sheet");
|
|
2610
|
-
}
|
|
2611
|
-
function AlertPresenter({ title, isPresented, message, actions, style }) {
|
|
2612
|
-
const [presented, setPresented] = readBinding(isPresented);
|
|
2613
|
-
if (!presented) return null;
|
|
2614
|
-
const dismiss = () => setPresented(false);
|
|
2615
|
-
return sb(
|
|
2616
|
-
HOIST_KIND,
|
|
2617
|
-
void 0,
|
|
2618
|
-
void 0,
|
|
2619
2595
|
sb(
|
|
2620
|
-
"
|
|
2621
|
-
|
|
2622
|
-
{
|
|
2623
|
-
|
|
2596
|
+
"layout",
|
|
2597
|
+
layoutProps,
|
|
2598
|
+
{
|
|
2599
|
+
layout: (event) => {
|
|
2600
|
+
const proposal = event.proposal;
|
|
2601
|
+
setRecord({
|
|
2602
|
+
proposal: { width: fromDimension(proposal.width), height: fromDimension(proposal.height) },
|
|
2603
|
+
children: event.children
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
},
|
|
2607
|
+
own.children
|
|
2624
2608
|
),
|
|
2625
|
-
|
|
2609
|
+
[...guideModifiers, ...modifiers]
|
|
2626
2610
|
);
|
|
2627
2611
|
}
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2612
|
+
const IDENTITY$1 = {
|
|
2613
|
+
offsetX: 0,
|
|
2614
|
+
offsetY: 0,
|
|
2615
|
+
scaleX: 1,
|
|
2616
|
+
scaleY: 1,
|
|
2617
|
+
rotation: 0,
|
|
2618
|
+
opacity: 1,
|
|
2619
|
+
blur: 0,
|
|
2620
|
+
brightness: 0,
|
|
2621
|
+
contrast: 1,
|
|
2622
|
+
saturation: 1,
|
|
2623
|
+
grayscale: 0,
|
|
2624
|
+
hueRotation: 0
|
|
2625
|
+
};
|
|
2626
|
+
class VisualEffect {
|
|
2627
|
+
/** @internal */
|
|
2628
|
+
constructor(values = IDENTITY$1) {
|
|
2629
|
+
this.values = values;
|
|
2630
|
+
}
|
|
2631
|
+
values;
|
|
2632
|
+
with(patch) {
|
|
2633
|
+
return new VisualEffect({ ...this.values, ...patch });
|
|
2634
|
+
}
|
|
2635
|
+
offset(offset) {
|
|
2636
|
+
return this.with({ offsetX: this.values.offsetX + (offset.x ?? 0), offsetY: this.values.offsetY + (offset.y ?? 0) });
|
|
2637
|
+
}
|
|
2638
|
+
scaleEffect(scale, anchor) {
|
|
2639
|
+
const x = typeof scale === "number" ? scale : scale.x ?? 1;
|
|
2640
|
+
const y = typeof scale === "number" ? scale : scale.y ?? 1;
|
|
2641
|
+
return this.with({ scaleX: this.values.scaleX * x, scaleY: this.values.scaleY * y, ...anchor !== void 0 ? { scaleAnchor: unitPoint(anchor) } : {} });
|
|
2642
|
+
}
|
|
2643
|
+
/** Degrees. */
|
|
2644
|
+
rotationEffect(degrees, anchor) {
|
|
2645
|
+
return this.with({ rotation: this.values.rotation + degrees, ...anchor !== void 0 ? { rotationAnchor: unitPoint(anchor) } : {} });
|
|
2646
|
+
}
|
|
2647
|
+
rotation3DEffect(spec) {
|
|
2648
|
+
const rotation = { angle: spec.angle, axis: spec.axis };
|
|
2649
|
+
if (spec.anchor !== void 0) rotation.anchor = unitPoint(spec.anchor);
|
|
2650
|
+
if (spec.perspective !== void 0) rotation.perspective = spec.perspective;
|
|
2651
|
+
return this.with({ rotation3D: rotation });
|
|
2652
|
+
}
|
|
2653
|
+
opacity(opacity2) {
|
|
2654
|
+
return this.with({ opacity: this.values.opacity * opacity2 });
|
|
2655
|
+
}
|
|
2656
|
+
blur(radius) {
|
|
2657
|
+
return this.with({ blur: this.values.blur + radius });
|
|
2658
|
+
}
|
|
2659
|
+
brightness(amount) {
|
|
2660
|
+
return this.with({ brightness: this.values.brightness + amount });
|
|
2661
|
+
}
|
|
2662
|
+
contrast(amount) {
|
|
2663
|
+
return this.with({ contrast: this.values.contrast * amount });
|
|
2664
|
+
}
|
|
2665
|
+
saturation(amount) {
|
|
2666
|
+
return this.with({ saturation: this.values.saturation * amount });
|
|
2667
|
+
}
|
|
2668
|
+
grayscale(amount) {
|
|
2669
|
+
return this.with({ grayscale: Math.min(1, this.values.grayscale + amount) });
|
|
2670
|
+
}
|
|
2671
|
+
/** Degrees. */
|
|
2672
|
+
hueRotation(degrees) {
|
|
2673
|
+
return this.with({ hueRotation: this.values.hueRotation + degrees });
|
|
2674
|
+
}
|
|
2634
2675
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2676
|
+
const EMPTY_EFFECT = new VisualEffect();
|
|
2677
|
+
const round = (value) => Math.round(value * 1e3) / 1e3;
|
|
2678
|
+
function effectStyle(values) {
|
|
2679
|
+
const style = {};
|
|
2680
|
+
if (values.offsetX !== 0 || values.offsetY !== 0) style.offset = { x: round(values.offsetX), y: round(values.offsetY) };
|
|
2681
|
+
if (values.scaleX !== 1 || values.scaleY !== 1) {
|
|
2682
|
+
style.scale = { x: round(values.scaleX), y: round(values.scaleY) };
|
|
2683
|
+
if (values.scaleAnchor) style.scaleAnchor = values.scaleAnchor;
|
|
2684
|
+
}
|
|
2685
|
+
if (values.rotation !== 0) {
|
|
2686
|
+
style.rotation = round(values.rotation);
|
|
2687
|
+
if (values.rotationAnchor) style.rotationAnchor = values.rotationAnchor;
|
|
2643
2688
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
return
|
|
2689
|
+
if (values.rotation3D && values.rotation3D.angle !== 0) style.rotation3D = { ...values.rotation3D, angle: round(values.rotation3D.angle) };
|
|
2690
|
+
if (values.opacity !== 1) style.opacity = round(values.opacity);
|
|
2691
|
+
if (values.blur !== 0) style.blur = round(values.blur);
|
|
2692
|
+
if (values.brightness !== 0) style.brightness = round(values.brightness);
|
|
2693
|
+
if (values.contrast !== 1) style.contrast = round(values.contrast);
|
|
2694
|
+
if (values.saturation !== 1) style.saturation = round(values.saturation);
|
|
2695
|
+
if (values.grayscale !== 0) style.grayscale = round(values.grayscale);
|
|
2696
|
+
if (values.hueRotation !== 0) style.hueRotation = round(values.hueRotation);
|
|
2697
|
+
return style;
|
|
2653
2698
|
}
|
|
2654
|
-
function
|
|
2655
|
-
const
|
|
2656
|
-
|
|
2699
|
+
function EffectBox({ render, children }) {
|
|
2700
|
+
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
2701
|
+
const [needsFrame, setNeedsFrame] = useState(false);
|
|
2702
|
+
let readFrame = false;
|
|
2703
|
+
const style = render(reported, () => {
|
|
2704
|
+
readFrame = true;
|
|
2705
|
+
});
|
|
2657
2706
|
useEffect(() => {
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2707
|
+
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2708
|
+
});
|
|
2709
|
+
const content = Object.keys(style).length > 0 ? sb("styled", { style }, void 0, children) : children;
|
|
2710
|
+
return sb(
|
|
2711
|
+
"zstack",
|
|
2712
|
+
{ alignment: "center", reportsSize: true, ...needsFrame ? { reportsFrame: true } : {} },
|
|
2713
|
+
{
|
|
2714
|
+
geometry: (event) => {
|
|
2715
|
+
const next = nextGeometry(event, reported);
|
|
2716
|
+
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2717
|
+
}
|
|
2718
|
+
},
|
|
2719
|
+
content
|
|
2720
|
+
);
|
|
2665
2721
|
}
|
|
2666
|
-
function
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
}
|
|
2683
|
-
|
|
2722
|
+
function VisualEffectView({ effect, children }) {
|
|
2723
|
+
const spaces = useCoordinateSpaces();
|
|
2724
|
+
return /* @__PURE__ */ jsx(EffectBox, { render: (reported, markRead) => effectStyle(effect(EMPTY_EFFECT, geometryProxy(reported, spaces, markRead)).values), children });
|
|
2725
|
+
}
|
|
2726
|
+
const PHASES = {
|
|
2727
|
+
topLeading: { phase: "topLeading", value: -1, isIdentity: false },
|
|
2728
|
+
identity: { phase: "identity", value: 0, isIdentity: true },
|
|
2729
|
+
bottomTrailing: { phase: "bottomTrailing", value: 1, isIdentity: false }
|
|
2730
|
+
};
|
|
2731
|
+
function ScrollTransitionView({ spec, children }) {
|
|
2732
|
+
const phase = (which) => effectStyle(spec.transition(EMPTY_EFFECT, PHASES[which]).values);
|
|
2733
|
+
const transition = {
|
|
2734
|
+
configuration: spec.configuration ?? "interactive",
|
|
2735
|
+
identity: phase("identity"),
|
|
2736
|
+
topLeading: phase("topLeading"),
|
|
2737
|
+
bottomTrailing: phase("bottomTrailing")
|
|
2738
|
+
};
|
|
2739
|
+
if (spec.axis) transition.axis = spec.axis;
|
|
2740
|
+
return sb("styled", { style: { scrollTransition: transition } }, void 0, children);
|
|
2684
2741
|
}
|
|
2685
2742
|
function Hover({ action, children }) {
|
|
2686
2743
|
return sb("styled", { style: { hover: true } }, { hover: (event) => action(event.value) }, children);
|
|
@@ -3644,345 +3701,404 @@ function TextInputHint({ hint, children }) {
|
|
|
3644
3701
|
const outer = useViewEnvironment().textInputHints;
|
|
3645
3702
|
return withEnvironment({ textInputHints: { ...outer, ...hint } }, children);
|
|
3646
3703
|
}
|
|
3647
|
-
|
|
3648
|
-
const
|
|
3649
|
-
|
|
3650
|
-
const hasOrigin = event.x !== void 0 && event.y !== void 0;
|
|
3651
|
-
return {
|
|
3652
|
-
size: { width: event.width, height: event.height },
|
|
3653
|
-
origin: hasOrigin ? { x: event.x, y: event.y } : reported.origin,
|
|
3654
|
-
safeArea: event.safeArea ?? reported.safeArea,
|
|
3655
|
-
// A frame report without a scroll view means the reader is in none.
|
|
3656
|
-
scrollView: hasOrigin ? event.scrollView ?? null : reported.scrollView
|
|
3657
|
-
};
|
|
3704
|
+
function HostElement(props) {
|
|
3705
|
+
const { own, modifiers } = splitProps(props);
|
|
3706
|
+
return applyModifiers(sb(own.kind, own.props ? { ...own.props } : void 0, void 0, own.children), modifiers);
|
|
3658
3707
|
}
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
if (space === "global") return { ...origin, ...reported.size };
|
|
3667
|
-
const named = spaces[space.named];
|
|
3668
|
-
return { x: origin.x - (named?.x ?? 0), y: origin.y - (named?.y ?? 0), ...reported.size };
|
|
3669
|
-
},
|
|
3670
|
-
bounds: () => {
|
|
3671
|
-
onReadFrame();
|
|
3672
|
-
const view = reported.scrollView;
|
|
3673
|
-
if (!view || !reported.origin) return null;
|
|
3674
|
-
return { x: view.x - reported.origin.x, y: view.y - reported.origin.y, width: view.width, height: view.height };
|
|
3675
|
-
},
|
|
3676
|
-
get safeAreaInsets() {
|
|
3677
|
-
onReadFrame();
|
|
3678
|
-
return reported.safeArea;
|
|
3679
|
-
}
|
|
3680
|
-
};
|
|
3708
|
+
let installed = null;
|
|
3709
|
+
function installTextMeasurer(measurer, remove = false) {
|
|
3710
|
+
if (remove) {
|
|
3711
|
+
if (installed === measurer) installed = null;
|
|
3712
|
+
return;
|
|
3713
|
+
}
|
|
3714
|
+
installed = measurer;
|
|
3681
3715
|
}
|
|
3682
|
-
function
|
|
3683
|
-
|
|
3684
|
-
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
3685
|
-
const [needsFrame, setNeedsFrame] = useState(false);
|
|
3686
|
-
let readFrame = false;
|
|
3687
|
-
const proxy = geometryProxy(reported, useCoordinateSpaces(), () => {
|
|
3688
|
-
readFrame = true;
|
|
3689
|
-
});
|
|
3690
|
-
const content = own.children(proxy);
|
|
3691
|
-
useEffect(() => {
|
|
3692
|
-
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
3693
|
-
});
|
|
3694
|
-
return applyModifiers(
|
|
3695
|
-
sb(
|
|
3696
|
-
"geometry",
|
|
3697
|
-
needsFrame ? { reportsFrame: true } : {},
|
|
3698
|
-
{
|
|
3699
|
-
geometry: (event) => {
|
|
3700
|
-
const next = nextGeometry(event, reported);
|
|
3701
|
-
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
3702
|
-
}
|
|
3703
|
-
},
|
|
3704
|
-
content
|
|
3705
|
-
),
|
|
3706
|
-
modifiers
|
|
3707
|
-
);
|
|
3716
|
+
function canMeasureText() {
|
|
3717
|
+
return installed !== null;
|
|
3708
3718
|
}
|
|
3709
|
-
function
|
|
3710
|
-
|
|
3711
|
-
const
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
"
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3719
|
+
function measureText(text, font$1 = "body", width) {
|
|
3720
|
+
if (!installed) throw new Error("measureText: nothing measures text here yet (mount the app, or run it in a SwiftBrowser Native host)");
|
|
3721
|
+
const constrained = typeof width === "number" && Number.isFinite(width) && width > 0 ? width : null;
|
|
3722
|
+
return installed(text, font(font$1), constrained);
|
|
3723
|
+
}
|
|
3724
|
+
function decidePlatform(width, media = matchesMedia) {
|
|
3725
|
+
return horizontalSizeClassFor(width) === "regular" && media("(hover: hover) and (pointer: fine)") ? "macos" : "ios";
|
|
3726
|
+
}
|
|
3727
|
+
function matchesMedia(query) {
|
|
3728
|
+
return typeof matchMedia === "function" && matchMedia(query).matches;
|
|
3729
|
+
}
|
|
3730
|
+
function mount(screen, element, options = {}) {
|
|
3731
|
+
let renderer = null;
|
|
3732
|
+
const root = createSwiftUIRoot((ops) => renderer?.applyOps(ops));
|
|
3733
|
+
renderer = new Renderer(screen, (event) => root.dispatch(event));
|
|
3734
|
+
renderer.fileDrops = "reference";
|
|
3735
|
+
const measurer = (text, font2, width2) => renderer.measureText(text, font2, width2);
|
|
3736
|
+
installTextMeasurer(measurer);
|
|
3737
|
+
let pageScheme = options.colorScheme ?? "light";
|
|
3738
|
+
let preferred = null;
|
|
3739
|
+
const width = screen.clientWidth || 393;
|
|
3740
|
+
const environment = {
|
|
3741
|
+
colorScheme: pageScheme,
|
|
3742
|
+
dynamicTypeSize: options.dynamicTypeSize ?? "large",
|
|
3743
|
+
horizontalSizeClass: horizontalSizeClassFor(width),
|
|
3744
|
+
scenePhase: typeof document !== "undefined" ? currentScenePhase() : "active",
|
|
3745
|
+
platform: options.platform === void 0 || options.platform === "auto" ? decidePlatform(width) : options.platform
|
|
3746
|
+
};
|
|
3747
|
+
renderer.contentHeight = options.contentHeight ?? false;
|
|
3748
|
+
if (options.sidebarTitleBar === false) renderer.sidebarTitleBar = false;
|
|
3749
|
+
if (options.assets) renderer.setAssetCatalog(options.assets);
|
|
3750
|
+
if (options.app) browserEnvironment.files?.setApp?.(options.app);
|
|
3751
|
+
renderer.setEnvironment({ colorScheme: environment.colorScheme, dynamicTypeSize: environment.dynamicTypeSize, platform: environment.platform });
|
|
3752
|
+
if (options.safeArea !== void 0) renderer.setSafeArea(options.safeArea);
|
|
3753
|
+
root.setEnvironment(environment);
|
|
3754
|
+
const browserHistory = (options.history ?? true) && typeof window !== "undefined" ? new BrowserHistory(renderer, screen) : null;
|
|
3755
|
+
browserHistory?.enable();
|
|
3756
|
+
const stopKeyboard = options.keyboard && typeof window !== "undefined" ? watchKeyboard((height) => renderer?.setKeyboard(height), { root: screen }) : null;
|
|
3757
|
+
const applyScheme = () => {
|
|
3758
|
+
const scheme = preferred ?? pageScheme;
|
|
3759
|
+
const device = screen.closest(".device");
|
|
3760
|
+
if (device) device.dataset["theme"] = scheme;
|
|
3761
|
+
renderer?.setEnvironment({ colorScheme: scheme });
|
|
3762
|
+
root.setEnvironment({ colorScheme: scheme });
|
|
3763
|
+
};
|
|
3764
|
+
const onPreferredScheme = (event) => {
|
|
3765
|
+
const scheme = event.detail.colorScheme;
|
|
3766
|
+
preferred = scheme;
|
|
3767
|
+
queueMicrotask(applyScheme);
|
|
3768
|
+
};
|
|
3769
|
+
screen.addEventListener("sb:color-scheme", onPreferredScheme);
|
|
3770
|
+
let sizeClass = environment.horizontalSizeClass;
|
|
3771
|
+
const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
3772
|
+
const next = horizontalSizeClassFor(screen.clientWidth);
|
|
3773
|
+
if (next === sizeClass) return;
|
|
3774
|
+
sizeClass = next;
|
|
3775
|
+
root.setEnvironment({ horizontalSizeClass: next });
|
|
3776
|
+
}) : null;
|
|
3777
|
+
observer?.observe(screen);
|
|
3778
|
+
const stopScenePhase = typeof document !== "undefined" ? watchScenePhase((scenePhase) => root.setEnvironment({ scenePhase })) : null;
|
|
3779
|
+
root.render(createElement(LazyWindowContext.Provider, { value: true }, element));
|
|
3780
|
+
const mounted = {
|
|
3781
|
+
root,
|
|
3782
|
+
renderer,
|
|
3783
|
+
setEnvironment(next) {
|
|
3784
|
+
if (next.colorScheme !== void 0) pageScheme = next.colorScheme;
|
|
3785
|
+
const scheme = preferred ?? pageScheme;
|
|
3786
|
+
renderer?.setEnvironment({ ...next, colorScheme: scheme });
|
|
3787
|
+
root.setEnvironment({ ...next, colorScheme: scheme });
|
|
3742
3788
|
},
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
}
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
});
|
|
3759
|
-
const GUIDES = ["leading", "horizontalCenter", "trailing", "top", "verticalCenter", "bottom", "firstTextBaseline", "lastTextBaseline"];
|
|
3760
|
-
function clamp(value, min, max) {
|
|
3761
|
-
return Math.min(Math.max(value, min), max);
|
|
3762
|
-
}
|
|
3763
|
-
function answerLayout(layout, record, traits = []) {
|
|
3764
|
-
const frames = record.children.map(() => null);
|
|
3765
|
-
const subviews = record.children.map((measurement, index) => {
|
|
3766
|
-
const min = toSize(measurement.min);
|
|
3767
|
-
const ideal = toSize(measurement.ideal);
|
|
3768
|
-
const max = toSize(measurement.max);
|
|
3769
|
-
const sizeThatFits = (proposal) => ({
|
|
3770
|
-
width: proposal.width === null ? ideal.width : clamp(proposal.width, min.width, max.width),
|
|
3771
|
-
height: proposal.height === null ? ideal.height : clamp(proposal.height, min.height, max.height)
|
|
3772
|
-
});
|
|
3773
|
-
return {
|
|
3774
|
-
min,
|
|
3775
|
-
ideal,
|
|
3776
|
-
max,
|
|
3777
|
-
priority: traits[index]?.priority ?? 0,
|
|
3778
|
-
values: traits[index]?.values ?? {},
|
|
3779
|
-
spacing: DEFAULT_VIEW_SPACING,
|
|
3780
|
-
sizeThatFits,
|
|
3781
|
-
place: ({ x, y, anchor, proposal }) => {
|
|
3782
|
-
const size2 = sizeThatFits(proposal ?? { width: null, height: null });
|
|
3783
|
-
const point = unitPoint(anchor ?? "topLeading");
|
|
3784
|
-
frames[index] = { x: x - point.x * size2.width, y: y - point.y * size2.height, ...size2 };
|
|
3785
|
-
}
|
|
3786
|
-
};
|
|
3787
|
-
});
|
|
3788
|
-
const cache = layout.makeCache ? layout.makeCache(subviews) : void 0;
|
|
3789
|
-
const measure = (proposal) => layout.sizeThatFits(proposal, subviews, cache);
|
|
3790
|
-
const size = measure(record.proposal);
|
|
3791
|
-
layout.placeSubviews({ x: 0, y: 0, ...size }, record.proposal, subviews, cache);
|
|
3792
|
-
const placed = frames.map((frame2, index) => {
|
|
3793
|
-
if (frame2) return frame2;
|
|
3794
|
-
const own = subviews[index].sizeThatFits({ width: size.width, height: size.height });
|
|
3795
|
-
return { x: (size.width - own.width) / 2, y: (size.height - own.height) / 2, ...own };
|
|
3796
|
-
});
|
|
3797
|
-
const guides = {};
|
|
3798
|
-
if (layout.explicitAlignment) {
|
|
3799
|
-
const bounds = { x: 0, y: 0, ...size };
|
|
3800
|
-
for (const guide of GUIDES) {
|
|
3801
|
-
const value = layout.explicitAlignment(guide, bounds, record.proposal, subviews, cache);
|
|
3802
|
-
if (value !== null && value !== void 0 && Number.isFinite(value)) guides[guide] = value;
|
|
3789
|
+
setSafeArea(insets2) {
|
|
3790
|
+
renderer?.setSafeArea(insets2);
|
|
3791
|
+
},
|
|
3792
|
+
viewportChanged() {
|
|
3793
|
+
renderer?.viewportChanged();
|
|
3794
|
+
},
|
|
3795
|
+
unmount() {
|
|
3796
|
+
observer?.disconnect();
|
|
3797
|
+
stopScenePhase?.();
|
|
3798
|
+
stopKeyboard?.();
|
|
3799
|
+
browserHistory?.dispose();
|
|
3800
|
+
screen.removeEventListener("sb:color-scheme", onPreferredScheme);
|
|
3801
|
+
installTextMeasurer(measurer, true);
|
|
3802
|
+
root.unmount();
|
|
3803
|
+
renderer?.dispose();
|
|
3803
3804
|
}
|
|
3804
|
-
}
|
|
3805
|
-
const sizes = {
|
|
3806
|
-
min: measure({ width: 0, height: 0 }),
|
|
3807
|
-
ideal: measure({ width: null, height: null }),
|
|
3808
|
-
max: measure({ width: Infinity, height: Infinity })
|
|
3809
3805
|
};
|
|
3810
|
-
|
|
3811
|
-
if (width !== null && Number.isFinite(width) && height !== null) sizes.atWidth = measure({ width, height: null });
|
|
3812
|
-
return { size, frames: placed, guides, sizes };
|
|
3813
|
-
}
|
|
3814
|
-
function Layout(props) {
|
|
3815
|
-
const { own, modifiers } = splitProps(props);
|
|
3816
|
-
const [record, setRecord] = useState(null);
|
|
3817
|
-
let layoutProps = { proposal: null, size: null, frames: null };
|
|
3818
|
-
const guideModifiers = [];
|
|
3819
|
-
if (record) {
|
|
3820
|
-
const answer = answerLayout(own.layout, record, subviewTraits(own.children));
|
|
3821
|
-
for (const [guide, value] of Object.entries(answer.guides)) guideModifiers.push(["alignmentGuide", { guide, value: () => value }]);
|
|
3822
|
-
const encode = (size) => ({ width: toDimension(size.width), height: toDimension(size.height) });
|
|
3823
|
-
const round2 = (value) => Math.round(value * 100) / 100;
|
|
3824
|
-
layoutProps = {
|
|
3825
|
-
proposal: {
|
|
3826
|
-
width: record.proposal.width === null ? null : toDimension(record.proposal.width),
|
|
3827
|
-
height: record.proposal.height === null ? null : toDimension(record.proposal.height)
|
|
3828
|
-
},
|
|
3829
|
-
size: { width: round2(answer.size.width), height: round2(answer.size.height) },
|
|
3830
|
-
frames: answer.frames.map((frame2) => ({ x: round2(frame2.x), y: round2(frame2.y), width: round2(frame2.width), height: round2(frame2.height) })),
|
|
3831
|
-
sizes: {
|
|
3832
|
-
min: encode(answer.sizes.min),
|
|
3833
|
-
ideal: encode(answer.sizes.ideal),
|
|
3834
|
-
max: encode(answer.sizes.max),
|
|
3835
|
-
...answer.sizes.atWidth ? { atWidth: encode(answer.sizes.atWidth) } : {}
|
|
3836
|
-
}
|
|
3837
|
-
};
|
|
3838
|
-
}
|
|
3839
|
-
return applyModifiers(
|
|
3840
|
-
sb(
|
|
3841
|
-
"layout",
|
|
3842
|
-
layoutProps,
|
|
3843
|
-
{
|
|
3844
|
-
layout: (event) => {
|
|
3845
|
-
const proposal = event.proposal;
|
|
3846
|
-
setRecord({
|
|
3847
|
-
proposal: { width: fromDimension(proposal.width), height: fromDimension(proposal.height) },
|
|
3848
|
-
children: event.children
|
|
3849
|
-
});
|
|
3850
|
-
}
|
|
3851
|
-
},
|
|
3852
|
-
own.children
|
|
3853
|
-
),
|
|
3854
|
-
[...guideModifiers, ...modifiers]
|
|
3855
|
-
);
|
|
3806
|
+
return mounted;
|
|
3856
3807
|
}
|
|
3857
|
-
const
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
scaleY: 1,
|
|
3862
|
-
rotation: 0,
|
|
3863
|
-
opacity: 1,
|
|
3864
|
-
blur: 0,
|
|
3865
|
-
brightness: 0,
|
|
3866
|
-
contrast: 1,
|
|
3867
|
-
saturation: 1,
|
|
3868
|
-
grayscale: 0,
|
|
3869
|
-
hueRotation: 0
|
|
3808
|
+
const EMPTY = { canUndo: false, canRedo: false, undoActionName: "", redoActionName: "" };
|
|
3809
|
+
const defaultSchedule = (close) => {
|
|
3810
|
+
if (typeof queueMicrotask === "function") queueMicrotask(close);
|
|
3811
|
+
else void Promise.resolve().then(close);
|
|
3870
3812
|
};
|
|
3871
|
-
class
|
|
3872
|
-
/**
|
|
3873
|
-
|
|
3874
|
-
|
|
3813
|
+
class UndoManager {
|
|
3814
|
+
/** Whether registrations in one event (one task of the event loop) form one group; true, as `groupsByEvent`. */
|
|
3815
|
+
groupsByEvent = true;
|
|
3816
|
+
/** How many groups the undo stack keeps; 0 for no limit, as `levelsOfUndo`. */
|
|
3817
|
+
levelsOfUndo = 0;
|
|
3818
|
+
undoStack = [];
|
|
3819
|
+
redoStack = [];
|
|
3820
|
+
/** The group registrations go in: an explicit group, the event's group, or the inverse of what is being undone or redone. */
|
|
3821
|
+
open = null;
|
|
3822
|
+
/** How deep `beginGrouping` is; 0 when `open` is the event's group or an inverse. */
|
|
3823
|
+
depth = 0;
|
|
3824
|
+
/** Whether `open` is the event's group, which `schedule` closes. */
|
|
3825
|
+
byEvent = false;
|
|
3826
|
+
/** The last keyed group closed onto the undo stack, which a registration with its key joins. */
|
|
3827
|
+
coalescing = null;
|
|
3828
|
+
undoing = false;
|
|
3829
|
+
redoing = false;
|
|
3830
|
+
snapshot = EMPTY;
|
|
3831
|
+
listeners = /* @__PURE__ */ new Set();
|
|
3832
|
+
schedule;
|
|
3833
|
+
host;
|
|
3834
|
+
stopListening = null;
|
|
3835
|
+
constructor(options = {}) {
|
|
3836
|
+
this.schedule = options.schedule ?? defaultSchedule;
|
|
3837
|
+
this.host = options.host === void 0 ? browserEnvironment.undoManager ?? null : options.host;
|
|
3838
|
+
if (this.host) {
|
|
3839
|
+
this.stopListening = this.host.listen({ undo: () => this.undo(), redo: () => this.redo() });
|
|
3840
|
+
this.host.update(this.snapshot);
|
|
3841
|
+
}
|
|
3875
3842
|
}
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
return new VisualEffect({ ...this.values, ...patch });
|
|
3843
|
+
get canUndo() {
|
|
3844
|
+
return this.undoStack.length > 0;
|
|
3879
3845
|
}
|
|
3880
|
-
|
|
3881
|
-
return this.
|
|
3846
|
+
get canRedo() {
|
|
3847
|
+
return this.redoStack.length > 0;
|
|
3882
3848
|
}
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
return this.with({ scaleX: this.values.scaleX * x, scaleY: this.values.scaleY * y, ...anchor !== void 0 ? { scaleAnchor: unitPoint(anchor) } : {} });
|
|
3849
|
+
/** The name of what `undo` takes back ('' for none): "Move" for an Edit menu's "Undo Move". */
|
|
3850
|
+
get undoActionName() {
|
|
3851
|
+
return this.undoStack[this.undoStack.length - 1]?.name ?? "";
|
|
3887
3852
|
}
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3853
|
+
get redoActionName() {
|
|
3854
|
+
return this.redoStack[this.redoStack.length - 1]?.name ?? "";
|
|
3855
|
+
}
|
|
3856
|
+
get isUndoing() {
|
|
3857
|
+
return this.undoing;
|
|
3858
|
+
}
|
|
3859
|
+
get isRedoing() {
|
|
3860
|
+
return this.redoing;
|
|
3861
|
+
}
|
|
3862
|
+
/** What the stacks can do, one object per change (for `useSyncExternalStore`). */
|
|
3863
|
+
get state() {
|
|
3864
|
+
return this.snapshot;
|
|
3865
|
+
}
|
|
3866
|
+
/**
|
|
3867
|
+
* Registers what undoes the change just made, under `name`. Run by `undo`,
|
|
3868
|
+
* the closure registers its own inverse the same way, which lands on the
|
|
3869
|
+
* redo stack because the manager is undoing.
|
|
3870
|
+
*/
|
|
3871
|
+
registerUndo(name, undo, options = {}) {
|
|
3872
|
+
const action = { name, undo, target: options.target };
|
|
3873
|
+
if (this.undoing || this.redoing) {
|
|
3874
|
+
this.open.actions.push(action);
|
|
3875
|
+
this.changed();
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
this.redoStack = [];
|
|
3879
|
+
this.coalescing = this.coalescing && this.undoStack[this.undoStack.length - 1] === this.coalescing ? this.coalescing : null;
|
|
3880
|
+
if (this.open) {
|
|
3881
|
+
if (!this.undoStack.includes(this.open)) this.push(this.open);
|
|
3882
|
+
this.open.actions.push(action);
|
|
3883
|
+
if (!this.open.named) this.open.name = name;
|
|
3884
|
+
} else if (this.coalescing && options.key !== void 0 && this.coalescing.key === options.key) {
|
|
3885
|
+
this.coalescing.actions.push(action);
|
|
3886
|
+
this.coalescing.name = name;
|
|
3887
|
+
} else {
|
|
3888
|
+
const group = { name, named: false, actions: [action], key: options.key };
|
|
3889
|
+
this.push(group);
|
|
3890
|
+
this.coalescing = null;
|
|
3891
|
+
if (this.groupsByEvent) {
|
|
3892
|
+
this.open = group;
|
|
3893
|
+
this.byEvent = true;
|
|
3894
|
+
this.schedule(() => {
|
|
3895
|
+
if (this.open === group && this.byEvent) this.close();
|
|
3896
|
+
});
|
|
3897
|
+
} else {
|
|
3898
|
+
this.coalescing = group.key !== void 0 ? group : null;
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
this.changed();
|
|
3902
|
+
}
|
|
3903
|
+
/** Takes back the top group of changes; its inverses become the top of the redo stack. */
|
|
3904
|
+
undo() {
|
|
3905
|
+
this.endOpenGroups();
|
|
3906
|
+
const group = this.undoStack.pop();
|
|
3907
|
+
if (!group) return;
|
|
3908
|
+
this.coalescing = null;
|
|
3909
|
+
this.run(group, "undo");
|
|
3910
|
+
}
|
|
3911
|
+
redo() {
|
|
3912
|
+
this.endOpenGroups();
|
|
3913
|
+
const group = this.redoStack.pop();
|
|
3914
|
+
if (!group) return;
|
|
3915
|
+
this.run(group, "redo");
|
|
3891
3916
|
}
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3917
|
+
/**
|
|
3918
|
+
* Starts a group: every registration until `endGrouping` undoes as one
|
|
3919
|
+
* (`beginUndoGrouping`). Nested calls join the outer group. The group is
|
|
3920
|
+
* named `name`, else after its last registration.
|
|
3921
|
+
*/
|
|
3922
|
+
beginGrouping(name) {
|
|
3923
|
+
if (this.undoing || this.redoing) return;
|
|
3924
|
+
this.depth += 1;
|
|
3925
|
+
if (this.depth > 1) return;
|
|
3926
|
+
if (this.open) this.close();
|
|
3927
|
+
this.open = { name: name ?? "", named: name !== void 0, actions: [], key: void 0 };
|
|
3928
|
+
this.byEvent = false;
|
|
3929
|
+
this.coalescing = null;
|
|
3897
3930
|
}
|
|
3898
|
-
|
|
3899
|
-
|
|
3931
|
+
/** Ends the group `beginGrouping` started; one that registered nothing is dropped. */
|
|
3932
|
+
endGrouping() {
|
|
3933
|
+
if (this.depth === 0) return;
|
|
3934
|
+
this.depth -= 1;
|
|
3935
|
+
if (this.depth === 0) this.close();
|
|
3900
3936
|
}
|
|
3901
|
-
|
|
3902
|
-
|
|
3937
|
+
/** `body` as one group named `name`. */
|
|
3938
|
+
group(name, body) {
|
|
3939
|
+
this.beginGrouping(name);
|
|
3940
|
+
try {
|
|
3941
|
+
return body();
|
|
3942
|
+
} finally {
|
|
3943
|
+
this.endGrouping();
|
|
3944
|
+
}
|
|
3903
3945
|
}
|
|
3904
|
-
|
|
3905
|
-
|
|
3946
|
+
/** Forgets every registration, or those `target` made (`removeAllActions(withTarget:)`), on both stacks and in the open group. */
|
|
3947
|
+
removeAllActions(target) {
|
|
3948
|
+
const mine = (action) => target === void 0 || action.target === target;
|
|
3949
|
+
const strip = (groups) => groups.filter((group) => {
|
|
3950
|
+
group.actions = group.actions.filter((action) => !mine(action));
|
|
3951
|
+
return group.actions.length > 0;
|
|
3952
|
+
});
|
|
3953
|
+
this.undoStack = strip(this.undoStack);
|
|
3954
|
+
this.redoStack = strip(this.redoStack);
|
|
3955
|
+
if (this.open) this.open.actions = this.open.actions.filter((action) => !mine(action));
|
|
3956
|
+
if (this.coalescing && !this.undoStack.includes(this.coalescing)) this.coalescing = null;
|
|
3957
|
+
this.changed();
|
|
3906
3958
|
}
|
|
3907
|
-
|
|
3908
|
-
|
|
3959
|
+
/** Calls `listener` after each change to `state`; returns what stops it. */
|
|
3960
|
+
subscribe = (listener) => {
|
|
3961
|
+
this.listeners.add(listener);
|
|
3962
|
+
return () => {
|
|
3963
|
+
this.listeners.delete(listener);
|
|
3964
|
+
};
|
|
3965
|
+
};
|
|
3966
|
+
/** Stops listening to the host, for a manager made in a test. */
|
|
3967
|
+
dispose() {
|
|
3968
|
+
this.stopListening?.();
|
|
3969
|
+
this.stopListening = null;
|
|
3909
3970
|
}
|
|
3910
|
-
|
|
3911
|
-
|
|
3971
|
+
push(group) {
|
|
3972
|
+
this.undoStack.push(group);
|
|
3973
|
+
if (this.levelsOfUndo > 0 && this.undoStack.length > this.levelsOfUndo) this.undoStack.splice(0, this.undoStack.length - this.levelsOfUndo);
|
|
3912
3974
|
}
|
|
3913
|
-
|
|
3914
|
-
|
|
3975
|
+
/** Closes `open`; a keyed group on top stays open to its key. */
|
|
3976
|
+
close() {
|
|
3977
|
+
const group = this.open;
|
|
3978
|
+
this.open = null;
|
|
3979
|
+
this.byEvent = false;
|
|
3980
|
+
if (group && group.key !== void 0 && this.undoStack[this.undoStack.length - 1] === group) this.coalescing = group;
|
|
3915
3981
|
}
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3982
|
+
endOpenGroups() {
|
|
3983
|
+
this.depth = 0;
|
|
3984
|
+
if (this.open) this.close();
|
|
3919
3985
|
}
|
|
3920
|
-
|
|
3921
|
-
const
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3986
|
+
run(group, direction) {
|
|
3987
|
+
const inverse = { name: group.name, named: true, actions: [], key: void 0 };
|
|
3988
|
+
this.open = inverse;
|
|
3989
|
+
this.byEvent = false;
|
|
3990
|
+
if (direction === "undo") this.undoing = true;
|
|
3991
|
+
else this.redoing = true;
|
|
3992
|
+
try {
|
|
3993
|
+
for (let i = group.actions.length - 1; i >= 0; i -= 1) group.actions[i].undo();
|
|
3994
|
+
} finally {
|
|
3995
|
+
this.undoing = false;
|
|
3996
|
+
this.redoing = false;
|
|
3997
|
+
this.open = null;
|
|
3998
|
+
if (inverse.actions.length > 0) {
|
|
3999
|
+
if (direction === "undo") this.redoStack.push(inverse);
|
|
4000
|
+
else this.push(inverse);
|
|
4001
|
+
}
|
|
4002
|
+
this.changed();
|
|
4003
|
+
}
|
|
3929
4004
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
4005
|
+
changed() {
|
|
4006
|
+
const next = { canUndo: this.canUndo, canRedo: this.canRedo, undoActionName: this.undoActionName, redoActionName: this.redoActionName };
|
|
4007
|
+
const last = this.snapshot;
|
|
4008
|
+
if (next.canUndo === last.canUndo && next.canRedo === last.canRedo && next.undoActionName === last.undoActionName && next.redoActionName === last.redoActionName) return;
|
|
4009
|
+
this.snapshot = next;
|
|
4010
|
+
this.host?.update(next);
|
|
4011
|
+
for (const listener of [...this.listeners]) listener();
|
|
3933
4012
|
}
|
|
3934
|
-
if (values.rotation3D && values.rotation3D.angle !== 0) style.rotation3D = { ...values.rotation3D, angle: round(values.rotation3D.angle) };
|
|
3935
|
-
if (values.opacity !== 1) style.opacity = round(values.opacity);
|
|
3936
|
-
if (values.blur !== 0) style.blur = round(values.blur);
|
|
3937
|
-
if (values.brightness !== 0) style.brightness = round(values.brightness);
|
|
3938
|
-
if (values.contrast !== 1) style.contrast = round(values.contrast);
|
|
3939
|
-
if (values.saturation !== 1) style.saturation = round(values.saturation);
|
|
3940
|
-
if (values.grayscale !== 0) style.grayscale = round(values.grayscale);
|
|
3941
|
-
if (values.hueRotation !== 0) style.hueRotation = round(values.hueRotation);
|
|
3942
|
-
return style;
|
|
3943
4013
|
}
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
"zstack",
|
|
3957
|
-
{ alignment: "center", reportsSize: true, ...needsFrame ? { reportsFrame: true } : {} },
|
|
3958
|
-
{
|
|
3959
|
-
geometry: (event) => {
|
|
3960
|
-
const next = nextGeometry(event, reported);
|
|
3961
|
-
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
3962
|
-
}
|
|
3963
|
-
},
|
|
3964
|
-
content
|
|
4014
|
+
const UndoManagerContext = createContext(null);
|
|
4015
|
+
let shared = null;
|
|
4016
|
+
function sharedUndoManager() {
|
|
4017
|
+
shared ??= new UndoManager();
|
|
4018
|
+
return shared;
|
|
4019
|
+
}
|
|
4020
|
+
function useUndoManager() {
|
|
4021
|
+
const manager = useContext(UndoManagerContext) ?? sharedUndoManager();
|
|
4022
|
+
useSyncExternalStore(
|
|
4023
|
+
manager.subscribe,
|
|
4024
|
+
() => manager.state,
|
|
4025
|
+
() => manager.state
|
|
3965
4026
|
);
|
|
4027
|
+
return manager;
|
|
3966
4028
|
}
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4029
|
+
const OWN = [
|
|
4030
|
+
EnvironmentContext,
|
|
4031
|
+
ViewEnvironmentContext,
|
|
4032
|
+
NavigationContext,
|
|
4033
|
+
DismissContext,
|
|
4034
|
+
UndoManagerContext
|
|
4035
|
+
];
|
|
4036
|
+
function useContextBridge(contexts = [], options = {}) {
|
|
4037
|
+
const own = options.environment === false ? OWN.filter((context) => context !== EnvironmentContext) : OWN;
|
|
4038
|
+
const all = [...own, ...contexts];
|
|
4039
|
+
const values = all.map((context) => useContext(context));
|
|
4040
|
+
return (children) => all.reduceRight((inner, context, index) => createElement(context.Provider, { value: values[index] }, inner), children);
|
|
3970
4041
|
}
|
|
3971
|
-
const
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
}
|
|
3976
|
-
function
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4042
|
+
const WINDOW_TOP_INSET = 10;
|
|
4043
|
+
function insetsOf(safeArea, fit) {
|
|
4044
|
+
const given = typeof safeArea === "number" ? { top: safeArea } : safeArea ?? { top: fit === "fill" ? WINDOW_TOP_INSET : 0 };
|
|
4045
|
+
return { top: given.top ?? 0, leading: given.leading ?? 0, bottom: given.bottom ?? 0, trailing: given.trailing ?? 0 };
|
|
4046
|
+
}
|
|
4047
|
+
function SwiftUIView({
|
|
4048
|
+
children,
|
|
4049
|
+
fit = "fill",
|
|
4050
|
+
colorScheme = "light",
|
|
4051
|
+
dynamicTypeSize = "large",
|
|
4052
|
+
contexts,
|
|
4053
|
+
assets,
|
|
4054
|
+
safeArea,
|
|
4055
|
+
history = true,
|
|
4056
|
+
keyboard = fit === "fill",
|
|
4057
|
+
sidebarTitleBar = true,
|
|
4058
|
+
className,
|
|
4059
|
+
style
|
|
4060
|
+
}) {
|
|
4061
|
+
const device = useRef(null);
|
|
4062
|
+
const screen = useRef(null);
|
|
4063
|
+
const mounted = useRef(null);
|
|
4064
|
+
const bridge = useContextBridge(contexts, { environment: false });
|
|
4065
|
+
const tree = bridge(children);
|
|
4066
|
+
const latest = useRef(tree);
|
|
4067
|
+
latest.current = tree;
|
|
4068
|
+
useLayoutEffect(() => {
|
|
4069
|
+
if (!screen.current) return;
|
|
4070
|
+
const instance = mount(screen.current, latest.current, {
|
|
4071
|
+
colorScheme,
|
|
4072
|
+
dynamicTypeSize,
|
|
4073
|
+
safeArea: insetsOf(safeArea, fit),
|
|
4074
|
+
contentHeight: fit === "content",
|
|
4075
|
+
history,
|
|
4076
|
+
keyboard,
|
|
4077
|
+
...assets ? { assets } : {}
|
|
4078
|
+
});
|
|
4079
|
+
mounted.current = instance;
|
|
4080
|
+
return () => {
|
|
4081
|
+
mounted.current = null;
|
|
4082
|
+
instance.unmount();
|
|
4083
|
+
};
|
|
4084
|
+
}, [fit, history, keyboard]);
|
|
4085
|
+
useLayoutEffect(() => {
|
|
4086
|
+
if (mounted.current) mounted.current.renderer.sidebarTitleBar = sidebarTitleBar;
|
|
4087
|
+
}, [sidebarTitleBar, fit, history, keyboard]);
|
|
4088
|
+
useLayoutEffect(() => {
|
|
4089
|
+
mounted.current?.root.render(tree);
|
|
4090
|
+
});
|
|
4091
|
+
const insets2 = insetsOf(safeArea, fit);
|
|
4092
|
+
const insetsKey = `${insets2.top},${insets2.leading},${insets2.bottom},${insets2.trailing}`;
|
|
4093
|
+
useLayoutEffect(() => {
|
|
4094
|
+
mounted.current?.renderer.setSafeArea(insets2);
|
|
4095
|
+
}, [insetsKey]);
|
|
4096
|
+
useLayoutEffect(() => {
|
|
4097
|
+
if (device.current) applyTypeSizeVariables(device.current, dynamicTypeSize, mounted.current?.renderer.platform);
|
|
4098
|
+
mounted.current?.setEnvironment({ colorScheme, dynamicTypeSize });
|
|
4099
|
+
}, [colorScheme, dynamicTypeSize]);
|
|
4100
|
+
const classes = ["device", "sb-island", className].filter(Boolean).join(" ");
|
|
4101
|
+
return /* @__PURE__ */ jsx("div", { ref: device, className: classes, "data-theme": colorScheme, "data-type-size": dynamicTypeSize, "data-state": "ready", "data-sb-fit": fit, style, children: /* @__PURE__ */ jsx("div", { className: "device-screen", children: /* @__PURE__ */ jsx("div", { ref: screen, className: "screen" }) }) });
|
|
3986
4102
|
}
|
|
3987
4103
|
const r = (n) => {
|
|
3988
4104
|
const v = Math.round(n * 100) / 100;
|
|
@@ -5982,6 +6098,7 @@ function TextEditor(props) {
|
|
|
5982
6098
|
if (focus) editor["focused"] = focus[0];
|
|
5983
6099
|
if (selection) editor["selection"] = { start: selection[0].start, end: selection[0].end };
|
|
5984
6100
|
if (own.onDeleteBackward) editor["deleteBackward"] = true;
|
|
6101
|
+
if (own.marks && own.marks.length > 0) editor["marks"] = own.marks.map((mark) => ({ start: mark.start, end: mark.end, color: color(mark.color ?? MARK_COLOR) }));
|
|
5985
6102
|
return applyModifiers(
|
|
5986
6103
|
sb("texteditor", editor, {
|
|
5987
6104
|
text: (event) => setText(rich ? AttributedText.replacingCharacters(text, event.value) : event.value),
|
|
@@ -5996,6 +6113,7 @@ function TextEditor(props) {
|
|
|
5996
6113
|
modifiers
|
|
5997
6114
|
);
|
|
5998
6115
|
}
|
|
6116
|
+
const MARK_COLOR = opacity("accent", 0.25);
|
|
5999
6117
|
function buttonDisabled(modifiers) {
|
|
6000
6118
|
return modifiers.some(([key, value]) => key === "disabled" && value === true);
|
|
6001
6119
|
}
|
|
@@ -6054,7 +6172,9 @@ ContainerRelativeShape.shape = { kind: "containerRelative", cornerRadius: null }
|
|
|
6054
6172
|
function Shape(props) {
|
|
6055
6173
|
const { own, modifiers } = splitProps(props);
|
|
6056
6174
|
const [size, setSize] = useState(null);
|
|
6057
|
-
const
|
|
6175
|
+
const sized = useRef(false);
|
|
6176
|
+
const affine = sized.current ? null : affinePath(own.path);
|
|
6177
|
+
if (affine === null) sized.current = true;
|
|
6058
6178
|
const shapeProps = {
|
|
6059
6179
|
shape: "path",
|
|
6060
6180
|
cornerRadius: 0,
|
|
@@ -6664,7 +6784,7 @@ function List(props) {
|
|
|
6664
6784
|
const ownSettings = takeScrollSettings(modifiers);
|
|
6665
6785
|
const edgeEffect = edgeEffectProp(useScrollSettings(ownSettings));
|
|
6666
6786
|
if (edgeEffect) listProps["edgeEffect"] = edgeEffect;
|
|
6667
|
-
const element = /* @__PURE__ */ jsx(LazyContext.Provider, { value: "vertical", children: sb("list", listProps, refresh.handlers, providingScrollSettings(ownSettings, wrapRows(own.children))) });
|
|
6787
|
+
const element = /* @__PURE__ */ jsx(LazyContext.Provider, { value: "vertical", children: /* @__PURE__ */ jsx(LazyStackContext.Provider, { value: false, children: sb("list", listProps, refresh.handlers, providingScrollSettings(ownSettings, wrapRows(own.children))) }) });
|
|
6668
6788
|
return applyModifiers(
|
|
6669
6789
|
selection ? /* @__PURE__ */ jsx(ListSelectionContext.Provider, { value: selection, children: element }) : element,
|
|
6670
6790
|
modifiers
|
|
@@ -7310,10 +7430,10 @@ function ViewThatFits(props) {
|
|
|
7310
7430
|
return applyModifiers(sb("viewthatfits", { axes: own.axes ?? "both" }, void 0, own.children), modifiers);
|
|
7311
7431
|
}
|
|
7312
7432
|
function LazyVStack(props) {
|
|
7313
|
-
return /* @__PURE__ */ jsx(LazyContext.Provider, { value: "vertical", children: /* @__PURE__ */ jsx(VStack, { ...props }) });
|
|
7433
|
+
return /* @__PURE__ */ jsx(LazyContext.Provider, { value: "vertical", children: /* @__PURE__ */ jsx(LazyStackContext.Provider, { value: true, children: /* @__PURE__ */ jsx(VStack, { ...props }) }) });
|
|
7314
7434
|
}
|
|
7315
7435
|
function LazyHStack(props) {
|
|
7316
|
-
return /* @__PURE__ */ jsx(LazyContext.Provider, { value: "horizontal", children: /* @__PURE__ */ jsx(HStack, { ...props }) });
|
|
7436
|
+
return /* @__PURE__ */ jsx(LazyContext.Provider, { value: "horizontal", children: /* @__PURE__ */ jsx(LazyStackContext.Provider, { value: true, children: /* @__PURE__ */ jsx(HStack, { ...props }) }) });
|
|
7317
7437
|
}
|
|
7318
7438
|
function ContentUnavailableView(props) {
|
|
7319
7439
|
const { own, modifiers } = splitProps(props);
|
|
@@ -8194,6 +8314,7 @@ export {
|
|
|
8194
8314
|
Divider,
|
|
8195
8315
|
EditButton,
|
|
8196
8316
|
Ellipse,
|
|
8317
|
+
FlowStack,
|
|
8197
8318
|
Font,
|
|
8198
8319
|
ForEach,
|
|
8199
8320
|
Form,
|
|
@@ -8209,6 +8330,7 @@ export {
|
|
|
8209
8330
|
GroupBox,
|
|
8210
8331
|
HStack,
|
|
8211
8332
|
Host,
|
|
8333
|
+
HostElement,
|
|
8212
8334
|
Image$1 as Image,
|
|
8213
8335
|
KeyframeAnimator,
|
|
8214
8336
|
LOADING_INDICATOR_DELAY_MS,
|
|
@@ -8347,6 +8469,7 @@ export {
|
|
|
8347
8469
|
usePlatform,
|
|
8348
8470
|
useRedacted,
|
|
8349
8471
|
useRefreshable,
|
|
8472
|
+
useRemoteSidebar,
|
|
8350
8473
|
useReportSplitSelection,
|
|
8351
8474
|
useScenePhase,
|
|
8352
8475
|
useSpeechRecognition,
|