@swiftbrowser/react 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/components/remoteTree.d.ts.map +1 -1
- package/dist/index.js +68 -6
- package/dist/index.js.map +1 -1
- package/dist/inheritedStyle.d.ts +31 -0
- package/dist/inheritedStyle.d.ts.map +1 -0
- package/dist/island.d.ts +8 -1
- package/dist/island.d.ts.map +1 -1
- package/dist/modifiers.d.ts.map +1 -1
- package/dist/mount.d.ts +7 -0
- package/dist/mount.d.ts.map +1 -1
- package/dist/presentation.d.ts +10 -2
- package/dist/presentation.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -304,6 +304,16 @@ title="Rename" action={rename} /></> }}`);
|
|
|
304
304
|
`presentationDetents` inside a sheet sets its detents. `useDismiss()` inside
|
|
305
305
|
a pushed screen or a sheet pops or dismisses it.
|
|
306
306
|
|
|
307
|
+
A sheet, a full-screen cover or a popover inherits the environment of the
|
|
308
|
+
view that presents it, as SwiftUI's presentations do, though it is drawn at
|
|
309
|
+
the root: a `defaultMinListRowHeight`, `font`, `fontWeight`, `bold`,
|
|
310
|
+
`monospacedDigit`, `tint`, `lineLimit`, `multilineTextAlignment` or
|
|
311
|
+
`imageScale` set around the presenter reaches the sheet's lists and text,
|
|
312
|
+
and so does one set on the presenting view itself when written after the
|
|
313
|
+
`sheet` (around it, as SwiftUI orders modifiers). An app drawn through
|
|
314
|
+
`RemoteTree` has its sheets inherit the host's environment around the tree
|
|
315
|
+
too.
|
|
316
|
+
|
|
307
317
|
Navigation is mirrored in the browser's history by default: pushing a
|
|
308
318
|
screen or presenting a sheet adds an entry, and the browser's back (a
|
|
309
319
|
phone's edge swipe, Android's back gesture, the toolbar button) pops or
|
|
@@ -448,6 +458,12 @@ dragged the sidebar to on a Mac, once the drag ends; keep it (in
|
|
|
448
458
|
`useAppStorage`, say) and pass it back as `ideal` to start there next time, as
|
|
449
459
|
a Mac app restores its columns.
|
|
450
460
|
|
|
461
|
+
On a Mac the sidebar panel's top 44 points are the window's color, where
|
|
462
|
+
macOS draws the title bar behind the window's buttons. A page has no window
|
|
463
|
+
buttons there; `<SwiftUIView sidebarTitleBar={false}>` (or `mount(...,
|
|
464
|
+
{ sidebarTitleBar: false })`, `renderer.sidebarTitleBar = false`) keeps the
|
|
465
|
+
panel's sidebar fill to its top. Web only: a native app is in a real window.
|
|
466
|
+
|
|
451
467
|
### Platform
|
|
452
468
|
|
|
453
469
|
`usePlatform()` is `ios` or `macos`: the platform the app is drawn as. A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteTree.d.ts","sourceRoot":"","sources":["../../src/components/remoteTree.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"remoteTree.d.ts","sourceRoot":"","sources":["../../src/components/remoteTree.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAsF,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3H,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM7D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAClC;AAgED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,eAAe,GAAG,SAAS,CA6E5E"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, createElement, useSyncExternalStore, useLayoutEffect, useRef, Fragment, useState, Children, useEffect,
|
|
1
|
+
import { createContext, useContext, createElement, isValidElement, useMemo, useSyncExternalStore, useLayoutEffect, useRef, Fragment, useState, Children, useEffect, useId, cloneElement, useCallback } from "react";
|
|
2
2
|
import { DefaultEventPriority, ConcurrentRoot } from "react-reconciler/constants";
|
|
3
3
|
import Reconciler from "react-reconciler";
|
|
4
4
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
@@ -746,6 +746,37 @@ function sb(kind, props, on, children, target) {
|
|
|
746
746
|
if (target) hostProps.target = target;
|
|
747
747
|
return children === void 0 ? createElement("sb", hostProps) : createElement("sb", hostProps, children);
|
|
748
748
|
}
|
|
749
|
+
const INHERITED_STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
750
|
+
"font",
|
|
751
|
+
"fontWeight",
|
|
752
|
+
"bold",
|
|
753
|
+
"monospacedDigit",
|
|
754
|
+
"tint",
|
|
755
|
+
"lineLimit",
|
|
756
|
+
"multilineTextAlignment",
|
|
757
|
+
"imageScale",
|
|
758
|
+
"defaultMinListRowHeight"
|
|
759
|
+
]);
|
|
760
|
+
const PRESENTATION_KEYS = /* @__PURE__ */ new Set(["sheet", "fullScreenCover", "popover"]);
|
|
761
|
+
const InheritedStylesContext = createContext([]);
|
|
762
|
+
function useInheritedStyles() {
|
|
763
|
+
return useContext(InheritedStylesContext);
|
|
764
|
+
}
|
|
765
|
+
function styleOf(node) {
|
|
766
|
+
if (!isValidElement(node) || node.props.kind !== "styled") return {};
|
|
767
|
+
return node.props.props?.style ?? {};
|
|
768
|
+
}
|
|
769
|
+
function InheritStyle({ style, children }) {
|
|
770
|
+
const parent = useContext(InheritedStylesContext);
|
|
771
|
+
const key = JSON.stringify(style);
|
|
772
|
+
const value = useMemo(() => key === "{}" ? parent : [...parent, style], [parent, key]);
|
|
773
|
+
return createElement(InheritedStylesContext.Provider, { value }, children);
|
|
774
|
+
}
|
|
775
|
+
function replayStyles(styles, content) {
|
|
776
|
+
if (styles.length === 0) return content;
|
|
777
|
+
const provided = createElement(InheritedStylesContext.Provider, { value: styles }, content);
|
|
778
|
+
return styles.reduceRight((child, style) => sb("styled", { style }, void 0, child), provided);
|
|
779
|
+
}
|
|
749
780
|
const NavigationContext = createContext(null);
|
|
750
781
|
const ScreenDepthContext = createContext(0);
|
|
751
782
|
function useScreenDepth() {
|
|
@@ -786,6 +817,10 @@ function renderNode(root, node, stack) {
|
|
|
786
817
|
const children = node.children.length ? node.children.map((child) => renderNode(root, child, stack)) : void 0;
|
|
787
818
|
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), children));
|
|
788
819
|
}
|
|
820
|
+
function renderSheet(root, node, stack, inherited) {
|
|
821
|
+
const children = node.children.map((child) => renderNode(root, child, stack));
|
|
822
|
+
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), replayStyles(inherited, children)));
|
|
823
|
+
}
|
|
789
824
|
function renderScreen(root, screen, stack) {
|
|
790
825
|
const out = [screenPrefs(screen.props, "$screen")];
|
|
791
826
|
for (const child of screen.children) {
|
|
@@ -804,6 +839,7 @@ function RemoteScreen({ root, id }) {
|
|
|
804
839
|
function RemoteTree({ root, initialPath }) {
|
|
805
840
|
useSyncExternalStore(root.subscribe, root.getVersion, root.getVersion);
|
|
806
841
|
const environment = useContext(EnvironmentContext);
|
|
842
|
+
const inherited = useInheritedStyles();
|
|
807
843
|
const tree = useContext(HostTreeContext);
|
|
808
844
|
const navigation = useNavigation();
|
|
809
845
|
const depth = useScreenDepth();
|
|
@@ -859,7 +895,7 @@ function RemoteTree({ root, initialPath }) {
|
|
|
859
895
|
if ("colorScheme" in root.rootProps)
|
|
860
896
|
out.push(createElement(Fragment, { key: "$scheme" }, sb(PREF_KIND, { colorScheme: root.rootProps["colorScheme"] }, void 0, void 0, "root")));
|
|
861
897
|
for (const child of root.root.children) {
|
|
862
|
-
const drawn = renderNode(root, child, stack);
|
|
898
|
+
const drawn = child.kind === "sheet" && inherited.length > 0 ? renderSheet(root, child, stack, inherited) : renderNode(root, child, stack);
|
|
863
899
|
if (child.kind === "sheet" || child.kind === "alert") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "root")));
|
|
864
900
|
else if (child.kind === "toolbar" || child.kind === "searchfield") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "navscreen")));
|
|
865
901
|
else out.push(drawn);
|
|
@@ -1052,6 +1088,7 @@ function mount(screen, element, options = {}) {
|
|
|
1052
1088
|
platform: options.platform === void 0 || options.platform === "auto" ? decidePlatform(width) : options.platform
|
|
1053
1089
|
};
|
|
1054
1090
|
renderer.contentHeight = options.contentHeight ?? false;
|
|
1091
|
+
if (options.sidebarTitleBar === false) renderer.sidebarTitleBar = false;
|
|
1055
1092
|
if (options.assets) renderer.setAssetCatalog(options.assets);
|
|
1056
1093
|
if (options.app) browserEnvironment.files?.setApp?.(options.app);
|
|
1057
1094
|
renderer.setEnvironment({ colorScheme: environment.colorScheme, dynamicTypeSize: environment.dynamicTypeSize, platform: environment.platform });
|
|
@@ -1360,6 +1397,7 @@ function SwiftUIView({
|
|
|
1360
1397
|
safeArea,
|
|
1361
1398
|
history = true,
|
|
1362
1399
|
keyboard = fit === "fill",
|
|
1400
|
+
sidebarTitleBar = true,
|
|
1363
1401
|
className,
|
|
1364
1402
|
style
|
|
1365
1403
|
}) {
|
|
@@ -1387,6 +1425,9 @@ function SwiftUIView({
|
|
|
1387
1425
|
instance.unmount();
|
|
1388
1426
|
};
|
|
1389
1427
|
}, [fit, history, keyboard]);
|
|
1428
|
+
useLayoutEffect(() => {
|
|
1429
|
+
if (mounted.current) mounted.current.renderer.sidebarTitleBar = sidebarTitleBar;
|
|
1430
|
+
}, [sidebarTitleBar, fit, history, keyboard]);
|
|
1390
1431
|
useLayoutEffect(() => {
|
|
1391
1432
|
mounted.current?.root.render(tree);
|
|
1392
1433
|
});
|
|
@@ -2334,7 +2375,8 @@ function useReportSplitSelection(split, selected, clear, active2 = true) {
|
|
|
2334
2375
|
function OutsideSplit({ children }) {
|
|
2335
2376
|
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
2336
2377
|
}
|
|
2337
|
-
function SheetPresenter({ isPresented, onDismiss, content, fullScreen }) {
|
|
2378
|
+
function SheetPresenter({ isPresented, onDismiss, content, fullScreen, inherited }) {
|
|
2379
|
+
const around = useInheritedStyles();
|
|
2338
2380
|
const [presented, setPresented] = readBinding(isPresented);
|
|
2339
2381
|
if (!presented) return null;
|
|
2340
2382
|
const dismiss = () => {
|
|
@@ -2350,7 +2392,10 @@ function SheetPresenter({ isPresented, onDismiss, content, fullScreen }) {
|
|
|
2350
2392
|
"sheet",
|
|
2351
2393
|
{ detents },
|
|
2352
2394
|
{ tap: dismiss },
|
|
2353
|
-
|
|
2395
|
+
replayStyles(
|
|
2396
|
+
inherited && inherited.length > 0 ? [...around, ...inherited] : around,
|
|
2397
|
+
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(OutsideSplit, { children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) }) })
|
|
2398
|
+
)
|
|
2354
2399
|
),
|
|
2355
2400
|
"root"
|
|
2356
2401
|
);
|
|
@@ -2857,13 +2902,30 @@ function applyModifiers(element, modifiers) {
|
|
|
2857
2902
|
const isPreference = (side) => isValidElement(side) && side.props.kind === PREF_KIND;
|
|
2858
2903
|
function wrap(element, modifiers, sides) {
|
|
2859
2904
|
let node = element;
|
|
2905
|
+
const holds = holdsViews(element);
|
|
2906
|
+
const presentations = [];
|
|
2860
2907
|
for (const [key, value] of modifiers) {
|
|
2861
2908
|
const inactive = value === void 0 || value === null && key !== "lineLimit" && key !== "badge";
|
|
2909
|
+
const before = sides.length;
|
|
2862
2910
|
const next = inactive ? node : apply(key, value, node, sides);
|
|
2863
2911
|
node = next === node ? neutral(key, node) : next;
|
|
2912
|
+
if (INHERITED_STYLE_KEYS.has(key)) {
|
|
2913
|
+
const style = styleOf(node);
|
|
2914
|
+
if (Object.keys(style).length > 0) for (const presentation of presentations) presentation.after.push(style);
|
|
2915
|
+
if (holds) node = createElement(InheritStyle, { style }, node);
|
|
2916
|
+
}
|
|
2917
|
+
if (PRESENTATION_KEYS.has(key) && sides.length > before) presentations.push({ at: before, after: [] });
|
|
2918
|
+
}
|
|
2919
|
+
for (const { at, after } of presentations) {
|
|
2920
|
+
const side = sides[at];
|
|
2921
|
+
if (after.length > 0 && isValidElement(side)) sides[at] = cloneElement(side, { inherited: after.reverse() });
|
|
2864
2922
|
}
|
|
2865
2923
|
return node;
|
|
2866
2924
|
}
|
|
2925
|
+
function holdsViews(element) {
|
|
2926
|
+
if (!isValidElement(element)) return false;
|
|
2927
|
+
return element.type !== "sb" || element.props.children !== void 0;
|
|
2928
|
+
}
|
|
2867
2929
|
const STYLED_KEYS = /* @__PURE__ */ new Set([
|
|
2868
2930
|
"padding",
|
|
2869
2931
|
"font",
|
|
@@ -6327,7 +6389,7 @@ function Chart(props) {
|
|
|
6327
6389
|
const key = mark.props.foregroundStyleBy;
|
|
6328
6390
|
if (key !== void 0 && !series.includes(key)) series.push(key);
|
|
6329
6391
|
}
|
|
6330
|
-
const
|
|
6392
|
+
const styleOf2 = (mark) => {
|
|
6331
6393
|
if (mark.props.foregroundStyle !== void 0) return shapeStyle(mark.props.foregroundStyle);
|
|
6332
6394
|
const key = mark.props.foregroundStyleBy;
|
|
6333
6395
|
if (key !== void 0) return { name: PALETTE[series.indexOf(key) % PALETTE.length] };
|
|
@@ -6385,7 +6447,7 @@ function Chart(props) {
|
|
|
6385
6447
|
);
|
|
6386
6448
|
};
|
|
6387
6449
|
const common = (mark) => {
|
|
6388
|
-
const base = { style:
|
|
6450
|
+
const base = { style: styleOf2(mark) };
|
|
6389
6451
|
if (mark.props.opacity !== void 0) base.opacity = mark.props.opacity;
|
|
6390
6452
|
return base;
|
|
6391
6453
|
};
|