@swiftbrowser/react 0.4.0 → 0.5.1
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 +101 -12
- package/dist/components/geometry.d.ts +32 -2
- package/dist/components/geometry.d.ts.map +1 -1
- package/dist/components/host.d.ts.map +1 -1
- package/dist/components/lists.d.ts.map +1 -1
- package/dist/components/split.d.ts +18 -4
- package/dist/components/split.d.ts.map +1 -1
- package/dist/components/stacks.d.ts +22 -1
- package/dist/components/stacks.d.ts.map +1 -1
- package/dist/host/root.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1382 -1020
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts.map +1 -1
- package/dist/modifiers.d.ts +54 -1
- package/dist/modifiers.d.ts.map +1 -1
- package/dist/presentation.d.ts.map +1 -1
- package/dist/scrollEnvironment.d.ts +50 -0
- package/dist/scrollEnvironment.d.ts.map +1 -0
- package/dist/visualEffect.d.ts +120 -0
- package/dist/visualEffect.d.ts.map +1 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createContext, useContext, createElement, useRef, useLayoutEffect,
|
|
1
|
+
import { createContext, useContext, createElement, useRef, useLayoutEffect, useState, Children, useEffect, isValidElement, Fragment, useId, cloneElement, useSyncExternalStore } from "react";
|
|
2
2
|
import { DefaultEventPriority, ConcurrentRoot } from "react-reconciler/constants";
|
|
3
3
|
import Reconciler from "react-reconciler";
|
|
4
4
|
import { horizontalSizeClassFor } from "@swiftbrowser/web/src/protocol";
|
|
5
5
|
import { Renderer } from "@swiftbrowser/web/src/renderer";
|
|
6
|
-
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
6
|
+
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
7
7
|
import { applyTypeSizeVariables } from "@swiftbrowser/web/src/typography";
|
|
8
8
|
import { registerHostContent, notifyHostContentChange, unregisterHostContent } from "@swiftbrowser/web/src/hostContent";
|
|
9
9
|
import { createRoot } from "react-dom/client";
|
|
@@ -534,6 +534,85 @@ function readBinding(value, onChange) {
|
|
|
534
534
|
return [value, onChange ?? (() => {
|
|
535
535
|
})];
|
|
536
536
|
}
|
|
537
|
+
function sb(kind, props, on, children, target) {
|
|
538
|
+
const hostProps = { kind };
|
|
539
|
+
if (props) hostProps.props = props;
|
|
540
|
+
if (on) hostProps.on = on;
|
|
541
|
+
if (target) hostProps.target = target;
|
|
542
|
+
return children === void 0 ? createElement("sb", hostProps) : createElement("sb", hostProps, children);
|
|
543
|
+
}
|
|
544
|
+
const CoordinateSpacesContext = createContext({});
|
|
545
|
+
function useCoordinateSpaces() {
|
|
546
|
+
return useContext(CoordinateSpacesContext);
|
|
547
|
+
}
|
|
548
|
+
function CoordinateSpace({ name, children }) {
|
|
549
|
+
const spaces = useContext(CoordinateSpacesContext);
|
|
550
|
+
const [frame2, setFrame] = useState(null);
|
|
551
|
+
return /* @__PURE__ */ jsx(CoordinateSpacesContext.Provider, { value: { ...spaces, [name]: frame2 }, children: sb(
|
|
552
|
+
"zstack",
|
|
553
|
+
{ alignment: "center", reportsSize: true, reportsFrame: true },
|
|
554
|
+
{
|
|
555
|
+
geometry: (event) => {
|
|
556
|
+
const next = { x: event.x ?? 0, y: event.y ?? 0, width: event.width, height: event.height };
|
|
557
|
+
if (!frame2 || frame2.x !== next.x || frame2.y !== next.y || frame2.width !== next.width || frame2.height !== next.height) setFrame(next);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
children
|
|
561
|
+
) });
|
|
562
|
+
}
|
|
563
|
+
let active = null;
|
|
564
|
+
function Draggable({ payload, children }) {
|
|
565
|
+
return sb(
|
|
566
|
+
"draggable",
|
|
567
|
+
{},
|
|
568
|
+
{
|
|
569
|
+
dragstart: (event) => {
|
|
570
|
+
active = { id: event.id, payload };
|
|
571
|
+
},
|
|
572
|
+
dragend: (event) => {
|
|
573
|
+
if (active?.id === event.id) active = null;
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
children
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
function itemValue(item) {
|
|
580
|
+
if (item.text !== void 0) {
|
|
581
|
+
if (item.type === "text/uri-list") {
|
|
582
|
+
try {
|
|
583
|
+
return new URL(item.text.split(/\r?\n/)[0].trim());
|
|
584
|
+
} catch {
|
|
585
|
+
return item.text;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return item.text;
|
|
589
|
+
}
|
|
590
|
+
const binary = atob(item.data ?? "");
|
|
591
|
+
const bytes = new Uint8Array(binary.length);
|
|
592
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
593
|
+
return typeof File !== "undefined" ? new File([bytes], item.name ?? "file", { type: item.type }) : bytes;
|
|
594
|
+
}
|
|
595
|
+
function DropDestination({ action, isTargeted, accepts, children }) {
|
|
596
|
+
return sb(
|
|
597
|
+
"dropdestination",
|
|
598
|
+
{ accepts: accepts ?? [] },
|
|
599
|
+
{
|
|
600
|
+
drop: (event) => {
|
|
601
|
+
if (event.phase === "entered") {
|
|
602
|
+
isTargeted?.(true);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
isTargeted?.(false);
|
|
606
|
+
if (event.phase !== "performed") return;
|
|
607
|
+
let items;
|
|
608
|
+
if (event.source !== void 0) items = active && active.id === event.source ? [active.payload] : [];
|
|
609
|
+
else items = (event.items ?? []).map(itemValue);
|
|
610
|
+
if (items.length > 0) action(items, { x: event.x, y: event.y });
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
children
|
|
614
|
+
);
|
|
615
|
+
}
|
|
537
616
|
const HIERARCHY = { primary: 1, secondary: 2, tertiary: 3, quaternary: 4 };
|
|
538
617
|
function rgb(r2, g, b, a = 1) {
|
|
539
618
|
return { r: r2, g, b, a };
|
|
@@ -680,369 +759,746 @@ function insets(edges, amount) {
|
|
|
680
759
|
}
|
|
681
760
|
return result;
|
|
682
761
|
}
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
parts = [];
|
|
689
|
-
current = null;
|
|
690
|
-
start = null;
|
|
691
|
-
constructor(build) {
|
|
692
|
-
build?.(this);
|
|
693
|
-
}
|
|
694
|
-
/** `Path(rect)` */
|
|
695
|
-
static rect(rect) {
|
|
696
|
-
return new Path().addRect(rect);
|
|
697
|
-
}
|
|
698
|
-
/** `Path(roundedRect:cornerRadius:)` */
|
|
699
|
-
static roundedRect(rect, cornerRadius) {
|
|
700
|
-
return new Path().addRoundedRect(rect, cornerRadius);
|
|
701
|
-
}
|
|
702
|
-
/** `Path(ellipseIn:)` */
|
|
703
|
-
static ellipse(rect) {
|
|
704
|
-
return new Path().addEllipse(rect);
|
|
705
|
-
}
|
|
706
|
-
move(to) {
|
|
707
|
-
this.parts.push(`M${r(to.x)} ${r(to.y)}`);
|
|
708
|
-
this.current = to;
|
|
709
|
-
this.start = to;
|
|
710
|
-
return this;
|
|
711
|
-
}
|
|
712
|
-
addLine(to) {
|
|
713
|
-
if (!this.current) return this.move(to);
|
|
714
|
-
this.parts.push(`L${r(to.x)} ${r(to.y)}`);
|
|
715
|
-
this.current = to;
|
|
716
|
-
return this;
|
|
717
|
-
}
|
|
718
|
-
addLines(points) {
|
|
719
|
-
points.forEach((point, index) => index === 0 ? this.move(point) : this.addLine(point));
|
|
720
|
-
return this;
|
|
721
|
-
}
|
|
722
|
-
addQuadCurve(to, control) {
|
|
723
|
-
if (!this.current) this.move(control);
|
|
724
|
-
this.parts.push(`Q${r(control.x)} ${r(control.y)} ${r(to.x)} ${r(to.y)}`);
|
|
725
|
-
this.current = to;
|
|
726
|
-
return this;
|
|
727
|
-
}
|
|
728
|
-
addCurve(to, control1, control2) {
|
|
729
|
-
if (!this.current) this.move(control1);
|
|
730
|
-
this.parts.push(`C${r(control1.x)} ${r(control1.y)} ${r(control2.x)} ${r(control2.y)} ${r(to.x)} ${r(to.y)}`);
|
|
731
|
-
this.current = to;
|
|
732
|
-
return this;
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* `addArc(center:radius:startAngle:endAngle:clockwise:)`, angles in
|
|
736
|
-
* degrees. As in SwiftUI's flipped coordinates, `clockwise: false` draws
|
|
737
|
-
* clockwise on screen.
|
|
738
|
-
*/
|
|
739
|
-
addArc(center, radius, startAngle, endAngle, clockwise) {
|
|
740
|
-
const rad = (deg) => deg * Math.PI / 180;
|
|
741
|
-
const point = (deg) => ({ x: center.x + radius * Math.cos(rad(deg)), y: center.y + radius * Math.sin(rad(deg)) });
|
|
742
|
-
const from = point(startAngle);
|
|
743
|
-
if (this.current) this.addLine(from);
|
|
744
|
-
else this.move(from);
|
|
745
|
-
const sweepPositive = !clockwise;
|
|
746
|
-
let delta = endAngle - startAngle;
|
|
747
|
-
if (sweepPositive) while (delta < 0) delta += 360;
|
|
748
|
-
else while (delta > 0) delta -= 360;
|
|
749
|
-
if (Math.abs(delta) >= 360) {
|
|
750
|
-
const half = point(startAngle + (sweepPositive ? 180 : -180));
|
|
751
|
-
const flag = sweepPositive ? 1 : 0;
|
|
752
|
-
this.parts.push(`A${r(radius)} ${r(radius)} 0 0 ${flag} ${r(half.x)} ${r(half.y)}`);
|
|
753
|
-
this.parts.push(`A${r(radius)} ${r(radius)} 0 0 ${flag} ${r(from.x)} ${r(from.y)}`);
|
|
754
|
-
this.current = from;
|
|
755
|
-
return this;
|
|
756
|
-
}
|
|
757
|
-
const to = point(startAngle + delta);
|
|
758
|
-
const large = Math.abs(delta) > 180 ? 1 : 0;
|
|
759
|
-
this.parts.push(`A${r(radius)} ${r(radius)} 0 ${large} ${sweepPositive ? 1 : 0} ${r(to.x)} ${r(to.y)}`);
|
|
760
|
-
this.current = to;
|
|
761
|
-
return this;
|
|
762
|
-
}
|
|
763
|
-
addRect(rect) {
|
|
764
|
-
this.move({ x: rect.x, y: rect.y });
|
|
765
|
-
this.addLine({ x: rect.x + rect.width, y: rect.y });
|
|
766
|
-
this.addLine({ x: rect.x + rect.width, y: rect.y + rect.height });
|
|
767
|
-
this.addLine({ x: rect.x, y: rect.y + rect.height });
|
|
768
|
-
return this.closeSubpath();
|
|
769
|
-
}
|
|
770
|
-
addRoundedRect(rect, cornerRadius) {
|
|
771
|
-
const c = Math.max(0, Math.min(cornerRadius, rect.width / 2, rect.height / 2));
|
|
772
|
-
if (c === 0) return this.addRect(rect);
|
|
773
|
-
const { x, y, width: w, height: h } = rect;
|
|
774
|
-
this.move({ x: x + c, y });
|
|
775
|
-
this.addLine({ x: x + w - c, y });
|
|
776
|
-
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + w)} ${r(y + c)}`);
|
|
777
|
-
this.current = { x: x + w, y: y + c };
|
|
778
|
-
this.addLine({ x: x + w, y: y + h - c });
|
|
779
|
-
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + w - c)} ${r(y + h)}`);
|
|
780
|
-
this.current = { x: x + w - c, y: y + h };
|
|
781
|
-
this.addLine({ x: x + c, y: y + h });
|
|
782
|
-
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x)} ${r(y + h - c)}`);
|
|
783
|
-
this.current = { x, y: y + h - c };
|
|
784
|
-
this.addLine({ x, y: y + c });
|
|
785
|
-
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + c)} ${r(y)}`);
|
|
786
|
-
this.current = { x: x + c, y };
|
|
787
|
-
return this.closeSubpath();
|
|
788
|
-
}
|
|
789
|
-
addEllipse(rect) {
|
|
790
|
-
const rx = rect.width / 2;
|
|
791
|
-
const ry = rect.height / 2;
|
|
792
|
-
const cx = rect.x + rx;
|
|
793
|
-
const cy = rect.y + ry;
|
|
794
|
-
this.move({ x: cx + rx, y: cy });
|
|
795
|
-
this.parts.push(`A${r(rx)} ${r(ry)} 0 0 1 ${r(cx - rx)} ${r(cy)}`);
|
|
796
|
-
this.parts.push(`A${r(rx)} ${r(ry)} 0 0 1 ${r(cx + rx)} ${r(cy)}`);
|
|
797
|
-
this.current = { x: cx + rx, y: cy };
|
|
798
|
-
return this.closeSubpath();
|
|
799
|
-
}
|
|
800
|
-
addPath(path) {
|
|
801
|
-
this.parts.push(path.svg());
|
|
802
|
-
return this;
|
|
803
|
-
}
|
|
804
|
-
closeSubpath() {
|
|
805
|
-
this.parts.push("Z");
|
|
806
|
-
this.current = this.start;
|
|
807
|
-
return this;
|
|
808
|
-
}
|
|
809
|
-
get isEmpty() {
|
|
810
|
-
return this.parts.length === 0;
|
|
811
|
-
}
|
|
812
|
-
/** The SVG path data. */
|
|
813
|
-
svg() {
|
|
814
|
-
return this.parts.join("");
|
|
815
|
-
}
|
|
816
|
-
toString() {
|
|
817
|
-
return this.svg();
|
|
818
|
-
}
|
|
762
|
+
const ScrollSettingsContext = createContext({});
|
|
763
|
+
function edgesOf(edges) {
|
|
764
|
+
const list = Array.isArray(edges) ? edges : [edges];
|
|
765
|
+
const all = list.some((edge) => edge === "all" || edge === "vertical");
|
|
766
|
+
return { top: all || list.includes("top"), bottom: all || list.includes("bottom") };
|
|
819
767
|
}
|
|
820
|
-
function
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
768
|
+
function edgeStyleSettings(value) {
|
|
769
|
+
const [style, edges] = Array.isArray(value) ? value : [value, "all"];
|
|
770
|
+
const on = edgesOf(edges);
|
|
771
|
+
const name = style === "automatic" ? void 0 : style;
|
|
772
|
+
const result = {};
|
|
773
|
+
if (on.top) result.topStyle = name;
|
|
774
|
+
if (on.bottom) result.bottomStyle = name;
|
|
775
|
+
return result;
|
|
826
776
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
active = { id: event.id, payload };
|
|
835
|
-
},
|
|
836
|
-
dragend: (event) => {
|
|
837
|
-
if (active?.id === event.id) active = null;
|
|
838
|
-
}
|
|
839
|
-
},
|
|
840
|
-
children
|
|
841
|
-
);
|
|
777
|
+
function edgeHiddenSettings(value) {
|
|
778
|
+
const [hidden, edges] = Array.isArray(value) ? value : [value, "all"];
|
|
779
|
+
const on = edgesOf(edges);
|
|
780
|
+
const result = {};
|
|
781
|
+
if (on.top) result.topHidden = hidden;
|
|
782
|
+
if (on.bottom) result.bottomHidden = hidden;
|
|
783
|
+
return result;
|
|
842
784
|
}
|
|
843
|
-
function
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
return item.text;
|
|
785
|
+
function marginSettings(value) {
|
|
786
|
+
return { margins: padding(value) };
|
|
787
|
+
}
|
|
788
|
+
function mergeScrollSettings(outer, inner) {
|
|
789
|
+
const result = { ...outer };
|
|
790
|
+
for (const key of ["topStyle", "bottomStyle", "topHidden", "bottomHidden"]) {
|
|
791
|
+
if (key in inner) result[key] = inner[key];
|
|
853
792
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
857
|
-
return typeof File !== "undefined" ? new File([bytes], item.name ?? "file", { type: item.type }) : bytes;
|
|
793
|
+
if (inner.margins) result.margins = { ...outer.margins, ...inner.margins };
|
|
794
|
+
return result;
|
|
858
795
|
}
|
|
859
|
-
function
|
|
796
|
+
function withScrollSettings(settings, children) {
|
|
797
|
+
return createElement(ScrollSettingsExtender, { settings }, children);
|
|
798
|
+
}
|
|
799
|
+
function ScrollSettingsExtender({ settings, children }) {
|
|
800
|
+
const outer = useContext(ScrollSettingsContext);
|
|
801
|
+
return createElement(ScrollSettingsContext.Provider, { value: mergeScrollSettings(outer, settings) }, children);
|
|
802
|
+
}
|
|
803
|
+
function useScrollSettings(own) {
|
|
804
|
+
return mergeScrollSettings(useContext(ScrollSettingsContext), own);
|
|
805
|
+
}
|
|
806
|
+
function edgeEffectProp(settings) {
|
|
807
|
+
const edges = {};
|
|
808
|
+
const top = settings.topHidden ? "hidden" : settings.topStyle;
|
|
809
|
+
const bottom = settings.bottomHidden ? "hidden" : settings.bottomStyle;
|
|
810
|
+
if (top) edges.top = top;
|
|
811
|
+
if (bottom) edges.bottom = bottom;
|
|
812
|
+
return top || bottom ? edges : void 0;
|
|
813
|
+
}
|
|
814
|
+
function marginedContent(children, margins, axis) {
|
|
815
|
+
if (!margins || Object.values(margins).every((value) => !value)) return children;
|
|
816
|
+
const list = Children.toArray(children);
|
|
817
|
+
const content = list.length === 1 ? list[0] : sb(axis === "horizontal" ? "hstack" : "vstack", { spacing: null, alignment: "center" }, void 0, children);
|
|
818
|
+
return sb("styled", { style: { padding: margins } }, void 0, content);
|
|
819
|
+
}
|
|
820
|
+
const ListSelectionContext = createContext(null);
|
|
821
|
+
function Row({ tag, onDelete, deletable, onMove, movable, index, containerIndex, children }) {
|
|
822
|
+
const selection = useContext(ListSelectionContext);
|
|
823
|
+
const selectable = selection !== null && tag !== void 0;
|
|
824
|
+
const canDelete = onDelete !== void 0 && deletable !== false;
|
|
825
|
+
const canMove = onMove !== void 0 && movable !== false;
|
|
826
|
+
if (!selectable && !canDelete && !canMove) return children;
|
|
827
|
+
const props = {};
|
|
828
|
+
if (selectable) {
|
|
829
|
+
props["selectable"] = true;
|
|
830
|
+
props["selected"] = selection.isSelected(tag);
|
|
831
|
+
}
|
|
832
|
+
if (canDelete) props["deletable"] = true;
|
|
833
|
+
if (canMove) props["movable"] = true;
|
|
860
834
|
return sb(
|
|
861
|
-
"
|
|
862
|
-
|
|
835
|
+
"listrow",
|
|
836
|
+
props,
|
|
863
837
|
{
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
isTargeted?.(false);
|
|
870
|
-
if (event.phase !== "performed") return;
|
|
871
|
-
let items;
|
|
872
|
-
if (event.source !== void 0) items = active && active.id === event.source ? [active.payload] : [];
|
|
873
|
-
else items = (event.items ?? []).map(itemValue);
|
|
874
|
-
if (items.length > 0) action(items, { x: event.x, y: event.y });
|
|
838
|
+
tap: () => selectable && selection.select(tag),
|
|
839
|
+
delete: () => onDelete?.(),
|
|
840
|
+
move: (event) => {
|
|
841
|
+
const start = (containerIndex ?? index ?? 0) - (index ?? 0);
|
|
842
|
+
onMove?.(Math.max(0, event.to - start));
|
|
875
843
|
}
|
|
876
844
|
},
|
|
877
845
|
children
|
|
878
846
|
);
|
|
879
847
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
848
|
+
const ScrollRequestContext = createContext(null);
|
|
849
|
+
let nextSerial = 1;
|
|
850
|
+
function ScrollViewReader({ children }) {
|
|
851
|
+
const [request, setRequest] = useState(null);
|
|
852
|
+
const proxy = {
|
|
853
|
+
scrollTo: (id, anchor) => setRequest({ id, anchor: anchor === void 0 ? null : unitPoint(anchor), serial: nextSerial++ })
|
|
886
854
|
};
|
|
887
|
-
|
|
888
|
-
return sb(
|
|
889
|
-
HOIST_KIND,
|
|
890
|
-
void 0,
|
|
891
|
-
void 0,
|
|
892
|
-
sb(
|
|
893
|
-
"sheet",
|
|
894
|
-
{ detents },
|
|
895
|
-
{ tap: dismiss },
|
|
896
|
-
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) })
|
|
897
|
-
),
|
|
898
|
-
"root"
|
|
899
|
-
);
|
|
900
|
-
}
|
|
901
|
-
function presentationDetents(detents) {
|
|
902
|
-
const encoded = detents.map(
|
|
903
|
-
(detent) => typeof detent === "string" ? detent : "height" in detent ? `height:${detent.height}` : `fraction:${detent.fraction}`
|
|
904
|
-
);
|
|
905
|
-
return sb(PREF_KIND, { detents: encoded }, void 0, void 0, "sheet");
|
|
855
|
+
return /* @__PURE__ */ jsx(ScrollRequestContext.Provider, { value: request, children: children(proxy) });
|
|
906
856
|
}
|
|
907
|
-
function
|
|
908
|
-
const
|
|
909
|
-
if (
|
|
910
|
-
|
|
911
|
-
return sb(
|
|
912
|
-
HOIST_KIND,
|
|
913
|
-
void 0,
|
|
914
|
-
void 0,
|
|
915
|
-
sb(
|
|
916
|
-
"alert",
|
|
917
|
-
{ title, message: message ?? null, style: style ?? "alert" },
|
|
918
|
-
{ tap: dismiss },
|
|
919
|
-
withEnvironment({ dismissAlert: dismiss }, actions)
|
|
920
|
-
),
|
|
921
|
-
"root"
|
|
922
|
-
);
|
|
857
|
+
function ScrollTarget({ id, children }) {
|
|
858
|
+
const request = useContext(ScrollRequestContext);
|
|
859
|
+
if (request && request.id === id) return styled({ scrollID: true, scrollTo: { anchor: request.anchor, serial: request.serial } }, children);
|
|
860
|
+
return styled({ scrollID: true }, children);
|
|
923
861
|
}
|
|
924
|
-
|
|
862
|
+
const LAZY_BATCH = 12;
|
|
863
|
+
const LazyContext = createContext(null);
|
|
864
|
+
function LazyGroup({ rows, start = 0, wrap: wrap2 }) {
|
|
865
|
+
const axis = useContext(LazyContext);
|
|
866
|
+
const request = useContext(ScrollRequestContext);
|
|
867
|
+
const [count, setCount] = useState(LAZY_BATCH);
|
|
868
|
+
const target = request ? rows.findIndex((row) => rowMatches(row, request.id)) : -1;
|
|
869
|
+
const needed = target >= 0 ? Math.ceil((target + 1) / LAZY_BATCH) * LAZY_BATCH : 0;
|
|
925
870
|
useEffect(() => {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
const panelContent = columnWidth !== void 0 ? sb("styled", { style: { inspectorColumnWidth: columnWidth } }, void 0, content) : content;
|
|
941
|
-
return sb("inspector", { presented }, void 0, [
|
|
942
|
-
/* @__PURE__ */ jsx(InspectorPart, { children }, "content"),
|
|
943
|
-
/* @__PURE__ */ jsx(InspectorPart, { children: sb("inspectorpanel", {}, void 0, panelContent) }, "panel")
|
|
944
|
-
]);
|
|
871
|
+
if (needed > count) setCount(needed);
|
|
872
|
+
}, [needed, count]);
|
|
873
|
+
const visible = Math.max(count, needed);
|
|
874
|
+
const shown = axis === null ? rows : rows.slice(0, visible);
|
|
875
|
+
const built = shown.map((row, index) => wrap2 ? wrap2(row, start + index) : row);
|
|
876
|
+
if (axis === null || shown.length >= rows.length) return built;
|
|
877
|
+
return [
|
|
878
|
+
...built,
|
|
879
|
+
createElement(
|
|
880
|
+
LazySpacer,
|
|
881
|
+
{ key: `lazy-${visible}`, axis, remaining: rows.length - shown.length, more: () => setCount(visible + LAZY_BATCH) }
|
|
882
|
+
)
|
|
883
|
+
];
|
|
945
884
|
}
|
|
946
|
-
function
|
|
947
|
-
return
|
|
885
|
+
function LazySpacer({ axis, remaining, more }) {
|
|
886
|
+
return sb("lazyspacer", { axis, remaining }, { lazy: more });
|
|
948
887
|
}
|
|
949
|
-
function
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
const
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}, [id]);
|
|
959
|
-
return null;
|
|
888
|
+
function rowMatches(row, id) {
|
|
889
|
+
if (row.key !== null && row.key === String(id)) return true;
|
|
890
|
+
let element = row;
|
|
891
|
+
for (let depth = 0; element && depth < 3; depth++) {
|
|
892
|
+
const props = element.props;
|
|
893
|
+
if (props.scrollID === id) return true;
|
|
894
|
+
element = isValidElement(props.children) ? props.children : null;
|
|
895
|
+
}
|
|
896
|
+
return false;
|
|
960
897
|
}
|
|
961
|
-
function
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
const previous = useRef(null);
|
|
967
|
-
const latest = useRef(action);
|
|
968
|
-
latest.current = action;
|
|
969
|
-
useEffect(() => {
|
|
970
|
-
const last = previous.current;
|
|
971
|
-
previous.current = { value };
|
|
972
|
-
if (last === null) {
|
|
973
|
-
if (initial) latest.current(value, value);
|
|
974
|
-
return;
|
|
975
|
-
}
|
|
976
|
-
if (!Object.is(last.value, value)) latest.current(last.value, value);
|
|
977
|
-
}, [value, initial]);
|
|
978
|
-
return null;
|
|
898
|
+
function VStack(props) {
|
|
899
|
+
const { own, modifiers } = splitProps(props);
|
|
900
|
+
const stack = { spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
901
|
+
if (own.scrollTargetLayout) stack["scrollTarget"] = true;
|
|
902
|
+
return applyModifiers(sb("vstack", stack, void 0, own.children), modifiers);
|
|
979
903
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
904
|
+
function HStack(props) {
|
|
905
|
+
const { own, modifiers } = splitProps(props);
|
|
906
|
+
const stack = { spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
907
|
+
if (own.scrollTargetLayout) stack["scrollTarget"] = true;
|
|
908
|
+
return applyModifiers(sb("hstack", stack, void 0, own.children), modifiers);
|
|
983
909
|
}
|
|
984
|
-
function
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
return /* @__PURE__ */ jsx(CoordinateSpacesContext.Provider, { value: { ...spaces, [name]: frame2 }, children: sb(
|
|
988
|
-
"zstack",
|
|
989
|
-
{ alignment: "center", reportsSize: true, reportsFrame: true },
|
|
990
|
-
{
|
|
991
|
-
geometry: (event) => {
|
|
992
|
-
const next = { x: event.x ?? 0, y: event.y ?? 0, width: event.width, height: event.height };
|
|
993
|
-
if (!frame2 || frame2.x !== next.x || frame2.y !== next.y || frame2.width !== next.width || frame2.height !== next.height) setFrame(next);
|
|
994
|
-
}
|
|
995
|
-
},
|
|
996
|
-
children
|
|
997
|
-
) });
|
|
910
|
+
function ZStack(props) {
|
|
911
|
+
const { own, modifiers } = splitProps(props);
|
|
912
|
+
return applyModifiers(sb("zstack", { alignment: own.alignment ?? "center" }, void 0, own.children), modifiers);
|
|
998
913
|
}
|
|
999
|
-
function
|
|
1000
|
-
|
|
914
|
+
function Spacer(props) {
|
|
915
|
+
const { own, modifiers } = splitProps(props);
|
|
916
|
+
return applyModifiers(sb("spacer", { minLength: own.minLength ?? null }), modifiers);
|
|
1001
917
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
default: "default",
|
|
1006
|
-
text: "text",
|
|
1007
|
-
verticalText: "vertical-text",
|
|
1008
|
-
grabIdle: "grab",
|
|
1009
|
-
grabActive: "grabbing",
|
|
1010
|
-
rectSelection: "crosshair",
|
|
1011
|
-
columnResize: "col-resize",
|
|
1012
|
-
rowResize: "row-resize"
|
|
1013
|
-
};
|
|
1014
|
-
function cursorFor(style) {
|
|
1015
|
-
return CURSORS[style] ?? style;
|
|
918
|
+
function Divider(props) {
|
|
919
|
+
const { modifiers } = splitProps(props);
|
|
920
|
+
return applyModifiers(sb("divider", {}), modifiers);
|
|
1016
921
|
}
|
|
1017
|
-
function
|
|
1018
|
-
const
|
|
1019
|
-
const
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
922
|
+
function ScrollView(props) {
|
|
923
|
+
const { own, modifiers } = splitProps(props);
|
|
924
|
+
const refresh = useRefreshable(takeModifier(modifiers, "refreshable"));
|
|
925
|
+
const ownSettings = takeScrollSettings(modifiers);
|
|
926
|
+
const settings = useScrollSettings(ownSettings);
|
|
927
|
+
const axes = own.axes ?? "vertical";
|
|
928
|
+
const scroll = { axes, ...refresh.props };
|
|
929
|
+
if (own.scrollTargetBehavior) scroll["snap"] = own.scrollTargetBehavior;
|
|
930
|
+
if (own.scrollDismissesKeyboard) scroll["dismissesKeyboard"] = true;
|
|
931
|
+
const edgeEffect = edgeEffectProp(settings);
|
|
932
|
+
if (edgeEffect) scroll["edgeEffect"] = edgeEffect;
|
|
933
|
+
const content = marginedContent(own.children, settings.margins, axes === "horizontal" ? "horizontal" : "vertical");
|
|
934
|
+
return applyModifiers(sb("scrollview", scroll, refresh.handlers, providingScrollSettings(ownSettings, content)), modifiers);
|
|
935
|
+
}
|
|
936
|
+
function takeScrollSettings(modifiers) {
|
|
937
|
+
let settings = {};
|
|
938
|
+
const own = [];
|
|
939
|
+
for (const key of ["scrollEdgeEffectStyle", "scrollEdgeEffectHidden", "contentMargins"]) {
|
|
940
|
+
const value = takeModifier(modifiers, key);
|
|
941
|
+
if (value === void 0) continue;
|
|
942
|
+
if (key === "scrollEdgeEffectStyle") own.push(edgeStyleSettings(value));
|
|
943
|
+
else if (key === "scrollEdgeEffectHidden") own.push(edgeHiddenSettings(value));
|
|
944
|
+
else own.push(marginSettings(value));
|
|
1023
945
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
if (spec.direction) effect.direction = spec.direction;
|
|
1027
|
-
if (spec.speed !== void 0) effect.speed = spec.speed;
|
|
1028
|
-
if (spec.repeat !== void 0) effect.repeat = spec.repeat;
|
|
1029
|
-
if (discrete) effect.trigger = serial.current.count;
|
|
1030
|
-
return styled({ symbolEffect: effect }, children);
|
|
946
|
+
for (const each of own) settings = mergeScrollSettings(settings, each);
|
|
947
|
+
return settings;
|
|
1031
948
|
}
|
|
1032
|
-
function
|
|
1033
|
-
return
|
|
949
|
+
function providingScrollSettings(settings, children) {
|
|
950
|
+
return Object.keys(settings).length > 0 ? withScrollSettings(settings, children) : children;
|
|
1034
951
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
952
|
+
function useRefreshable(own) {
|
|
953
|
+
const environment = useViewEnvironment();
|
|
954
|
+
const refresh = own ?? environment.refresh;
|
|
955
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
956
|
+
if (!refresh) return { props: {} };
|
|
957
|
+
return {
|
|
958
|
+
props: { refreshable: true, refreshing },
|
|
959
|
+
handlers: {
|
|
960
|
+
refresh: () => {
|
|
961
|
+
if (refreshing) return;
|
|
962
|
+
setRefreshing(true);
|
|
963
|
+
Promise.resolve().then(refresh).catch((error) => console.error(error)).finally(() => setRefreshing(false));
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function Group(props) {
|
|
969
|
+
const { own, modifiers } = splitProps(props);
|
|
970
|
+
if (modifiers.length === 0) return own.children;
|
|
971
|
+
return Children.map(own.children, (child) => applyModifiers(child, modifiers));
|
|
972
|
+
}
|
|
973
|
+
function moveItems(items, offsets, to) {
|
|
974
|
+
const moving = new Set(offsets);
|
|
975
|
+
const picked = items.filter((_, index) => moving.has(index));
|
|
976
|
+
const rest = items.filter((_, index) => !moving.has(index));
|
|
977
|
+
const before = offsets.filter((offset) => offset < to).length;
|
|
978
|
+
const at = to - before;
|
|
979
|
+
return [...rest.slice(0, at), ...picked, ...rest.slice(at)];
|
|
980
|
+
}
|
|
981
|
+
function ForEach(props) {
|
|
982
|
+
const { own, modifiers } = splitProps(props);
|
|
983
|
+
const rows = own.data.map((element, index) => {
|
|
984
|
+
const key = own.id ? own.id(element, index) : keyOf(element, index);
|
|
985
|
+
const content = applyModifiers(own.children(element, index), modifiers);
|
|
986
|
+
if (!own.onDelete && !own.onMove) return createElement(Fragment, { key }, content);
|
|
987
|
+
const { onDelete, onMove } = own;
|
|
988
|
+
const row = { tag: key, index };
|
|
989
|
+
if (onDelete) {
|
|
990
|
+
row.onDelete = () => onDelete([index]);
|
|
991
|
+
row.deletable = !own.deleteDisabled?.(element, index);
|
|
992
|
+
}
|
|
993
|
+
if (onMove) {
|
|
994
|
+
row.onMove = (to) => onMove([index], to);
|
|
995
|
+
row.movable = !own.moveDisabled?.(element, index);
|
|
996
|
+
}
|
|
997
|
+
return createElement(Row, { key, ...row }, content);
|
|
998
|
+
});
|
|
999
|
+
return rows.length > LAZY_BATCH ? createElement(LazyGroup, { rows }) : rows;
|
|
1000
|
+
}
|
|
1001
|
+
function keyOf(element, index) {
|
|
1002
|
+
if (typeof element === "string" || typeof element === "number") return element;
|
|
1003
|
+
if (typeof element === "object" && element !== null && "id" in element) {
|
|
1004
|
+
const id = element.id;
|
|
1005
|
+
if (typeof id === "string" || typeof id === "number") return id;
|
|
1006
|
+
}
|
|
1007
|
+
return index;
|
|
1008
|
+
}
|
|
1009
|
+
function flattenChildren(children, options = {}) {
|
|
1010
|
+
const result = [];
|
|
1011
|
+
const visit = (node) => {
|
|
1012
|
+
if (node === null || node === void 0 || typeof node === "boolean") return;
|
|
1013
|
+
if (Array.isArray(node)) {
|
|
1014
|
+
node.forEach(visit);
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
if (!isValidElement(node)) return;
|
|
1018
|
+
const element = node;
|
|
1019
|
+
if (element.type === Fragment) {
|
|
1020
|
+
const inner = element.props["children"];
|
|
1021
|
+
if (element.key !== null && isValidElement(inner) && inner.key === null && inner.type !== Fragment) {
|
|
1022
|
+
visit({ ...inner, key: element.key });
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
visit(inner);
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
if (element.type === ForEach) {
|
|
1029
|
+
visit(ForEach(element.props));
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
if (element.type === LazyGroup && !options.keepLazy) {
|
|
1033
|
+
visit(element.props.rows);
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
result.push(element);
|
|
1037
|
+
};
|
|
1038
|
+
visit(children);
|
|
1039
|
+
return result;
|
|
1040
|
+
}
|
|
1041
|
+
function GridItem(spec = {}) {
|
|
1042
|
+
const dimension = (n) => n === void 0 || n === Infinity ? "infinity" : n;
|
|
1043
|
+
let size;
|
|
1044
|
+
if (spec.size && "fixed" in spec.size) size = { kind: "fixed", value: spec.size.fixed };
|
|
1045
|
+
else if (spec.size && "adaptive" in spec.size) {
|
|
1046
|
+
size = { kind: "adaptive", minimum: spec.size.adaptive.minimum, maximum: dimension(spec.size.adaptive.maximum) };
|
|
1047
|
+
} else {
|
|
1048
|
+
const flexible = spec.size && "flexible" in spec.size ? spec.size.flexible : {};
|
|
1049
|
+
size = { kind: "flexible", minimum: flexible.minimum ?? 10, maximum: dimension(flexible.maximum) };
|
|
1050
|
+
}
|
|
1051
|
+
return { size, spacing: spec.spacing ?? null, alignment: spec.alignment ?? null };
|
|
1052
|
+
}
|
|
1053
|
+
GridItem.flexible = (options = {}) => GridItem({ size: { flexible: options }, spacing: options.spacing, alignment: options.alignment });
|
|
1054
|
+
GridItem.fixed = (value, options = {}) => GridItem({ size: { fixed: value }, spacing: options.spacing, alignment: options.alignment });
|
|
1055
|
+
GridItem.adaptive = (options) => GridItem({ size: { adaptive: options }, spacing: options.spacing, alignment: options.alignment });
|
|
1056
|
+
function LazyVGrid(props) {
|
|
1057
|
+
const { own, modifiers } = splitProps(props);
|
|
1058
|
+
return applyModifiers(
|
|
1059
|
+
sb("lazyvgrid", { columns: own.columns, spacing: own.spacing ?? null, alignment: own.alignment ?? "center" }, void 0, own.children),
|
|
1060
|
+
modifiers
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
function LazyHGrid(props) {
|
|
1064
|
+
const { own, modifiers } = splitProps(props);
|
|
1065
|
+
return applyModifiers(
|
|
1066
|
+
sb("lazyhgrid", { rows: own.rows, spacing: own.spacing ?? null, alignment: own.alignment ?? "center" }, void 0, own.children),
|
|
1067
|
+
modifiers
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
function Grid(props) {
|
|
1071
|
+
const { own, modifiers } = splitProps(props);
|
|
1072
|
+
return applyModifiers(
|
|
1073
|
+
sb(
|
|
1074
|
+
"grid",
|
|
1075
|
+
{ horizontalSpacing: own.horizontalSpacing ?? null, verticalSpacing: own.verticalSpacing ?? null, alignment: own.alignment ?? "center" },
|
|
1076
|
+
void 0,
|
|
1077
|
+
own.children
|
|
1078
|
+
),
|
|
1079
|
+
modifiers
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
function GridRow(props) {
|
|
1083
|
+
const { own, modifiers } = splitProps(props);
|
|
1084
|
+
return applyModifiers(sb("gridrow", { alignment: own.alignment ?? null }, void 0, own.children), modifiers);
|
|
1085
|
+
}
|
|
1086
|
+
function runStyleOf(props, inherited, nested) {
|
|
1087
|
+
const style = { ...inherited };
|
|
1088
|
+
if (props.italic) style.italic = true;
|
|
1089
|
+
if (props.underline) style.underline = typeof props.underline === "object" && props.underline.color ? { color: color(props.underline.color) } : {};
|
|
1090
|
+
if (props.strikethrough) {
|
|
1091
|
+
style.strikethrough = typeof props.strikethrough === "object" && props.strikethrough.color ? { color: color(props.strikethrough.color) } : {};
|
|
1092
|
+
}
|
|
1093
|
+
const kerning = props.tracking ?? props.kerning;
|
|
1094
|
+
if (kerning !== void 0) style.kerning = kerning;
|
|
1095
|
+
if (props.baselineOffset !== void 0) style.baselineOffset = props.baselineOffset;
|
|
1096
|
+
if (props.link) style.link = props.link;
|
|
1097
|
+
if (nested) {
|
|
1098
|
+
let runFont = props.font !== void 0 ? font(props.font) : void 0;
|
|
1099
|
+
if (props.bold) runFont = { ...runFont ?? {}, weight: "bold" };
|
|
1100
|
+
if (props.fontWeight) runFont = { ...runFont ?? {}, weight: props.fontWeight };
|
|
1101
|
+
if (runFont) style.font = { ...style.font ?? {}, ...runFont };
|
|
1102
|
+
if (props.foregroundStyle !== void 0) style.foreground = shapeStyle(props.foregroundStyle);
|
|
1103
|
+
}
|
|
1104
|
+
return style;
|
|
1105
|
+
}
|
|
1106
|
+
function segmentsOf(children, style, into) {
|
|
1107
|
+
const visit = (node) => {
|
|
1108
|
+
if (node === null || node === void 0 || typeof node === "boolean") return;
|
|
1109
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
1110
|
+
const last = into[into.length - 1];
|
|
1111
|
+
if (last && "text" in last && last.style === style) last.text += String(node);
|
|
1112
|
+
else into.push({ text: String(node), style });
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
if (Array.isArray(node)) {
|
|
1116
|
+
node.forEach(visit);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
if (!isValidElement(node)) return;
|
|
1120
|
+
const element = node;
|
|
1121
|
+
if (element.type === Fragment) {
|
|
1122
|
+
visit(element.props["children"]);
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
if (element.type === Text) {
|
|
1126
|
+
const props = element.props;
|
|
1127
|
+
segmentsOf(props.children, runStyleOf(props, style, true), into);
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
if (element.type === Image$1) {
|
|
1131
|
+
const props = element.props;
|
|
1132
|
+
into.push({ image: imageProps(props), style });
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
visit(children);
|
|
1137
|
+
}
|
|
1138
|
+
function isPlainStyle(style) {
|
|
1139
|
+
return Object.keys(style).length === 0;
|
|
1140
|
+
}
|
|
1141
|
+
function Text(props) {
|
|
1142
|
+
const { own, modifiers } = splitProps(props);
|
|
1143
|
+
const environment = useViewEnvironment();
|
|
1144
|
+
const style = runStyleOf(props, {}, false);
|
|
1145
|
+
const segments = [];
|
|
1146
|
+
segmentsOf(own.children, style, segments);
|
|
1147
|
+
const textCase = takeModifier(modifiers, "textCase") ?? environment.textCase;
|
|
1148
|
+
if (textCase) {
|
|
1149
|
+
for (const segment of segments) {
|
|
1150
|
+
if ("text" in segment) segment.text = textCase === "uppercase" ? segment.text.toUpperCase() : segment.text.toLowerCase();
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
const redacted = takeModifier(modifiers, "redacted") ?? environment.redacted;
|
|
1154
|
+
const content = segments.map((segment) => "text" in segment ? segment.text : "").join("");
|
|
1155
|
+
const plain = segments.length <= 1 && (segments.length === 0 || "text" in segments[0] && isPlainStyle(segments[0].style));
|
|
1156
|
+
if (plain) return applyModifiers(placeholder(sb("text", { text: content }), redacted), modifiers);
|
|
1157
|
+
const runs = segments.map((segment) => {
|
|
1158
|
+
const run = { ...segment.style };
|
|
1159
|
+
if ("text" in segment) run["text"] = segment.text;
|
|
1160
|
+
else run["image"] = segment.image;
|
|
1161
|
+
return run;
|
|
1162
|
+
});
|
|
1163
|
+
const hasLinks = segments.some((segment) => segment.style.link);
|
|
1164
|
+
const handlers = hasLinks ? { link: (event) => openURL(event.value) } : void 0;
|
|
1165
|
+
return applyModifiers(placeholder(sb("text", { text: content, runs }, handlers), redacted), modifiers);
|
|
1166
|
+
}
|
|
1167
|
+
function placeholder(node, redacted) {
|
|
1168
|
+
if (!redacted) return node;
|
|
1169
|
+
return styled({ background: { hierarchical: 3 }, backgroundCornerRadius: 4 }, styled({ foreground: { name: "clear" } }, node));
|
|
1170
|
+
}
|
|
1171
|
+
function openURL(url) {
|
|
1172
|
+
if (typeof window !== "undefined") window.open(url, "_blank", "noopener");
|
|
1173
|
+
}
|
|
1174
|
+
function imageProps(props) {
|
|
1175
|
+
if (props.systemName !== void 0) return { systemName: props.systemName };
|
|
1176
|
+
if (props.url !== void 0) return { url: props.url, resizable: props.resizable ?? false, width: props.width ?? 0, height: props.height ?? 0 };
|
|
1177
|
+
return { name: props.name ?? "", resizable: props.resizable ?? false };
|
|
1178
|
+
}
|
|
1179
|
+
function Image$1(props) {
|
|
1180
|
+
const { modifiers } = splitProps(props);
|
|
1181
|
+
const environment = useViewEnvironment();
|
|
1182
|
+
const redacted = takeModifier(modifiers, "redacted") ?? environment.redacted;
|
|
1183
|
+
return applyModifiers(placeholder(sb("image", imageProps(props)), redacted), modifiers);
|
|
1184
|
+
}
|
|
1185
|
+
function Label(props) {
|
|
1186
|
+
const { own, modifiers } = splitProps(props);
|
|
1187
|
+
const environment = useViewEnvironment();
|
|
1188
|
+
const style = takeModifier(modifiers, "labelStyle") ?? environment.labelStyle ?? "automatic";
|
|
1189
|
+
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);
|
|
1190
|
+
const title = typeof own.title === "string" || typeof own.title === "number" ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.title;
|
|
1191
|
+
if (style === "iconOnly") return applyModifiers(icon, modifiers);
|
|
1192
|
+
if (style === "titleOnly") return applyModifiers(title, modifiers);
|
|
1193
|
+
return applyModifiers(
|
|
1194
|
+
/* @__PURE__ */ jsxs(HStack, { spacing: 8, children: [
|
|
1195
|
+
styled({ labelIcon: true }, icon),
|
|
1196
|
+
title
|
|
1197
|
+
] }),
|
|
1198
|
+
modifiers
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
function LabeledContent(props) {
|
|
1202
|
+
const { own, modifiers } = splitProps(props);
|
|
1203
|
+
const label = typeof own.label === "string" || typeof own.label === "number" ? /* @__PURE__ */ jsx(Text, { children: own.label }) : own.label;
|
|
1204
|
+
const content = own.children ?? own.value;
|
|
1205
|
+
const value = typeof content === "string" || typeof content === "number" ? /* @__PURE__ */ jsx(Text, { children: content }) : content;
|
|
1206
|
+
return applyModifiers(
|
|
1207
|
+
/* @__PURE__ */ jsxs(HStack, { children: [
|
|
1208
|
+
label,
|
|
1209
|
+
sb("spacer", { minLength: null }),
|
|
1210
|
+
styled({ foreground: { hierarchical: 2 } }, value)
|
|
1211
|
+
] }),
|
|
1212
|
+
modifiers
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
function Link(props) {
|
|
1216
|
+
const { own, modifiers } = splitProps(props);
|
|
1217
|
+
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.children;
|
|
1218
|
+
return applyModifiers(sb("button", { role: null, style: "automatic" }, { tap: () => openURL(own.destination) }, label), modifiers);
|
|
1219
|
+
}
|
|
1220
|
+
const isPushedView = (value) => typeof value === "object" && value !== null && "view" in value && Object.keys(value).length === 1;
|
|
1221
|
+
function NavigationStack(props) {
|
|
1222
|
+
const enclosing = useNavigation();
|
|
1223
|
+
if (enclosing) return /* @__PURE__ */ jsx(FlattenedStack, { ...props });
|
|
1224
|
+
return /* @__PURE__ */ jsx(OwnStack, { ...props });
|
|
1225
|
+
}
|
|
1226
|
+
function FlattenedStack(props) {
|
|
1227
|
+
const { own, modifiers } = splitProps(props);
|
|
1228
|
+
return applyModifiers(
|
|
1229
|
+
/* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1230
|
+
own.destination && /* @__PURE__ */ jsx(RegisterDestination, { destination: own.destination }),
|
|
1231
|
+
own.children
|
|
1232
|
+
] }),
|
|
1233
|
+
modifiers
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
function OwnStack(props) {
|
|
1237
|
+
const { own, modifiers } = splitProps(props);
|
|
1238
|
+
const [internalPath, setInternalPath] = useState([]);
|
|
1239
|
+
const [path, setPath] = own.path !== void 0 ? readBinding(own.path, own.onPathChange) : [internalPath, setInternalPath];
|
|
1240
|
+
const destination = useRef(null);
|
|
1241
|
+
destination.current = own.destination ?? null;
|
|
1242
|
+
const context = {
|
|
1243
|
+
push: (value) => setPath([...path, value]),
|
|
1244
|
+
pop: () => setPath(path.slice(0, -1)),
|
|
1245
|
+
registerDestination: (builder) => {
|
|
1246
|
+
destination.current = builder;
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
const screens = [
|
|
1250
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb("navscreen", { title: "", displayMode: "automatic", depth: 0 }, { tap: context.pop }, own.children) }, "root")
|
|
1251
|
+
];
|
|
1252
|
+
path.forEach((value, index) => {
|
|
1253
|
+
const pop = () => setPath(path.slice(0, index));
|
|
1254
|
+
screens.push(
|
|
1255
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb(
|
|
1256
|
+
"navscreen",
|
|
1257
|
+
{ title: "", displayMode: "automatic", depth: index + 1 },
|
|
1258
|
+
{ tap: pop },
|
|
1259
|
+
/* @__PURE__ */ jsx(DismissContext.Provider, { value: pop, children: /* @__PURE__ */ jsx(PathScreen, { value, destination }) })
|
|
1260
|
+
) }, index + 1)
|
|
1261
|
+
);
|
|
1262
|
+
});
|
|
1263
|
+
return applyModifiers(
|
|
1264
|
+
sb("navstack", {}, void 0, /* @__PURE__ */ jsx(NavigationContext.Provider, { value: context, children: screens })),
|
|
1265
|
+
modifiers
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
function PathScreen({ value, destination }) {
|
|
1269
|
+
if (isPushedView(value)) return value.view;
|
|
1270
|
+
return destination.current ? destination.current(value) : null;
|
|
1271
|
+
}
|
|
1272
|
+
function NavigationLink(props) {
|
|
1273
|
+
const { own, modifiers } = splitProps(props);
|
|
1274
|
+
const navigation = useNavigation();
|
|
1275
|
+
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.children;
|
|
1276
|
+
const tap = () => {
|
|
1277
|
+
if (!navigation) return;
|
|
1278
|
+
if (own.destination !== void 0) navigation.push({ view: own.destination });
|
|
1279
|
+
else navigation.push(own.value);
|
|
1280
|
+
};
|
|
1281
|
+
return applyModifiers(sb("navlink", {}, { tap }, label), modifiers);
|
|
1282
|
+
}
|
|
1283
|
+
const SplitSelectionContext = createContext(null);
|
|
1284
|
+
function NavigationSplitView(props) {
|
|
1285
|
+
const { own, modifiers } = splitProps(props);
|
|
1286
|
+
const sizeClass = useHorizontalSizeClass();
|
|
1287
|
+
const [selected, setSelected] = useState(false);
|
|
1288
|
+
const reporters = useRef(/* @__PURE__ */ new Map());
|
|
1289
|
+
const [report] = useState(() => {
|
|
1290
|
+
const settle = () => setSelected([...reporters.current.values()].some((entry) => entry.selected));
|
|
1291
|
+
return {
|
|
1292
|
+
report: (key, nowSelected, clear2) => {
|
|
1293
|
+
reporters.current.set(key, { selected: nowSelected, clear: clear2 });
|
|
1294
|
+
settle();
|
|
1295
|
+
},
|
|
1296
|
+
retract: (key) => {
|
|
1297
|
+
if (reporters.current.delete(key)) settle();
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
});
|
|
1301
|
+
const clear = () => {
|
|
1302
|
+
for (const entry of reporters.current.values()) if (entry.selected) entry.clear();
|
|
1303
|
+
};
|
|
1304
|
+
const [internal, setInternal] = useState("automatic");
|
|
1305
|
+
const [visibility, setVisibility] = own.columnVisibility !== void 0 ? readBinding(own.columnVisibility, own.onColumnVisibilityChange) : [internal, setInternal];
|
|
1306
|
+
if (sizeClass === "compact") {
|
|
1307
|
+
return applyModifiers(
|
|
1308
|
+
/* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children: /* @__PURE__ */ jsx(CompactSplit, { sidebar: own.sidebar, detail: own.detail, selected, clear }) }),
|
|
1309
|
+
modifiers
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
const sidebarVisible = visibility !== "detailOnly";
|
|
1313
|
+
const toggle = () => withAnimation(() => setVisibility(sidebarVisible ? "detailOnly" : "all"));
|
|
1314
|
+
const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
|
|
1315
|
+
return applyModifiers(
|
|
1316
|
+
sb("navsplit", { sidebarVisible }, { tap: toggle }, [
|
|
1317
|
+
/* @__PURE__ */ jsx(SplitColumn, { report, children: /* @__PURE__ */ jsx(NavigationStack, { children: own.sidebar }) }, "sidebar"),
|
|
1318
|
+
/* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
|
|
1319
|
+
]),
|
|
1320
|
+
modifiers
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
function SplitColumn({ report, children }) {
|
|
1324
|
+
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children }) });
|
|
1325
|
+
}
|
|
1326
|
+
function CompactSplit({ sidebar, detail, selected, clear }) {
|
|
1327
|
+
const [extra, setExtra] = useState([]);
|
|
1328
|
+
const base = selected ? [{ view: /* @__PURE__ */ jsx(DetailScope, { children: detail }) }] : [];
|
|
1329
|
+
const path = [...base, ...extra];
|
|
1330
|
+
const setPath = (next) => {
|
|
1331
|
+
if (selected && next.length === 0) {
|
|
1332
|
+
setExtra([]);
|
|
1333
|
+
clear();
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
setExtra(next.slice(base.length));
|
|
1337
|
+
};
|
|
1338
|
+
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(NavigationStack, { path: [path, setPath], children: sidebar }) });
|
|
1339
|
+
}
|
|
1340
|
+
function DetailScope({ children }) {
|
|
1341
|
+
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
1342
|
+
}
|
|
1343
|
+
function useReportSplitSelection(split, selected, clear, active2 = true) {
|
|
1344
|
+
const key = useRef({}).current;
|
|
1345
|
+
useLayoutEffect(() => {
|
|
1346
|
+
if (active2) split?.report(key, selected, clear);
|
|
1347
|
+
else split?.retract(key);
|
|
1348
|
+
});
|
|
1349
|
+
useLayoutEffect(() => () => split?.retract(key), [split, key]);
|
|
1350
|
+
}
|
|
1351
|
+
function OutsideSplit({ children }) {
|
|
1352
|
+
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
1353
|
+
}
|
|
1354
|
+
function SheetPresenter({ isPresented, onDismiss, content, fullScreen }) {
|
|
1355
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
1356
|
+
if (!presented) return null;
|
|
1357
|
+
const dismiss = () => {
|
|
1358
|
+
setPresented(false);
|
|
1359
|
+
onDismiss?.();
|
|
1360
|
+
};
|
|
1361
|
+
const detents = fullScreen ? ["full"] : ["large"];
|
|
1362
|
+
return sb(
|
|
1363
|
+
HOIST_KIND,
|
|
1364
|
+
void 0,
|
|
1365
|
+
void 0,
|
|
1366
|
+
sb(
|
|
1367
|
+
"sheet",
|
|
1368
|
+
{ detents },
|
|
1369
|
+
{ tap: dismiss },
|
|
1370
|
+
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(OutsideSplit, { children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) }) })
|
|
1371
|
+
),
|
|
1372
|
+
"root"
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
function presentationDetents(detents) {
|
|
1376
|
+
const encoded = detents.map(
|
|
1377
|
+
(detent) => typeof detent === "string" ? detent : "height" in detent ? `height:${detent.height}` : `fraction:${detent.fraction}`
|
|
1378
|
+
);
|
|
1379
|
+
return sb(PREF_KIND, { detents: encoded }, void 0, void 0, "sheet");
|
|
1380
|
+
}
|
|
1381
|
+
function AlertPresenter({ title, isPresented, message, actions, style }) {
|
|
1382
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
1383
|
+
if (!presented) return null;
|
|
1384
|
+
const dismiss = () => setPresented(false);
|
|
1385
|
+
return sb(
|
|
1386
|
+
HOIST_KIND,
|
|
1387
|
+
void 0,
|
|
1388
|
+
void 0,
|
|
1389
|
+
sb(
|
|
1390
|
+
"alert",
|
|
1391
|
+
{ title, message: message ?? null, style: style ?? "alert" },
|
|
1392
|
+
{ tap: dismiss },
|
|
1393
|
+
withEnvironment({ dismissAlert: dismiss }, actions)
|
|
1394
|
+
),
|
|
1395
|
+
"root"
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
function Lifecycle({ onAppear, onDisappear }) {
|
|
1399
|
+
useEffect(() => {
|
|
1400
|
+
onAppear?.();
|
|
1401
|
+
return () => onDisappear?.();
|
|
1402
|
+
}, []);
|
|
1403
|
+
return null;
|
|
1404
|
+
}
|
|
1405
|
+
function Inspector({ isPresented, content, columnWidth, children }) {
|
|
1406
|
+
const sizeClass = useHorizontalSizeClass();
|
|
1407
|
+
const [presented, setPresented] = readBinding(isPresented);
|
|
1408
|
+
if (sizeClass === "compact") {
|
|
1409
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1410
|
+
children,
|
|
1411
|
+
/* @__PURE__ */ jsx(SheetPresenter, { isPresented: [presented, setPresented], content })
|
|
1412
|
+
] });
|
|
1413
|
+
}
|
|
1414
|
+
const outside = /* @__PURE__ */ jsx(OutsideSplit, { children: content });
|
|
1415
|
+
const panelContent = columnWidth !== void 0 ? sb("styled", { style: { inspectorColumnWidth: columnWidth } }, void 0, outside) : outside;
|
|
1416
|
+
return sb("inspector", { presented }, void 0, [
|
|
1417
|
+
/* @__PURE__ */ jsx(InspectorPart, { children }, "content"),
|
|
1418
|
+
/* @__PURE__ */ jsx(InspectorPart, { children: sb("inspectorpanel", {}, void 0, panelContent) }, "panel")
|
|
1419
|
+
]);
|
|
1420
|
+
}
|
|
1421
|
+
function InspectorPart({ children }) {
|
|
1422
|
+
return children;
|
|
1423
|
+
}
|
|
1424
|
+
function Task({ id, action }) {
|
|
1425
|
+
const latest = useRef(action);
|
|
1426
|
+
latest.current = action;
|
|
1427
|
+
useEffect(() => {
|
|
1428
|
+
const controller = new AbortController();
|
|
1429
|
+
Promise.resolve().then(() => latest.current(controller.signal)).catch((error) => {
|
|
1430
|
+
if (!controller.signal.aborted) console.error(error);
|
|
1431
|
+
});
|
|
1432
|
+
return () => controller.abort();
|
|
1433
|
+
}, [id]);
|
|
1434
|
+
return null;
|
|
1435
|
+
}
|
|
1436
|
+
function OnChange({
|
|
1437
|
+
value,
|
|
1438
|
+
action,
|
|
1439
|
+
initial
|
|
1440
|
+
}) {
|
|
1441
|
+
const previous = useRef(null);
|
|
1442
|
+
const latest = useRef(action);
|
|
1443
|
+
latest.current = action;
|
|
1444
|
+
useEffect(() => {
|
|
1445
|
+
const last = previous.current;
|
|
1446
|
+
previous.current = { value };
|
|
1447
|
+
if (last === null) {
|
|
1448
|
+
if (initial) latest.current(value, value);
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (!Object.is(last.value, value)) latest.current(last.value, value);
|
|
1452
|
+
}, [value, initial]);
|
|
1453
|
+
return null;
|
|
1454
|
+
}
|
|
1455
|
+
function Hover({ action, children }) {
|
|
1456
|
+
return sb("styled", { style: { hover: true } }, { hover: (event) => action(event.value) }, children);
|
|
1457
|
+
}
|
|
1458
|
+
const CURSORS = {
|
|
1459
|
+
link: "pointer",
|
|
1460
|
+
automatic: "auto",
|
|
1461
|
+
default: "default",
|
|
1462
|
+
text: "text",
|
|
1463
|
+
verticalText: "vertical-text",
|
|
1464
|
+
grabIdle: "grab",
|
|
1465
|
+
grabActive: "grabbing",
|
|
1466
|
+
rectSelection: "crosshair",
|
|
1467
|
+
columnResize: "col-resize",
|
|
1468
|
+
rowResize: "row-resize"
|
|
1469
|
+
};
|
|
1470
|
+
function cursorFor(style) {
|
|
1471
|
+
return CURSORS[style] ?? style;
|
|
1472
|
+
}
|
|
1473
|
+
function SymbolEffect({ spec, children }) {
|
|
1474
|
+
const serial = useRef(null);
|
|
1475
|
+
const discrete = "value" in spec;
|
|
1476
|
+
if (discrete) {
|
|
1477
|
+
if (!serial.current) serial.current = { value: spec.value, count: 0 };
|
|
1478
|
+
else if (!Object.is(serial.current.value, spec.value)) serial.current = { value: spec.value, count: serial.current.count + 1 };
|
|
1479
|
+
}
|
|
1480
|
+
if (!discrete && spec.isActive === false) return children;
|
|
1481
|
+
const effect = { effect: spec.effect };
|
|
1482
|
+
if (spec.direction) effect.direction = spec.direction;
|
|
1483
|
+
if (spec.speed !== void 0) effect.speed = spec.speed;
|
|
1484
|
+
if (spec.repeat !== void 0) effect.repeat = spec.repeat;
|
|
1485
|
+
if (discrete) effect.trigger = serial.current.count;
|
|
1486
|
+
return styled({ symbolEffect: effect }, children);
|
|
1487
|
+
}
|
|
1488
|
+
function useNamespace() {
|
|
1489
|
+
return useId();
|
|
1490
|
+
}
|
|
1491
|
+
const KEY_NAMES = {
|
|
1492
|
+
return: "Enter",
|
|
1493
|
+
escape: "Escape",
|
|
1494
|
+
delete: "Backspace",
|
|
1495
|
+
tab: "Tab",
|
|
1496
|
+
space: " ",
|
|
1497
|
+
upArrow: "ArrowUp",
|
|
1498
|
+
downArrow: "ArrowDown",
|
|
1499
|
+
leftArrow: "ArrowLeft",
|
|
1500
|
+
rightArrow: "ArrowRight"
|
|
1501
|
+
};
|
|
1046
1502
|
const isApple = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
|
|
1047
1503
|
function matchesKey(event, key) {
|
|
1048
1504
|
const name = KEY_NAMES[key] ?? key;
|
|
@@ -1128,10 +1584,31 @@ function toolbarPlacement(name) {
|
|
|
1128
1584
|
return "principal";
|
|
1129
1585
|
case "bottomBar":
|
|
1130
1586
|
return "bottom";
|
|
1587
|
+
case "secondaryAction":
|
|
1588
|
+
return "secondary";
|
|
1131
1589
|
default:
|
|
1132
1590
|
return "trailing";
|
|
1133
1591
|
}
|
|
1134
1592
|
}
|
|
1593
|
+
function containerRelativeFrame(value) {
|
|
1594
|
+
const spec = typeof value === "string" ? { axes: value } : value;
|
|
1595
|
+
const horizontal = spec.axes !== "vertical";
|
|
1596
|
+
const vertical = spec.axes !== "horizontal";
|
|
1597
|
+
let a = 1;
|
|
1598
|
+
let b = 0;
|
|
1599
|
+
if (spec.length) {
|
|
1600
|
+
const axis = horizontal ? "horizontal" : "vertical";
|
|
1601
|
+
b = spec.length(0, axis);
|
|
1602
|
+
a = (spec.length(1e3, axis) - b) / 1e3;
|
|
1603
|
+
} else if (spec.count !== void 0) {
|
|
1604
|
+
const n = Math.max(spec.count, 1);
|
|
1605
|
+
const span = Math.max(spec.span ?? 1, 1);
|
|
1606
|
+
const spacing = spec.spacing ?? 0;
|
|
1607
|
+
a = span / n;
|
|
1608
|
+
b = -spacing * (n - 1) * span / n + spacing * (span - 1);
|
|
1609
|
+
}
|
|
1610
|
+
return { ...horizontal ? { horizontal: true } : {}, ...vertical ? { vertical: true } : {}, a, b, alignment: spec.alignment ?? "center" };
|
|
1611
|
+
}
|
|
1135
1612
|
const MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
1136
1613
|
"padding",
|
|
1137
1614
|
"font",
|
|
@@ -1169,6 +1646,7 @@ const MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
|
1169
1646
|
"labelsHidden",
|
|
1170
1647
|
"navigationTitle",
|
|
1171
1648
|
"navigationBarTitleDisplayMode",
|
|
1649
|
+
"toolbarRole",
|
|
1172
1650
|
"toolbar",
|
|
1173
1651
|
"searchable",
|
|
1174
1652
|
"navigationDestination",
|
|
@@ -1230,7 +1708,13 @@ const MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
|
1230
1708
|
"sensoryFeedback",
|
|
1231
1709
|
"textCase",
|
|
1232
1710
|
"coordinateSpace",
|
|
1233
|
-
"contentTransition"
|
|
1711
|
+
"contentTransition",
|
|
1712
|
+
"scrollEdgeEffectStyle",
|
|
1713
|
+
"scrollEdgeEffectHidden",
|
|
1714
|
+
"contentMargins",
|
|
1715
|
+
"containerRelativeFrame",
|
|
1716
|
+
"visualEffect",
|
|
1717
|
+
"scrollTransition"
|
|
1234
1718
|
]);
|
|
1235
1719
|
function splitProps(props) {
|
|
1236
1720
|
const own = {};
|
|
@@ -1253,8 +1737,8 @@ function styled(style, child) {
|
|
|
1253
1737
|
}
|
|
1254
1738
|
function decorated(role, alignment, content, decoration) {
|
|
1255
1739
|
return sb("decorated", { role, alignment }, void 0, [
|
|
1256
|
-
createElement(Fragment
|
|
1257
|
-
createElement(Fragment
|
|
1740
|
+
createElement(Fragment, { key: "content" }, content),
|
|
1741
|
+
createElement(Fragment, { key: "decoration" }, decoration)
|
|
1258
1742
|
]);
|
|
1259
1743
|
}
|
|
1260
1744
|
function shapeSpecOf(element) {
|
|
@@ -1276,7 +1760,7 @@ function applyModifiers(element, modifiers) {
|
|
|
1276
1760
|
const sides = [];
|
|
1277
1761
|
const node = wrap(element, modifiers, sides);
|
|
1278
1762
|
if (sides.length === 0) return node;
|
|
1279
|
-
return createElement(Fragment
|
|
1763
|
+
return createElement(Fragment, null, node, ...sides);
|
|
1280
1764
|
}
|
|
1281
1765
|
function wrap(element, modifiers, sides) {
|
|
1282
1766
|
let node = element;
|
|
@@ -1398,6 +1882,9 @@ function apply(key, value, node, sides) {
|
|
|
1398
1882
|
case "navigationBarTitleDisplayMode":
|
|
1399
1883
|
sides.push(sb(PREF_KIND, { displayMode: value }, void 0, void 0, "navscreen"));
|
|
1400
1884
|
return node;
|
|
1885
|
+
case "toolbarRole":
|
|
1886
|
+
sides.push(sb(PREF_KIND, { toolbarRole: value }, void 0, void 0, "navscreen"));
|
|
1887
|
+
return node;
|
|
1401
1888
|
case "toolbar":
|
|
1402
1889
|
sides.push(sb(HOIST_KIND, void 0, void 0, value, "navscreen"));
|
|
1403
1890
|
return node;
|
|
@@ -1454,7 +1941,7 @@ function apply(key, value, node, sides) {
|
|
|
1454
1941
|
);
|
|
1455
1942
|
}
|
|
1456
1943
|
case "contextMenu":
|
|
1457
|
-
return sb("contextmenu", {}, void 0, [createElement(Fragment
|
|
1944
|
+
return sb("contextmenu", {}, void 0, [createElement(Fragment, { key: "content" }, node), createElement(Fragment, { key: "items" }, value)]);
|
|
1458
1945
|
case "swipeActions": {
|
|
1459
1946
|
const specs = Array.isArray(value) ? value : [value];
|
|
1460
1947
|
const trailing = [];
|
|
@@ -1475,7 +1962,7 @@ function apply(key, value, node, sides) {
|
|
|
1475
1962
|
"swipeactions",
|
|
1476
1963
|
{ trailing: trailing.length, leading: leading.length, fullSwipeTrailing, fullSwipeLeading },
|
|
1477
1964
|
void 0,
|
|
1478
|
-
[createElement(Fragment
|
|
1965
|
+
[createElement(Fragment, { key: "content" }, node), ...trailing, ...leading]
|
|
1479
1966
|
);
|
|
1480
1967
|
}
|
|
1481
1968
|
case "onAppear":
|
|
@@ -1535,7 +2022,7 @@ function apply(key, value, node, sides) {
|
|
|
1535
2022
|
const spec = value;
|
|
1536
2023
|
const at = (width, height) => spec.value({ width, height });
|
|
1537
2024
|
const a = at(0, 0);
|
|
1538
|
-
const
|
|
2025
|
+
const round2 = (n) => Math.round(n * 1e6) / 1e6;
|
|
1539
2026
|
const vertical = ["top", "bottom", "verticalCenter", "firstTextBaseline", "lastTextBaseline"].includes(spec.guide);
|
|
1540
2027
|
const name = spec.guide === "horizontalCenter" || spec.guide === "verticalCenter" ? "center" : spec.guide;
|
|
1541
2028
|
return styled(
|
|
@@ -1543,7 +2030,7 @@ function apply(key, value, node, sides) {
|
|
|
1543
2030
|
alignmentGuide: {
|
|
1544
2031
|
axis: vertical ? "vertical" : "horizontal",
|
|
1545
2032
|
name,
|
|
1546
|
-
value: [
|
|
2033
|
+
value: [round2(a), round2((at(100, 0) - a) / 100), round2((at(0, 100) - a) / 100)]
|
|
1547
2034
|
}
|
|
1548
2035
|
},
|
|
1549
2036
|
node
|
|
@@ -1592,7 +2079,7 @@ function apply(key, value, node, sides) {
|
|
|
1592
2079
|
const spec = value;
|
|
1593
2080
|
const vertical = spec.edge === "top" || spec.edge === "bottom";
|
|
1594
2081
|
const before = spec.edge === "top" || spec.edge === "leading";
|
|
1595
|
-
const children = before ? [createElement(Fragment
|
|
2082
|
+
const children = before ? [createElement(Fragment, { key: "inset" }, spec.content), createElement(Fragment, { key: "content" }, node)] : [createElement(Fragment, { key: "content" }, node), createElement(Fragment, { key: "inset" }, spec.content)];
|
|
1596
2083
|
return vertical ? sb("vstack", { spacing: spec.spacing ?? 0, alignment: spec.alignment ?? "center" }, void 0, children) : sb("hstack", { spacing: spec.spacing ?? 0, alignment: spec.alignment ?? "center" }, void 0, children);
|
|
1597
2084
|
}
|
|
1598
2085
|
case "popover":
|
|
@@ -1605,406 +2092,538 @@ function apply(key, value, node, sides) {
|
|
|
1605
2092
|
case "onKeyPress":
|
|
1606
2093
|
sides.push(createElement(KeyPressListener, { spec: value }));
|
|
1607
2094
|
return node;
|
|
1608
|
-
case "sensoryFeedback": {
|
|
1609
|
-
const spec = value;
|
|
1610
|
-
sides.push(createElement(SensoryFeedbackPlayer, spec));
|
|
1611
|
-
return node;
|
|
1612
|
-
}
|
|
1613
|
-
case "textCase":
|
|
1614
|
-
return withEnvironment({ textCase: value }, node);
|
|
1615
|
-
case "coordinateSpace":
|
|
1616
|
-
return createElement(CoordinateSpace, { name: value }, node);
|
|
1617
|
-
case "contentTransition": {
|
|
1618
|
-
if (value === "identity") return node;
|
|
1619
|
-
if (typeof value === "object") {
|
|
1620
|
-
const countsDown = value.numericText.countsDown;
|
|
1621
|
-
return styled({ contentTransition: { kind: "numericText", ...countsDown !== void 0 ? { countsDown } : {} } }, node);
|
|
1622
|
-
}
|
|
1623
|
-
return styled({ contentTransition: { kind: value } }, node);
|
|
1624
|
-
}
|
|
1625
|
-
case "modifiers": {
|
|
1626
|
-
let result = node;
|
|
1627
|
-
for (const extra of value) {
|
|
1628
|
-
result = wrap(result, Object.entries(extra), sides);
|
|
1629
|
-
}
|
|
1630
|
-
return result;
|
|
1631
|
-
}
|
|
1632
|
-
default: {
|
|
1633
|
-
const unknown = key;
|
|
1634
|
-
throw new Error(`Unknown modifier ${String(unknown)}`);
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
const ScrollRequestContext = createContext(null);
|
|
1639
|
-
let nextSerial = 1;
|
|
1640
|
-
function ScrollViewReader({ children }) {
|
|
1641
|
-
const [request, setRequest] = useState(null);
|
|
1642
|
-
const proxy = {
|
|
1643
|
-
scrollTo: (id, anchor) => setRequest({ id, anchor: anchor === void 0 ? null : unitPoint(anchor), serial: nextSerial++ })
|
|
1644
|
-
};
|
|
1645
|
-
return /* @__PURE__ */ jsx(ScrollRequestContext.Provider, { value: request, children: children(proxy) });
|
|
1646
|
-
}
|
|
1647
|
-
function ScrollTarget({ id, children }) {
|
|
1648
|
-
const request = useContext(ScrollRequestContext);
|
|
1649
|
-
if (request && request.id === id) return styled({ scrollID: true, scrollTo: { anchor: request.anchor, serial: request.serial } }, children);
|
|
1650
|
-
return styled({ scrollID: true }, children);
|
|
1651
|
-
}
|
|
1652
|
-
const ListSelectionContext = createContext(null);
|
|
1653
|
-
function Row({ tag, onDelete, deletable, onMove, movable, index, containerIndex, children }) {
|
|
1654
|
-
const selection = useContext(ListSelectionContext);
|
|
1655
|
-
const selectable = selection !== null && tag !== void 0;
|
|
1656
|
-
const canDelete = onDelete !== void 0 && deletable !== false;
|
|
1657
|
-
const canMove = onMove !== void 0 && movable !== false;
|
|
1658
|
-
if (!selectable && !canDelete && !canMove) return children;
|
|
1659
|
-
const props = {};
|
|
1660
|
-
if (selectable) {
|
|
1661
|
-
props["selectable"] = true;
|
|
1662
|
-
props["selected"] = selection.isSelected(tag);
|
|
1663
|
-
}
|
|
1664
|
-
if (canDelete) props["deletable"] = true;
|
|
1665
|
-
if (canMove) props["movable"] = true;
|
|
1666
|
-
return sb(
|
|
1667
|
-
"listrow",
|
|
1668
|
-
props,
|
|
1669
|
-
{
|
|
1670
|
-
tap: () => selectable && selection.select(tag),
|
|
1671
|
-
delete: () => onDelete?.(),
|
|
1672
|
-
move: (event) => {
|
|
1673
|
-
const start = (containerIndex ?? index ?? 0) - (index ?? 0);
|
|
1674
|
-
onMove?.(Math.max(0, event.to - start));
|
|
1675
|
-
}
|
|
1676
|
-
},
|
|
1677
|
-
children
|
|
1678
|
-
);
|
|
1679
|
-
}
|
|
1680
|
-
const LAZY_BATCH = 12;
|
|
1681
|
-
const LazyContext = createContext(null);
|
|
1682
|
-
function LazyGroup({ rows, start = 0, wrap: wrap2 }) {
|
|
1683
|
-
const axis = useContext(LazyContext);
|
|
1684
|
-
const request = useContext(ScrollRequestContext);
|
|
1685
|
-
const [count, setCount] = useState(LAZY_BATCH);
|
|
1686
|
-
const target = request ? rows.findIndex((row) => rowMatches(row, request.id)) : -1;
|
|
1687
|
-
const needed = target >= 0 ? Math.ceil((target + 1) / LAZY_BATCH) * LAZY_BATCH : 0;
|
|
1688
|
-
useEffect(() => {
|
|
1689
|
-
if (needed > count) setCount(needed);
|
|
1690
|
-
}, [needed, count]);
|
|
1691
|
-
const visible = Math.max(count, needed);
|
|
1692
|
-
const shown = axis === null ? rows : rows.slice(0, visible);
|
|
1693
|
-
const built = shown.map((row, index) => wrap2 ? wrap2(row, start + index) : row);
|
|
1694
|
-
if (axis === null || shown.length >= rows.length) return built;
|
|
1695
|
-
return [
|
|
1696
|
-
...built,
|
|
1697
|
-
createElement(
|
|
1698
|
-
LazySpacer,
|
|
1699
|
-
{ key: `lazy-${visible}`, axis, remaining: rows.length - shown.length, more: () => setCount(visible + LAZY_BATCH) }
|
|
1700
|
-
)
|
|
1701
|
-
];
|
|
1702
|
-
}
|
|
1703
|
-
function LazySpacer({ axis, remaining, more }) {
|
|
1704
|
-
return sb("lazyspacer", { axis, remaining }, { lazy: more });
|
|
1705
|
-
}
|
|
1706
|
-
function rowMatches(row, id) {
|
|
1707
|
-
if (row.key !== null && row.key === String(id)) return true;
|
|
1708
|
-
let element = row;
|
|
1709
|
-
for (let depth = 0; element && depth < 3; depth++) {
|
|
1710
|
-
const props = element.props;
|
|
1711
|
-
if (props.scrollID === id) return true;
|
|
1712
|
-
element = isValidElement(props.children) ? props.children : null;
|
|
1713
|
-
}
|
|
1714
|
-
return false;
|
|
1715
|
-
}
|
|
1716
|
-
function VStack(props) {
|
|
1717
|
-
const { own, modifiers } = splitProps(props);
|
|
1718
|
-
const stack = { spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
1719
|
-
if (own.scrollTargetLayout) stack["scrollTarget"] = true;
|
|
1720
|
-
return applyModifiers(sb("vstack", stack, void 0, own.children), modifiers);
|
|
1721
|
-
}
|
|
1722
|
-
function HStack(props) {
|
|
1723
|
-
const { own, modifiers } = splitProps(props);
|
|
1724
|
-
const stack = { spacing: own.spacing ?? null, alignment: own.alignment ?? "center" };
|
|
1725
|
-
if (own.scrollTargetLayout) stack["scrollTarget"] = true;
|
|
1726
|
-
return applyModifiers(sb("hstack", stack, void 0, own.children), modifiers);
|
|
1727
|
-
}
|
|
1728
|
-
function ZStack(props) {
|
|
1729
|
-
const { own, modifiers } = splitProps(props);
|
|
1730
|
-
return applyModifiers(sb("zstack", { alignment: own.alignment ?? "center" }, void 0, own.children), modifiers);
|
|
1731
|
-
}
|
|
1732
|
-
function Spacer(props) {
|
|
1733
|
-
const { own, modifiers } = splitProps(props);
|
|
1734
|
-
return applyModifiers(sb("spacer", { minLength: own.minLength ?? null }), modifiers);
|
|
1735
|
-
}
|
|
1736
|
-
function Divider(props) {
|
|
1737
|
-
const { modifiers } = splitProps(props);
|
|
1738
|
-
return applyModifiers(sb("divider", {}), modifiers);
|
|
1739
|
-
}
|
|
1740
|
-
function ScrollView(props) {
|
|
1741
|
-
const { own, modifiers } = splitProps(props);
|
|
1742
|
-
const refresh = useRefreshable(takeModifier(modifiers, "refreshable"));
|
|
1743
|
-
const scroll = { axes: own.axes ?? "vertical", ...refresh.props };
|
|
1744
|
-
if (own.scrollTargetBehavior) scroll["snap"] = own.scrollTargetBehavior;
|
|
1745
|
-
if (own.scrollDismissesKeyboard) scroll["dismissesKeyboard"] = true;
|
|
1746
|
-
return applyModifiers(sb("scrollview", scroll, refresh.handlers, own.children), modifiers);
|
|
1747
|
-
}
|
|
1748
|
-
function useRefreshable(own) {
|
|
1749
|
-
const environment = useViewEnvironment();
|
|
1750
|
-
const refresh = own ?? environment.refresh;
|
|
1751
|
-
const [refreshing, setRefreshing] = useState(false);
|
|
1752
|
-
if (!refresh) return { props: {} };
|
|
1753
|
-
return {
|
|
1754
|
-
props: { refreshable: true, refreshing },
|
|
1755
|
-
handlers: {
|
|
1756
|
-
refresh: () => {
|
|
1757
|
-
if (refreshing) return;
|
|
1758
|
-
setRefreshing(true);
|
|
1759
|
-
Promise.resolve().then(refresh).catch((error) => console.error(error)).finally(() => setRefreshing(false));
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
function Group(props) {
|
|
1765
|
-
const { own, modifiers } = splitProps(props);
|
|
1766
|
-
if (modifiers.length === 0) return own.children;
|
|
1767
|
-
return Children.map(own.children, (child) => applyModifiers(child, modifiers));
|
|
1768
|
-
}
|
|
1769
|
-
function moveItems(items, offsets, to) {
|
|
1770
|
-
const moving = new Set(offsets);
|
|
1771
|
-
const picked = items.filter((_, index) => moving.has(index));
|
|
1772
|
-
const rest = items.filter((_, index) => !moving.has(index));
|
|
1773
|
-
const before = offsets.filter((offset) => offset < to).length;
|
|
1774
|
-
const at = to - before;
|
|
1775
|
-
return [...rest.slice(0, at), ...picked, ...rest.slice(at)];
|
|
1776
|
-
}
|
|
1777
|
-
function ForEach(props) {
|
|
1778
|
-
const { own, modifiers } = splitProps(props);
|
|
1779
|
-
const rows = own.data.map((element, index) => {
|
|
1780
|
-
const key = own.id ? own.id(element, index) : keyOf(element, index);
|
|
1781
|
-
const content = applyModifiers(own.children(element, index), modifiers);
|
|
1782
|
-
if (!own.onDelete && !own.onMove) return createElement(Fragment$1, { key }, content);
|
|
1783
|
-
const { onDelete, onMove } = own;
|
|
1784
|
-
const row = { tag: key, index };
|
|
1785
|
-
if (onDelete) {
|
|
1786
|
-
row.onDelete = () => onDelete([index]);
|
|
1787
|
-
row.deletable = !own.deleteDisabled?.(element, index);
|
|
1788
|
-
}
|
|
1789
|
-
if (onMove) {
|
|
1790
|
-
row.onMove = (to) => onMove([index], to);
|
|
1791
|
-
row.movable = !own.moveDisabled?.(element, index);
|
|
2095
|
+
case "sensoryFeedback": {
|
|
2096
|
+
const spec = value;
|
|
2097
|
+
sides.push(createElement(SensoryFeedbackPlayer, spec));
|
|
2098
|
+
return node;
|
|
1792
2099
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
node.forEach(visit);
|
|
1811
|
-
return;
|
|
2100
|
+
case "textCase":
|
|
2101
|
+
return withEnvironment({ textCase: value }, node);
|
|
2102
|
+
case "coordinateSpace":
|
|
2103
|
+
return createElement(CoordinateSpace, { name: value }, node);
|
|
2104
|
+
case "scrollEdgeEffectStyle":
|
|
2105
|
+
return withScrollSettings(edgeStyleSettings(value), node);
|
|
2106
|
+
case "scrollEdgeEffectHidden":
|
|
2107
|
+
return withScrollSettings(edgeHiddenSettings(value), node);
|
|
2108
|
+
case "contentMargins":
|
|
2109
|
+
return withScrollSettings(marginSettings(value), node);
|
|
2110
|
+
case "containerRelativeFrame":
|
|
2111
|
+
return styled({ containerRelativeFrame: containerRelativeFrame(value) }, node);
|
|
2112
|
+
case "visualEffect":
|
|
2113
|
+
return createElement(VisualEffectView, { effect: value }, node);
|
|
2114
|
+
case "scrollTransition": {
|
|
2115
|
+
const spec = typeof value === "function" ? { transition: value } : value;
|
|
2116
|
+
return createElement(ScrollTransitionView, { spec }, node);
|
|
1812
2117
|
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
visit({ ...inner, key: element.key });
|
|
1819
|
-
return;
|
|
2118
|
+
case "contentTransition": {
|
|
2119
|
+
if (value === "identity") return node;
|
|
2120
|
+
if (typeof value === "object") {
|
|
2121
|
+
const countsDown = value.numericText.countsDown;
|
|
2122
|
+
return styled({ contentTransition: { kind: "numericText", ...countsDown !== void 0 ? { countsDown } : {} } }, node);
|
|
1820
2123
|
}
|
|
1821
|
-
|
|
1822
|
-
return;
|
|
2124
|
+
return styled({ contentTransition: { kind: value } }, node);
|
|
1823
2125
|
}
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
2126
|
+
case "modifiers": {
|
|
2127
|
+
let result = node;
|
|
2128
|
+
for (const extra of value) {
|
|
2129
|
+
result = wrap(result, Object.entries(extra), sides);
|
|
2130
|
+
}
|
|
2131
|
+
return result;
|
|
1827
2132
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
2133
|
+
default: {
|
|
2134
|
+
const unknown = key;
|
|
2135
|
+
throw new Error(`Unknown modifier ${String(unknown)}`);
|
|
1831
2136
|
}
|
|
1832
|
-
result.push(element);
|
|
1833
|
-
};
|
|
1834
|
-
visit(children);
|
|
1835
|
-
return result;
|
|
1836
|
-
}
|
|
1837
|
-
function GridItem(spec = {}) {
|
|
1838
|
-
const dimension = (n) => n === void 0 || n === Infinity ? "infinity" : n;
|
|
1839
|
-
let size;
|
|
1840
|
-
if (spec.size && "fixed" in spec.size) size = { kind: "fixed", value: spec.size.fixed };
|
|
1841
|
-
else if (spec.size && "adaptive" in spec.size) {
|
|
1842
|
-
size = { kind: "adaptive", minimum: spec.size.adaptive.minimum, maximum: dimension(spec.size.adaptive.maximum) };
|
|
1843
|
-
} else {
|
|
1844
|
-
const flexible = spec.size && "flexible" in spec.size ? spec.size.flexible : {};
|
|
1845
|
-
size = { kind: "flexible", minimum: flexible.minimum ?? 10, maximum: dimension(flexible.maximum) };
|
|
1846
2137
|
}
|
|
1847
|
-
return { size, spacing: spec.spacing ?? null, alignment: spec.alignment ?? null };
|
|
1848
2138
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2139
|
+
const NO_INSETS = { top: 0, leading: 0, bottom: 0, trailing: 0 };
|
|
2140
|
+
const NO_GEOMETRY = { size: { width: 0, height: 0 }, origin: null, safeArea: NO_INSETS, scrollView: null };
|
|
2141
|
+
function nextGeometry(event, reported) {
|
|
2142
|
+
const hasOrigin = event.x !== void 0 && event.y !== void 0;
|
|
2143
|
+
return {
|
|
2144
|
+
size: { width: event.width, height: event.height },
|
|
2145
|
+
origin: hasOrigin ? { x: event.x, y: event.y } : reported.origin,
|
|
2146
|
+
safeArea: event.safeArea ?? reported.safeArea,
|
|
2147
|
+
// A frame report without a scroll view means the reader is in none.
|
|
2148
|
+
scrollView: hasOrigin ? event.scrollView ?? null : reported.scrollView
|
|
2149
|
+
};
|
|
1858
2150
|
}
|
|
1859
|
-
function
|
|
2151
|
+
function geometryProxy(reported, spaces, onReadFrame) {
|
|
2152
|
+
return {
|
|
2153
|
+
size: reported.size,
|
|
2154
|
+
frame: (space = "local") => {
|
|
2155
|
+
if (space === "local") return { x: 0, y: 0, ...reported.size };
|
|
2156
|
+
onReadFrame();
|
|
2157
|
+
const origin = reported.origin ?? { x: 0, y: 0 };
|
|
2158
|
+
if (space === "global") return { ...origin, ...reported.size };
|
|
2159
|
+
const named = spaces[space.named];
|
|
2160
|
+
return { x: origin.x - (named?.x ?? 0), y: origin.y - (named?.y ?? 0), ...reported.size };
|
|
2161
|
+
},
|
|
2162
|
+
bounds: () => {
|
|
2163
|
+
onReadFrame();
|
|
2164
|
+
const view = reported.scrollView;
|
|
2165
|
+
if (!view || !reported.origin) return null;
|
|
2166
|
+
return { x: view.x - reported.origin.x, y: view.y - reported.origin.y, width: view.width, height: view.height };
|
|
2167
|
+
},
|
|
2168
|
+
get safeAreaInsets() {
|
|
2169
|
+
onReadFrame();
|
|
2170
|
+
return reported.safeArea;
|
|
2171
|
+
}
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
function GeometryReader(props) {
|
|
1860
2175
|
const { own, modifiers } = splitProps(props);
|
|
2176
|
+
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
2177
|
+
const [needsFrame, setNeedsFrame] = useState(false);
|
|
2178
|
+
let readFrame = false;
|
|
2179
|
+
const proxy = geometryProxy(reported, useCoordinateSpaces(), () => {
|
|
2180
|
+
readFrame = true;
|
|
2181
|
+
});
|
|
2182
|
+
const content = own.children(proxy);
|
|
2183
|
+
useEffect(() => {
|
|
2184
|
+
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2185
|
+
});
|
|
1861
2186
|
return applyModifiers(
|
|
1862
2187
|
sb(
|
|
1863
|
-
"
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
2188
|
+
"geometry",
|
|
2189
|
+
needsFrame ? { reportsFrame: true } : {},
|
|
2190
|
+
{
|
|
2191
|
+
geometry: (event) => {
|
|
2192
|
+
const next = nextGeometry(event, reported);
|
|
2193
|
+
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2194
|
+
}
|
|
2195
|
+
},
|
|
2196
|
+
content
|
|
1867
2197
|
),
|
|
1868
2198
|
modifiers
|
|
1869
2199
|
);
|
|
1870
2200
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
return
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
if (props.italic) style.italic = true;
|
|
1878
|
-
if (props.underline) style.underline = typeof props.underline === "object" && props.underline.color ? { color: color(props.underline.color) } : {};
|
|
1879
|
-
if (props.strikethrough) {
|
|
1880
|
-
style.strikethrough = typeof props.strikethrough === "object" && props.strikethrough.color ? { color: color(props.strikethrough.color) } : {};
|
|
1881
|
-
}
|
|
1882
|
-
const kerning = props.tracking ?? props.kerning;
|
|
1883
|
-
if (kerning !== void 0) style.kerning = kerning;
|
|
1884
|
-
if (props.baselineOffset !== void 0) style.baselineOffset = props.baselineOffset;
|
|
1885
|
-
if (props.link) style.link = props.link;
|
|
1886
|
-
if (nested) {
|
|
1887
|
-
let runFont = props.font !== void 0 ? font(props.font) : void 0;
|
|
1888
|
-
if (props.bold) runFont = { ...runFont ?? {}, weight: "bold" };
|
|
1889
|
-
if (props.fontWeight) runFont = { ...runFont ?? {}, weight: props.fontWeight };
|
|
1890
|
-
if (runFont) style.font = { ...style.font ?? {}, ...runFont };
|
|
1891
|
-
if (props.foregroundStyle !== void 0) style.foreground = shapeStyle(props.foregroundStyle);
|
|
1892
|
-
}
|
|
1893
|
-
return style;
|
|
1894
|
-
}
|
|
1895
|
-
function segmentsOf(children, style, into) {
|
|
1896
|
-
const visit = (node) => {
|
|
1897
|
-
if (node === null || node === void 0 || typeof node === "boolean") return;
|
|
1898
|
-
if (typeof node === "string" || typeof node === "number") {
|
|
1899
|
-
const last = into[into.length - 1];
|
|
1900
|
-
if (last && "text" in last && last.style === style) last.text += String(node);
|
|
1901
|
-
else into.push({ text: String(node), style });
|
|
1902
|
-
return;
|
|
1903
|
-
}
|
|
1904
|
-
if (Array.isArray(node)) {
|
|
1905
|
-
node.forEach(visit);
|
|
1906
|
-
return;
|
|
1907
|
-
}
|
|
1908
|
-
if (!isValidElement(node)) return;
|
|
1909
|
-
const element = node;
|
|
1910
|
-
if (element.type === Fragment$1) {
|
|
1911
|
-
visit(element.props["children"]);
|
|
1912
|
-
return;
|
|
1913
|
-
}
|
|
1914
|
-
if (element.type === Text) {
|
|
1915
|
-
const props = element.props;
|
|
1916
|
-
segmentsOf(props.children, runStyleOf(props, style, true), into);
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
if (element.type === Image$1) {
|
|
1920
|
-
const props = element.props;
|
|
1921
|
-
into.push({ image: imageProps(props), style });
|
|
1922
|
-
return;
|
|
1923
|
-
}
|
|
1924
|
-
};
|
|
1925
|
-
visit(children);
|
|
2201
|
+
const DEFAULT_VIEW_SPACING = { distance: () => 8 };
|
|
2202
|
+
function subviewTraits(children) {
|
|
2203
|
+
return flattenChildren(children).map((element) => {
|
|
2204
|
+
const props = element.props;
|
|
2205
|
+
return { priority: props.layoutPriority ?? 0, values: props.layoutValue ?? {} };
|
|
2206
|
+
});
|
|
1926
2207
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
2208
|
+
const fromDimension = (value) => value === "infinity" ? Infinity : value;
|
|
2209
|
+
const toDimension = (value) => Number.isFinite(value) ? Math.round(value * 100) / 100 : "infinity";
|
|
2210
|
+
const toSize = (size) => ({
|
|
2211
|
+
width: fromDimension(size.width) ?? 0,
|
|
2212
|
+
height: fromDimension(size.height) ?? 0
|
|
2213
|
+
});
|
|
2214
|
+
const GUIDES = ["leading", "horizontalCenter", "trailing", "top", "verticalCenter", "bottom", "firstTextBaseline", "lastTextBaseline"];
|
|
2215
|
+
function clamp(value, min, max) {
|
|
2216
|
+
return Math.min(Math.max(value, min), max);
|
|
1929
2217
|
}
|
|
1930
|
-
function
|
|
1931
|
-
const
|
|
1932
|
-
const
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
2218
|
+
function answerLayout(layout, record, traits = []) {
|
|
2219
|
+
const frames = record.children.map(() => null);
|
|
2220
|
+
const subviews = record.children.map((measurement, index) => {
|
|
2221
|
+
const min = toSize(measurement.min);
|
|
2222
|
+
const ideal = toSize(measurement.ideal);
|
|
2223
|
+
const max = toSize(measurement.max);
|
|
2224
|
+
const sizeThatFits = (proposal) => ({
|
|
2225
|
+
width: proposal.width === null ? ideal.width : clamp(proposal.width, min.width, max.width),
|
|
2226
|
+
height: proposal.height === null ? ideal.height : clamp(proposal.height, min.height, max.height)
|
|
2227
|
+
});
|
|
2228
|
+
return {
|
|
2229
|
+
min,
|
|
2230
|
+
ideal,
|
|
2231
|
+
max,
|
|
2232
|
+
priority: traits[index]?.priority ?? 0,
|
|
2233
|
+
values: traits[index]?.values ?? {},
|
|
2234
|
+
spacing: DEFAULT_VIEW_SPACING,
|
|
2235
|
+
sizeThatFits,
|
|
2236
|
+
place: ({ x, y, anchor, proposal }) => {
|
|
2237
|
+
const size2 = sizeThatFits(proposal ?? { width: null, height: null });
|
|
2238
|
+
const point = unitPoint(anchor ?? "topLeading");
|
|
2239
|
+
frames[index] = { x: x - point.x * size2.width, y: y - point.y * size2.height, ...size2 };
|
|
2240
|
+
}
|
|
2241
|
+
};
|
|
2242
|
+
});
|
|
2243
|
+
const cache = layout.makeCache ? layout.makeCache(subviews) : void 0;
|
|
2244
|
+
const measure = (proposal) => layout.sizeThatFits(proposal, subviews, cache);
|
|
2245
|
+
const size = measure(record.proposal);
|
|
2246
|
+
layout.placeSubviews({ x: 0, y: 0, ...size }, record.proposal, subviews, cache);
|
|
2247
|
+
const placed = frames.map((frame2, index) => {
|
|
2248
|
+
if (frame2) return frame2;
|
|
2249
|
+
const own = subviews[index].sizeThatFits({ width: size.width, height: size.height });
|
|
2250
|
+
return { x: (size.width - own.width) / 2, y: (size.height - own.height) / 2, ...own };
|
|
2251
|
+
});
|
|
2252
|
+
const guides = {};
|
|
2253
|
+
if (layout.explicitAlignment) {
|
|
2254
|
+
const bounds = { x: 0, y: 0, ...size };
|
|
2255
|
+
for (const guide of GUIDES) {
|
|
2256
|
+
const value = layout.explicitAlignment(guide, bounds, record.proposal, subviews, cache);
|
|
2257
|
+
if (value !== null && value !== void 0 && Number.isFinite(value)) guides[guide] = value;
|
|
1940
2258
|
}
|
|
1941
2259
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
}
|
|
1952
|
-
const hasLinks = segments.some((segment) => segment.style.link);
|
|
1953
|
-
const handlers = hasLinks ? { link: (event) => openURL(event.value) } : void 0;
|
|
1954
|
-
return applyModifiers(placeholder(sb("text", { text: content, runs }, handlers), redacted), modifiers);
|
|
2260
|
+
return {
|
|
2261
|
+
size,
|
|
2262
|
+
frames: placed,
|
|
2263
|
+
guides,
|
|
2264
|
+
sizes: {
|
|
2265
|
+
min: measure({ width: 0, height: 0 }),
|
|
2266
|
+
ideal: measure({ width: null, height: null }),
|
|
2267
|
+
max: measure({ width: Infinity, height: Infinity })
|
|
2268
|
+
}
|
|
2269
|
+
};
|
|
1955
2270
|
}
|
|
1956
|
-
function
|
|
1957
|
-
|
|
1958
|
-
|
|
2271
|
+
function Layout(props) {
|
|
2272
|
+
const { own, modifiers } = splitProps(props);
|
|
2273
|
+
const [record, setRecord] = useState(null);
|
|
2274
|
+
let layoutProps = { proposal: null, size: null, frames: null };
|
|
2275
|
+
const guideModifiers = [];
|
|
2276
|
+
if (record) {
|
|
2277
|
+
const answer = answerLayout(own.layout, record, subviewTraits(own.children));
|
|
2278
|
+
for (const [guide, value] of Object.entries(answer.guides)) guideModifiers.push(["alignmentGuide", { guide, value: () => value }]);
|
|
2279
|
+
const encode = (size) => ({ width: toDimension(size.width), height: toDimension(size.height) });
|
|
2280
|
+
const round2 = (value) => Math.round(value * 100) / 100;
|
|
2281
|
+
layoutProps = {
|
|
2282
|
+
proposal: {
|
|
2283
|
+
width: record.proposal.width === null ? null : toDimension(record.proposal.width),
|
|
2284
|
+
height: record.proposal.height === null ? null : toDimension(record.proposal.height)
|
|
2285
|
+
},
|
|
2286
|
+
size: { width: round2(answer.size.width), height: round2(answer.size.height) },
|
|
2287
|
+
frames: answer.frames.map((frame2) => ({ x: round2(frame2.x), y: round2(frame2.y), width: round2(frame2.width), height: round2(frame2.height) })),
|
|
2288
|
+
sizes: { min: encode(answer.sizes.min), ideal: encode(answer.sizes.ideal), max: encode(answer.sizes.max) }
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
return applyModifiers(
|
|
2292
|
+
sb(
|
|
2293
|
+
"layout",
|
|
2294
|
+
layoutProps,
|
|
2295
|
+
{
|
|
2296
|
+
layout: (event) => {
|
|
2297
|
+
const proposal = event.proposal;
|
|
2298
|
+
setRecord({
|
|
2299
|
+
proposal: { width: fromDimension(proposal.width), height: fromDimension(proposal.height) },
|
|
2300
|
+
children: event.children
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
},
|
|
2304
|
+
own.children
|
|
2305
|
+
),
|
|
2306
|
+
[...guideModifiers, ...modifiers]
|
|
2307
|
+
);
|
|
1959
2308
|
}
|
|
1960
|
-
|
|
1961
|
-
|
|
2309
|
+
const IDENTITY$1 = {
|
|
2310
|
+
offsetX: 0,
|
|
2311
|
+
offsetY: 0,
|
|
2312
|
+
scaleX: 1,
|
|
2313
|
+
scaleY: 1,
|
|
2314
|
+
rotation: 0,
|
|
2315
|
+
opacity: 1,
|
|
2316
|
+
blur: 0,
|
|
2317
|
+
brightness: 0,
|
|
2318
|
+
contrast: 1,
|
|
2319
|
+
saturation: 1,
|
|
2320
|
+
grayscale: 0,
|
|
2321
|
+
hueRotation: 0
|
|
2322
|
+
};
|
|
2323
|
+
class VisualEffect {
|
|
2324
|
+
/** @internal */
|
|
2325
|
+
constructor(values = IDENTITY$1) {
|
|
2326
|
+
this.values = values;
|
|
2327
|
+
}
|
|
2328
|
+
values;
|
|
2329
|
+
with(patch) {
|
|
2330
|
+
return new VisualEffect({ ...this.values, ...patch });
|
|
2331
|
+
}
|
|
2332
|
+
offset(offset) {
|
|
2333
|
+
return this.with({ offsetX: this.values.offsetX + (offset.x ?? 0), offsetY: this.values.offsetY + (offset.y ?? 0) });
|
|
2334
|
+
}
|
|
2335
|
+
scaleEffect(scale, anchor) {
|
|
2336
|
+
const x = typeof scale === "number" ? scale : scale.x ?? 1;
|
|
2337
|
+
const y = typeof scale === "number" ? scale : scale.y ?? 1;
|
|
2338
|
+
return this.with({ scaleX: this.values.scaleX * x, scaleY: this.values.scaleY * y, ...anchor !== void 0 ? { scaleAnchor: unitPoint(anchor) } : {} });
|
|
2339
|
+
}
|
|
2340
|
+
/** Degrees. */
|
|
2341
|
+
rotationEffect(degrees, anchor) {
|
|
2342
|
+
return this.with({ rotation: this.values.rotation + degrees, ...anchor !== void 0 ? { rotationAnchor: unitPoint(anchor) } : {} });
|
|
2343
|
+
}
|
|
2344
|
+
rotation3DEffect(spec) {
|
|
2345
|
+
const rotation = { angle: spec.angle, axis: spec.axis };
|
|
2346
|
+
if (spec.anchor !== void 0) rotation.anchor = unitPoint(spec.anchor);
|
|
2347
|
+
if (spec.perspective !== void 0) rotation.perspective = spec.perspective;
|
|
2348
|
+
return this.with({ rotation3D: rotation });
|
|
2349
|
+
}
|
|
2350
|
+
opacity(opacity2) {
|
|
2351
|
+
return this.with({ opacity: this.values.opacity * opacity2 });
|
|
2352
|
+
}
|
|
2353
|
+
blur(radius) {
|
|
2354
|
+
return this.with({ blur: this.values.blur + radius });
|
|
2355
|
+
}
|
|
2356
|
+
brightness(amount) {
|
|
2357
|
+
return this.with({ brightness: this.values.brightness + amount });
|
|
2358
|
+
}
|
|
2359
|
+
contrast(amount) {
|
|
2360
|
+
return this.with({ contrast: this.values.contrast * amount });
|
|
2361
|
+
}
|
|
2362
|
+
saturation(amount) {
|
|
2363
|
+
return this.with({ saturation: this.values.saturation * amount });
|
|
2364
|
+
}
|
|
2365
|
+
grayscale(amount) {
|
|
2366
|
+
return this.with({ grayscale: Math.min(1, this.values.grayscale + amount) });
|
|
2367
|
+
}
|
|
2368
|
+
/** Degrees. */
|
|
2369
|
+
hueRotation(degrees) {
|
|
2370
|
+
return this.with({ hueRotation: this.values.hueRotation + degrees });
|
|
2371
|
+
}
|
|
1962
2372
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
2373
|
+
const EMPTY_EFFECT = new VisualEffect();
|
|
2374
|
+
const round = (value) => Math.round(value * 1e3) / 1e3;
|
|
2375
|
+
function effectStyle(values) {
|
|
2376
|
+
const style = {};
|
|
2377
|
+
if (values.offsetX !== 0 || values.offsetY !== 0) style.offset = { x: round(values.offsetX), y: round(values.offsetY) };
|
|
2378
|
+
if (values.scaleX !== 1 || values.scaleY !== 1) {
|
|
2379
|
+
style.scale = { x: round(values.scaleX), y: round(values.scaleY) };
|
|
2380
|
+
if (values.scaleAnchor) style.scaleAnchor = values.scaleAnchor;
|
|
2381
|
+
}
|
|
2382
|
+
if (values.rotation !== 0) {
|
|
2383
|
+
style.rotation = round(values.rotation);
|
|
2384
|
+
if (values.rotationAnchor) style.rotationAnchor = values.rotationAnchor;
|
|
2385
|
+
}
|
|
2386
|
+
if (values.rotation3D && values.rotation3D.angle !== 0) style.rotation3D = { ...values.rotation3D, angle: round(values.rotation3D.angle) };
|
|
2387
|
+
if (values.opacity !== 1) style.opacity = round(values.opacity);
|
|
2388
|
+
if (values.blur !== 0) style.blur = round(values.blur);
|
|
2389
|
+
if (values.brightness !== 0) style.brightness = round(values.brightness);
|
|
2390
|
+
if (values.contrast !== 1) style.contrast = round(values.contrast);
|
|
2391
|
+
if (values.saturation !== 1) style.saturation = round(values.saturation);
|
|
2392
|
+
if (values.grayscale !== 0) style.grayscale = round(values.grayscale);
|
|
2393
|
+
if (values.hueRotation !== 0) style.hueRotation = round(values.hueRotation);
|
|
2394
|
+
return style;
|
|
1967
2395
|
}
|
|
1968
|
-
function
|
|
1969
|
-
const
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
|
|
2396
|
+
function interpolateEffects(from, to, t) {
|
|
2397
|
+
const mix = (a, b) => a + (b - a) * t;
|
|
2398
|
+
const result = {
|
|
2399
|
+
offsetX: mix(from.offsetX, to.offsetX),
|
|
2400
|
+
offsetY: mix(from.offsetY, to.offsetY),
|
|
2401
|
+
scaleX: mix(from.scaleX, to.scaleX),
|
|
2402
|
+
scaleY: mix(from.scaleY, to.scaleY),
|
|
2403
|
+
rotation: mix(from.rotation, to.rotation),
|
|
2404
|
+
opacity: mix(from.opacity, to.opacity),
|
|
2405
|
+
blur: mix(from.blur, to.blur),
|
|
2406
|
+
brightness: mix(from.brightness, to.brightness),
|
|
2407
|
+
contrast: mix(from.contrast, to.contrast),
|
|
2408
|
+
saturation: mix(from.saturation, to.saturation),
|
|
2409
|
+
grayscale: mix(from.grayscale, to.grayscale),
|
|
2410
|
+
hueRotation: mix(from.hueRotation, to.hueRotation)
|
|
2411
|
+
};
|
|
2412
|
+
const scaleAnchor = to.scaleAnchor ?? from.scaleAnchor;
|
|
2413
|
+
if (scaleAnchor) result.scaleAnchor = scaleAnchor;
|
|
2414
|
+
const rotationAnchor = to.rotationAnchor ?? from.rotationAnchor;
|
|
2415
|
+
if (rotationAnchor) result.rotationAnchor = rotationAnchor;
|
|
2416
|
+
const rotation3D = to.rotation3D ?? from.rotation3D;
|
|
2417
|
+
if (rotation3D) result.rotation3D = { ...rotation3D, angle: mix(from.rotation3D?.angle ?? 0, to.rotation3D?.angle ?? 0) };
|
|
2418
|
+
return result;
|
|
1973
2419
|
}
|
|
1974
|
-
function
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2420
|
+
function EffectBox({
|
|
2421
|
+
render,
|
|
2422
|
+
alwaysFrame,
|
|
2423
|
+
animationToken,
|
|
2424
|
+
children
|
|
2425
|
+
}) {
|
|
2426
|
+
const [reported, setReported] = useState(NO_GEOMETRY);
|
|
2427
|
+
const [needsFrame, setNeedsFrame] = useState(alwaysFrame);
|
|
2428
|
+
let readFrame = false;
|
|
2429
|
+
const style = render(reported, () => {
|
|
2430
|
+
readFrame = true;
|
|
2431
|
+
});
|
|
2432
|
+
useEffect(() => {
|
|
2433
|
+
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2434
|
+
});
|
|
2435
|
+
let content = Object.keys(style).length > 0 ? sb("styled", { style }, void 0, children) : children;
|
|
2436
|
+
if (animationToken) content = sb("styled", { style: { animation: { type: "default" }, animationToken: animationToken(reported) } }, void 0, content);
|
|
2437
|
+
return sb(
|
|
2438
|
+
"zstack",
|
|
2439
|
+
{ alignment: "center", reportsSize: true, ...needsFrame ? { reportsFrame: true } : {} },
|
|
2440
|
+
{
|
|
2441
|
+
geometry: (event) => {
|
|
2442
|
+
const next = nextGeometry(event, reported);
|
|
2443
|
+
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2444
|
+
}
|
|
2445
|
+
},
|
|
2446
|
+
content
|
|
1988
2447
|
);
|
|
1989
2448
|
}
|
|
1990
|
-
function
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2449
|
+
function VisualEffectView({ effect, children }) {
|
|
2450
|
+
const spaces = useCoordinateSpaces();
|
|
2451
|
+
return /* @__PURE__ */ jsx(EffectBox, { alwaysFrame: false, render: (reported, markRead) => effectStyle(effect(EMPTY_EFFECT, geometryProxy(reported, spaces, markRead)).values), children });
|
|
2452
|
+
}
|
|
2453
|
+
const PHASES = {
|
|
2454
|
+
topLeading: { phase: "topLeading", value: -1, isIdentity: false },
|
|
2455
|
+
identity: { phase: "identity", value: 0, isIdentity: true },
|
|
2456
|
+
bottomTrailing: { phase: "bottomTrailing", value: 1, isIdentity: false }
|
|
2457
|
+
};
|
|
2458
|
+
function scrollProgress(reported, axis) {
|
|
2459
|
+
const view = reported.scrollView;
|
|
2460
|
+
const origin = reported.origin;
|
|
2461
|
+
if (!view || !origin) return 0;
|
|
2462
|
+
const horizontal = (axis ?? view.axis) === "horizontal";
|
|
2463
|
+
const start = horizontal ? origin.x : origin.y;
|
|
2464
|
+
const length = horizontal ? reported.size.width : reported.size.height;
|
|
2465
|
+
const viewStart = horizontal ? view.x : view.y;
|
|
2466
|
+
const viewEnd = viewStart + (horizontal ? view.width : view.height);
|
|
2467
|
+
if (length <= 0) return 0;
|
|
2468
|
+
if (start < viewStart) return -Math.min(1, (viewStart - start) / length);
|
|
2469
|
+
if (start + length > viewEnd) return Math.min(1, (start + length - viewEnd) / length);
|
|
2470
|
+
return 0;
|
|
2471
|
+
}
|
|
2472
|
+
function scrollTransitionValues(spec, progress) {
|
|
2473
|
+
const identity = spec.transition(EMPTY_EFFECT, PHASES.identity).values;
|
|
2474
|
+
const configuration = spec.configuration ?? "interactive";
|
|
2475
|
+
if (configuration === "identity" || progress === 0) return identity;
|
|
2476
|
+
const edge = spec.transition(EMPTY_EFFECT, progress < 0 ? PHASES.topLeading : PHASES.bottomTrailing).values;
|
|
2477
|
+
if (configuration === "animated") return edge;
|
|
2478
|
+
return interpolateEffects(identity, edge, Math.abs(progress));
|
|
2479
|
+
}
|
|
2480
|
+
function ScrollTransitionView({ spec, children }) {
|
|
2481
|
+
return /* @__PURE__ */ jsx(
|
|
2482
|
+
EffectBox,
|
|
2483
|
+
{
|
|
2484
|
+
alwaysFrame: true,
|
|
2485
|
+
render: (reported) => effectStyle(scrollTransitionValues(spec, scrollProgress(reported, spec.axis))),
|
|
2486
|
+
...spec.configuration === "animated" ? { animationToken: (reported) => Math.sign(scrollProgress(reported, spec.axis)) + 1 } : {},
|
|
2487
|
+
children
|
|
2488
|
+
}
|
|
2002
2489
|
);
|
|
2003
2490
|
}
|
|
2004
|
-
|
|
2005
|
-
const
|
|
2006
|
-
|
|
2007
|
-
|
|
2491
|
+
const r = (n) => {
|
|
2492
|
+
const v = Math.round(n * 100) / 100;
|
|
2493
|
+
return Object.is(v, -0) ? "0" : String(v);
|
|
2494
|
+
};
|
|
2495
|
+
class Path {
|
|
2496
|
+
parts = [];
|
|
2497
|
+
current = null;
|
|
2498
|
+
start = null;
|
|
2499
|
+
constructor(build) {
|
|
2500
|
+
build?.(this);
|
|
2501
|
+
}
|
|
2502
|
+
/** `Path(rect)` */
|
|
2503
|
+
static rect(rect) {
|
|
2504
|
+
return new Path().addRect(rect);
|
|
2505
|
+
}
|
|
2506
|
+
/** `Path(roundedRect:cornerRadius:)` */
|
|
2507
|
+
static roundedRect(rect, cornerRadius) {
|
|
2508
|
+
return new Path().addRoundedRect(rect, cornerRadius);
|
|
2509
|
+
}
|
|
2510
|
+
/** `Path(ellipseIn:)` */
|
|
2511
|
+
static ellipse(rect) {
|
|
2512
|
+
return new Path().addEllipse(rect);
|
|
2513
|
+
}
|
|
2514
|
+
move(to) {
|
|
2515
|
+
this.parts.push(`M${r(to.x)} ${r(to.y)}`);
|
|
2516
|
+
this.current = to;
|
|
2517
|
+
this.start = to;
|
|
2518
|
+
return this;
|
|
2519
|
+
}
|
|
2520
|
+
addLine(to) {
|
|
2521
|
+
if (!this.current) return this.move(to);
|
|
2522
|
+
this.parts.push(`L${r(to.x)} ${r(to.y)}`);
|
|
2523
|
+
this.current = to;
|
|
2524
|
+
return this;
|
|
2525
|
+
}
|
|
2526
|
+
addLines(points) {
|
|
2527
|
+
points.forEach((point, index) => index === 0 ? this.move(point) : this.addLine(point));
|
|
2528
|
+
return this;
|
|
2529
|
+
}
|
|
2530
|
+
addQuadCurve(to, control) {
|
|
2531
|
+
if (!this.current) this.move(control);
|
|
2532
|
+
this.parts.push(`Q${r(control.x)} ${r(control.y)} ${r(to.x)} ${r(to.y)}`);
|
|
2533
|
+
this.current = to;
|
|
2534
|
+
return this;
|
|
2535
|
+
}
|
|
2536
|
+
addCurve(to, control1, control2) {
|
|
2537
|
+
if (!this.current) this.move(control1);
|
|
2538
|
+
this.parts.push(`C${r(control1.x)} ${r(control1.y)} ${r(control2.x)} ${r(control2.y)} ${r(to.x)} ${r(to.y)}`);
|
|
2539
|
+
this.current = to;
|
|
2540
|
+
return this;
|
|
2541
|
+
}
|
|
2542
|
+
/**
|
|
2543
|
+
* `addArc(center:radius:startAngle:endAngle:clockwise:)`, angles in
|
|
2544
|
+
* degrees. As in SwiftUI's flipped coordinates, `clockwise: false` draws
|
|
2545
|
+
* clockwise on screen.
|
|
2546
|
+
*/
|
|
2547
|
+
addArc(center, radius, startAngle, endAngle, clockwise) {
|
|
2548
|
+
const rad = (deg) => deg * Math.PI / 180;
|
|
2549
|
+
const point = (deg) => ({ x: center.x + radius * Math.cos(rad(deg)), y: center.y + radius * Math.sin(rad(deg)) });
|
|
2550
|
+
const from = point(startAngle);
|
|
2551
|
+
if (this.current) this.addLine(from);
|
|
2552
|
+
else this.move(from);
|
|
2553
|
+
const sweepPositive = !clockwise;
|
|
2554
|
+
let delta = endAngle - startAngle;
|
|
2555
|
+
if (sweepPositive) while (delta < 0) delta += 360;
|
|
2556
|
+
else while (delta > 0) delta -= 360;
|
|
2557
|
+
if (Math.abs(delta) >= 360) {
|
|
2558
|
+
const half = point(startAngle + (sweepPositive ? 180 : -180));
|
|
2559
|
+
const flag = sweepPositive ? 1 : 0;
|
|
2560
|
+
this.parts.push(`A${r(radius)} ${r(radius)} 0 0 ${flag} ${r(half.x)} ${r(half.y)}`);
|
|
2561
|
+
this.parts.push(`A${r(radius)} ${r(radius)} 0 0 ${flag} ${r(from.x)} ${r(from.y)}`);
|
|
2562
|
+
this.current = from;
|
|
2563
|
+
return this;
|
|
2564
|
+
}
|
|
2565
|
+
const to = point(startAngle + delta);
|
|
2566
|
+
const large = Math.abs(delta) > 180 ? 1 : 0;
|
|
2567
|
+
this.parts.push(`A${r(radius)} ${r(radius)} 0 ${large} ${sweepPositive ? 1 : 0} ${r(to.x)} ${r(to.y)}`);
|
|
2568
|
+
this.current = to;
|
|
2569
|
+
return this;
|
|
2570
|
+
}
|
|
2571
|
+
addRect(rect) {
|
|
2572
|
+
this.move({ x: rect.x, y: rect.y });
|
|
2573
|
+
this.addLine({ x: rect.x + rect.width, y: rect.y });
|
|
2574
|
+
this.addLine({ x: rect.x + rect.width, y: rect.y + rect.height });
|
|
2575
|
+
this.addLine({ x: rect.x, y: rect.y + rect.height });
|
|
2576
|
+
return this.closeSubpath();
|
|
2577
|
+
}
|
|
2578
|
+
addRoundedRect(rect, cornerRadius) {
|
|
2579
|
+
const c = Math.max(0, Math.min(cornerRadius, rect.width / 2, rect.height / 2));
|
|
2580
|
+
if (c === 0) return this.addRect(rect);
|
|
2581
|
+
const { x, y, width: w, height: h } = rect;
|
|
2582
|
+
this.move({ x: x + c, y });
|
|
2583
|
+
this.addLine({ x: x + w - c, y });
|
|
2584
|
+
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + w)} ${r(y + c)}`);
|
|
2585
|
+
this.current = { x: x + w, y: y + c };
|
|
2586
|
+
this.addLine({ x: x + w, y: y + h - c });
|
|
2587
|
+
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + w - c)} ${r(y + h)}`);
|
|
2588
|
+
this.current = { x: x + w - c, y: y + h };
|
|
2589
|
+
this.addLine({ x: x + c, y: y + h });
|
|
2590
|
+
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x)} ${r(y + h - c)}`);
|
|
2591
|
+
this.current = { x, y: y + h - c };
|
|
2592
|
+
this.addLine({ x, y: y + c });
|
|
2593
|
+
this.parts.push(`A${r(c)} ${r(c)} 0 0 1 ${r(x + c)} ${r(y)}`);
|
|
2594
|
+
this.current = { x: x + c, y };
|
|
2595
|
+
return this.closeSubpath();
|
|
2596
|
+
}
|
|
2597
|
+
addEllipse(rect) {
|
|
2598
|
+
const rx = rect.width / 2;
|
|
2599
|
+
const ry = rect.height / 2;
|
|
2600
|
+
const cx = rect.x + rx;
|
|
2601
|
+
const cy = rect.y + ry;
|
|
2602
|
+
this.move({ x: cx + rx, y: cy });
|
|
2603
|
+
this.parts.push(`A${r(rx)} ${r(ry)} 0 0 1 ${r(cx - rx)} ${r(cy)}`);
|
|
2604
|
+
this.parts.push(`A${r(rx)} ${r(ry)} 0 0 1 ${r(cx + rx)} ${r(cy)}`);
|
|
2605
|
+
this.current = { x: cx + rx, y: cy };
|
|
2606
|
+
return this.closeSubpath();
|
|
2607
|
+
}
|
|
2608
|
+
addPath(path) {
|
|
2609
|
+
this.parts.push(path.svg());
|
|
2610
|
+
return this;
|
|
2611
|
+
}
|
|
2612
|
+
closeSubpath() {
|
|
2613
|
+
this.parts.push("Z");
|
|
2614
|
+
this.current = this.start;
|
|
2615
|
+
return this;
|
|
2616
|
+
}
|
|
2617
|
+
get isEmpty() {
|
|
2618
|
+
return this.parts.length === 0;
|
|
2619
|
+
}
|
|
2620
|
+
/** The SVG path data. */
|
|
2621
|
+
svg() {
|
|
2622
|
+
return this.parts.join("");
|
|
2623
|
+
}
|
|
2624
|
+
toString() {
|
|
2625
|
+
return this.svg();
|
|
2626
|
+
}
|
|
2008
2627
|
}
|
|
2009
2628
|
function Button(props) {
|
|
2010
2629
|
const { own, modifiers } = splitProps(props);
|
|
@@ -2076,7 +2695,7 @@ function collectText(node) {
|
|
|
2076
2695
|
if (Array.isArray(node)) return node.map(collectText).join("");
|
|
2077
2696
|
if (typeof node === "object" && "props" in node) {
|
|
2078
2697
|
const element = node;
|
|
2079
|
-
if (element.type === Fragment
|
|
2698
|
+
if (element.type === Fragment || element.type === Text) return collectText(element.props.children);
|
|
2080
2699
|
}
|
|
2081
2700
|
return "";
|
|
2082
2701
|
}
|
|
@@ -2089,11 +2708,11 @@ function Slider(props) {
|
|
|
2089
2708
|
const children = [];
|
|
2090
2709
|
if (own.label !== void 0 && !environment.labelsHidden) {
|
|
2091
2710
|
labels.push("label");
|
|
2092
|
-
children.push(/* @__PURE__ */ jsx(Fragment
|
|
2711
|
+
children.push(/* @__PURE__ */ jsx(Fragment, { children: own.label }, "label"));
|
|
2093
2712
|
}
|
|
2094
2713
|
if (own.minimumValueLabel !== void 0 || own.maximumValueLabel !== void 0) {
|
|
2095
2714
|
labels.push("min", "max");
|
|
2096
|
-
children.push(/* @__PURE__ */ jsx(Fragment
|
|
2715
|
+
children.push(/* @__PURE__ */ jsx(Fragment, { children: own.minimumValueLabel }, "min"), /* @__PURE__ */ jsx(Fragment, { children: own.maximumValueLabel }, "max"));
|
|
2097
2716
|
}
|
|
2098
2717
|
return applyModifiers(
|
|
2099
2718
|
sb("slider", { value, min, max, step: own.step ?? null, labels }, { slide: (event) => setValue(event.value) }, children.length ? children : void 0),
|
|
@@ -2155,9 +2774,9 @@ function ProgressView(props) {
|
|
|
2155
2774
|
}
|
|
2156
2775
|
const label = own.label ?? own.children;
|
|
2157
2776
|
const children = [];
|
|
2158
|
-
if (label !== void 0 && label !== null) children.push(/* @__PURE__ */ jsx(Fragment
|
|
2777
|
+
if (label !== void 0 && label !== null) children.push(/* @__PURE__ */ jsx(Fragment, { children: label }, "label"));
|
|
2159
2778
|
if (own.currentValueLabel !== void 0 && own.currentValueLabel !== null) {
|
|
2160
|
-
children.push(/* @__PURE__ */ jsx(Fragment
|
|
2779
|
+
children.push(/* @__PURE__ */ jsx(Fragment, { children: styled({ foreground: { hierarchical: 2 } }, own.currentValueLabel) }, "current"));
|
|
2161
2780
|
}
|
|
2162
2781
|
return applyModifiers(
|
|
2163
2782
|
sb(
|
|
@@ -2203,127 +2822,6 @@ function TextEditor(props) {
|
|
|
2203
2822
|
function buttonDisabled(modifiers) {
|
|
2204
2823
|
return modifiers.some(([key, value]) => key === "disabled" && value === true);
|
|
2205
2824
|
}
|
|
2206
|
-
const isPushedView = (value) => typeof value === "object" && value !== null && "view" in value && Object.keys(value).length === 1;
|
|
2207
|
-
function NavigationStack(props) {
|
|
2208
|
-
const enclosing = useNavigation();
|
|
2209
|
-
if (enclosing) return /* @__PURE__ */ jsx(FlattenedStack, { ...props });
|
|
2210
|
-
return /* @__PURE__ */ jsx(OwnStack, { ...props });
|
|
2211
|
-
}
|
|
2212
|
-
function FlattenedStack(props) {
|
|
2213
|
-
const { own, modifiers } = splitProps(props);
|
|
2214
|
-
return applyModifiers(
|
|
2215
|
-
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2216
|
-
own.destination && /* @__PURE__ */ jsx(RegisterDestination, { destination: own.destination }),
|
|
2217
|
-
own.children
|
|
2218
|
-
] }),
|
|
2219
|
-
modifiers
|
|
2220
|
-
);
|
|
2221
|
-
}
|
|
2222
|
-
function OwnStack(props) {
|
|
2223
|
-
const { own, modifiers } = splitProps(props);
|
|
2224
|
-
const [internalPath, setInternalPath] = useState([]);
|
|
2225
|
-
const [path, setPath] = own.path !== void 0 ? readBinding(own.path, own.onPathChange) : [internalPath, setInternalPath];
|
|
2226
|
-
const destination = useRef(null);
|
|
2227
|
-
destination.current = own.destination ?? null;
|
|
2228
|
-
const context = {
|
|
2229
|
-
push: (value) => setPath([...path, value]),
|
|
2230
|
-
pop: () => setPath(path.slice(0, -1)),
|
|
2231
|
-
registerDestination: (builder) => {
|
|
2232
|
-
destination.current = builder;
|
|
2233
|
-
}
|
|
2234
|
-
};
|
|
2235
|
-
const screens = [
|
|
2236
|
-
/* @__PURE__ */ jsx(Fragment$1, { children: sb("navscreen", { title: "", displayMode: "automatic", depth: 0 }, { tap: context.pop }, own.children) }, "root")
|
|
2237
|
-
];
|
|
2238
|
-
path.forEach((value, index) => {
|
|
2239
|
-
const pop = () => setPath(path.slice(0, index));
|
|
2240
|
-
screens.push(
|
|
2241
|
-
/* @__PURE__ */ jsx(Fragment$1, { children: sb(
|
|
2242
|
-
"navscreen",
|
|
2243
|
-
{ title: "", displayMode: "automatic", depth: index + 1 },
|
|
2244
|
-
{ tap: pop },
|
|
2245
|
-
/* @__PURE__ */ jsx(DismissContext.Provider, { value: pop, children: /* @__PURE__ */ jsx(PathScreen, { value, destination }) })
|
|
2246
|
-
) }, index + 1)
|
|
2247
|
-
);
|
|
2248
|
-
});
|
|
2249
|
-
return applyModifiers(
|
|
2250
|
-
sb("navstack", {}, void 0, /* @__PURE__ */ jsx(NavigationContext.Provider, { value: context, children: screens })),
|
|
2251
|
-
modifiers
|
|
2252
|
-
);
|
|
2253
|
-
}
|
|
2254
|
-
function PathScreen({ value, destination }) {
|
|
2255
|
-
if (isPushedView(value)) return value.view;
|
|
2256
|
-
return destination.current ? destination.current(value) : null;
|
|
2257
|
-
}
|
|
2258
|
-
function NavigationLink(props) {
|
|
2259
|
-
const { own, modifiers } = splitProps(props);
|
|
2260
|
-
const navigation = useNavigation();
|
|
2261
|
-
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.children;
|
|
2262
|
-
const tap = () => {
|
|
2263
|
-
if (!navigation) return;
|
|
2264
|
-
if (own.destination !== void 0) navigation.push({ view: own.destination });
|
|
2265
|
-
else navigation.push(own.value);
|
|
2266
|
-
};
|
|
2267
|
-
return applyModifiers(sb("navlink", {}, { tap }, label), modifiers);
|
|
2268
|
-
}
|
|
2269
|
-
const SplitSelectionContext = createContext(null);
|
|
2270
|
-
function NavigationSplitView(props) {
|
|
2271
|
-
const { own, modifiers } = splitProps(props);
|
|
2272
|
-
const sizeClass = useHorizontalSizeClass();
|
|
2273
|
-
const [selected, setSelected] = useState(false);
|
|
2274
|
-
const clearRef = useRef(() => {
|
|
2275
|
-
});
|
|
2276
|
-
const report = {
|
|
2277
|
-
report: (nowSelected, clear2) => {
|
|
2278
|
-
clearRef.current = clear2;
|
|
2279
|
-
if (nowSelected !== selected) setSelected(nowSelected);
|
|
2280
|
-
}
|
|
2281
|
-
};
|
|
2282
|
-
const clear = () => clearRef.current();
|
|
2283
|
-
const [internal, setInternal] = useState("automatic");
|
|
2284
|
-
const [visibility, setVisibility] = own.columnVisibility !== void 0 ? readBinding(own.columnVisibility, own.onColumnVisibilityChange) : [internal, setInternal];
|
|
2285
|
-
if (sizeClass === "compact") {
|
|
2286
|
-
return applyModifiers(
|
|
2287
|
-
/* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children: /* @__PURE__ */ jsx(CompactSplit, { sidebar: own.sidebar, detail: own.detail, selected, clear }) }),
|
|
2288
|
-
modifiers
|
|
2289
|
-
);
|
|
2290
|
-
}
|
|
2291
|
-
const sidebarVisible = visibility !== "detailOnly";
|
|
2292
|
-
const toggle = () => withAnimation(() => setVisibility(sidebarVisible ? "detailOnly" : "all"));
|
|
2293
|
-
const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
|
|
2294
|
-
return applyModifiers(
|
|
2295
|
-
sb("navsplit", { sidebarVisible }, { tap: toggle }, [
|
|
2296
|
-
/* @__PURE__ */ jsx(SplitColumn, { report, children: /* @__PURE__ */ jsx(NavigationStack, { children: own.sidebar }) }, "sidebar"),
|
|
2297
|
-
/* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
|
|
2298
|
-
]),
|
|
2299
|
-
modifiers
|
|
2300
|
-
);
|
|
2301
|
-
}
|
|
2302
|
-
function SplitColumn({ report, children }) {
|
|
2303
|
-
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: report, children }) });
|
|
2304
|
-
}
|
|
2305
|
-
function CompactSplit({ sidebar, detail, selected, clear }) {
|
|
2306
|
-
const [extra, setExtra] = useState([]);
|
|
2307
|
-
const base = selected ? [{ view: /* @__PURE__ */ jsx(DetailScope, { children: detail }) }] : [];
|
|
2308
|
-
const path = [...base, ...extra];
|
|
2309
|
-
const setPath = (next) => {
|
|
2310
|
-
if (selected && next.length === 0) {
|
|
2311
|
-
setExtra([]);
|
|
2312
|
-
clear();
|
|
2313
|
-
return;
|
|
2314
|
-
}
|
|
2315
|
-
setExtra(next.slice(base.length));
|
|
2316
|
-
};
|
|
2317
|
-
return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(NavigationStack, { path: [path, setPath], children: sidebar }) });
|
|
2318
|
-
}
|
|
2319
|
-
function DetailScope({ children }) {
|
|
2320
|
-
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
2321
|
-
}
|
|
2322
|
-
function useReportSplitSelection(split, selected, clear) {
|
|
2323
|
-
useLayoutEffect(() => {
|
|
2324
|
-
split?.report(selected, clear);
|
|
2325
|
-
});
|
|
2326
|
-
}
|
|
2327
2825
|
const NO_CLEAR = () => {
|
|
2328
2826
|
};
|
|
2329
2827
|
function List(props) {
|
|
@@ -2354,10 +2852,13 @@ function List(props) {
|
|
|
2354
2852
|
}
|
|
2355
2853
|
};
|
|
2356
2854
|
}
|
|
2357
|
-
useReportSplitSelection(split, selected, clearSelection);
|
|
2855
|
+
useReportSplitSelection(split, selected, clearSelection, own.selection !== void 0);
|
|
2358
2856
|
const refresh = useRefreshable(takeModifier(modifiers, "refreshable"));
|
|
2359
2857
|
Object.assign(listProps, refresh.props);
|
|
2360
|
-
const
|
|
2858
|
+
const ownSettings = takeScrollSettings(modifiers);
|
|
2859
|
+
const edgeEffect = edgeEffectProp(useScrollSettings(ownSettings));
|
|
2860
|
+
if (edgeEffect) listProps["edgeEffect"] = edgeEffect;
|
|
2861
|
+
const element = /* @__PURE__ */ jsx(LazyContext.Provider, { value: "vertical", children: sb("list", listProps, refresh.handlers, providingScrollSettings(ownSettings, wrapRows(own.children))) });
|
|
2361
2862
|
return applyModifiers(
|
|
2362
2863
|
selection ? /* @__PURE__ */ jsx(ListSelectionContext.Provider, { value: selection, children: element }) : element,
|
|
2363
2864
|
modifiers
|
|
@@ -2543,11 +3044,11 @@ function Host(props) {
|
|
|
2543
3044
|
if (typeof document === "undefined") return null;
|
|
2544
3045
|
const element = document.createElement("div");
|
|
2545
3046
|
element.className = "sb-host-content";
|
|
2546
|
-
registerHostContent(key, element);
|
|
2547
3047
|
return element;
|
|
2548
3048
|
});
|
|
2549
3049
|
const bridge = useContextBridge(own.contexts);
|
|
2550
3050
|
const root = useRef(null);
|
|
3051
|
+
const mounted = useRef(false);
|
|
2551
3052
|
const sizing = own.sizing ?? "content";
|
|
2552
3053
|
const style = sizing === "fill" ? { height: "100%", ...own.style } : own.style;
|
|
2553
3054
|
const tree = bridge(
|
|
@@ -2555,6 +3056,8 @@ function Host(props) {
|
|
|
2555
3056
|
);
|
|
2556
3057
|
useLayoutEffect(() => {
|
|
2557
3058
|
if (!content) return;
|
|
3059
|
+
mounted.current = true;
|
|
3060
|
+
registerHostContent(key, content);
|
|
2558
3061
|
root.current ??= createRoot(content);
|
|
2559
3062
|
const current = root.current;
|
|
2560
3063
|
queueMicrotask(() => {
|
|
@@ -2565,175 +3068,26 @@ function Host(props) {
|
|
|
2565
3068
|
});
|
|
2566
3069
|
useEffect(
|
|
2567
3070
|
() => () => {
|
|
2568
|
-
|
|
2569
|
-
root.current = null;
|
|
3071
|
+
mounted.current = false;
|
|
2570
3072
|
unregisterHostContent(key);
|
|
2571
|
-
queueMicrotask(() =>
|
|
3073
|
+
queueMicrotask(() => {
|
|
3074
|
+
if (mounted.current) return;
|
|
3075
|
+
const current = root.current;
|
|
3076
|
+
root.current = null;
|
|
3077
|
+
current?.unmount();
|
|
3078
|
+
});
|
|
2572
3079
|
},
|
|
2573
3080
|
[key]
|
|
2574
3081
|
);
|
|
2575
3082
|
return applyModifiers(sb("host", { content: key, sizing }), modifiers);
|
|
2576
3083
|
}
|
|
2577
|
-
const NO_INSETS = { top: 0, leading: 0, bottom: 0, trailing: 0 };
|
|
2578
|
-
function GeometryReader(props) {
|
|
2579
|
-
const { own, modifiers } = splitProps(props);
|
|
2580
|
-
const [reported, setReported] = useState({ size: { width: 0, height: 0 }, origin: null, safeArea: NO_INSETS });
|
|
2581
|
-
const [needsFrame, setNeedsFrame] = useState(false);
|
|
2582
|
-
const spaces = useCoordinateSpaces();
|
|
2583
|
-
let readFrame = false;
|
|
2584
|
-
const proxy = {
|
|
2585
|
-
size: reported.size,
|
|
2586
|
-
frame: (space = "local") => {
|
|
2587
|
-
if (space === "local") return { x: 0, y: 0, ...reported.size };
|
|
2588
|
-
readFrame = true;
|
|
2589
|
-
const origin = reported.origin ?? { x: 0, y: 0 };
|
|
2590
|
-
if (space === "global") return { ...origin, ...reported.size };
|
|
2591
|
-
const named = spaces[space.named];
|
|
2592
|
-
return { x: origin.x - (named?.x ?? 0), y: origin.y - (named?.y ?? 0), ...reported.size };
|
|
2593
|
-
},
|
|
2594
|
-
get safeAreaInsets() {
|
|
2595
|
-
readFrame = true;
|
|
2596
|
-
return reported.safeArea;
|
|
2597
|
-
}
|
|
2598
|
-
};
|
|
2599
|
-
const content = own.children(proxy);
|
|
2600
|
-
useEffect(() => {
|
|
2601
|
-
if (readFrame && !needsFrame) setNeedsFrame(true);
|
|
2602
|
-
});
|
|
2603
|
-
return applyModifiers(
|
|
2604
|
-
sb(
|
|
2605
|
-
"geometry",
|
|
2606
|
-
needsFrame ? { reportsFrame: true } : {},
|
|
2607
|
-
{
|
|
2608
|
-
geometry: (event) => {
|
|
2609
|
-
const next = {
|
|
2610
|
-
size: { width: event.width, height: event.height },
|
|
2611
|
-
origin: event.x !== void 0 && event.y !== void 0 ? { x: event.x, y: event.y } : reported.origin,
|
|
2612
|
-
safeArea: event.safeArea ?? reported.safeArea
|
|
2613
|
-
};
|
|
2614
|
-
if (JSON.stringify(next) !== JSON.stringify(reported)) setReported(next);
|
|
2615
|
-
}
|
|
2616
|
-
},
|
|
2617
|
-
content
|
|
2618
|
-
),
|
|
2619
|
-
modifiers
|
|
2620
|
-
);
|
|
2621
|
-
}
|
|
2622
|
-
const DEFAULT_VIEW_SPACING = { distance: () => 8 };
|
|
2623
|
-
function subviewTraits(children) {
|
|
2624
|
-
return flattenChildren(children).map((element) => {
|
|
2625
|
-
const props = element.props;
|
|
2626
|
-
return { priority: props.layoutPriority ?? 0, values: props.layoutValue ?? {} };
|
|
2627
|
-
});
|
|
2628
|
-
}
|
|
2629
|
-
const fromDimension = (value) => value === "infinity" ? Infinity : value;
|
|
2630
|
-
const toDimension = (value) => Number.isFinite(value) ? Math.round(value * 100) / 100 : "infinity";
|
|
2631
|
-
const toSize = (size) => ({
|
|
2632
|
-
width: fromDimension(size.width) ?? 0,
|
|
2633
|
-
height: fromDimension(size.height) ?? 0
|
|
2634
|
-
});
|
|
2635
|
-
const GUIDES = ["leading", "horizontalCenter", "trailing", "top", "verticalCenter", "bottom", "firstTextBaseline", "lastTextBaseline"];
|
|
2636
|
-
function clamp(value, min, max) {
|
|
2637
|
-
return Math.min(Math.max(value, min), max);
|
|
2638
|
-
}
|
|
2639
|
-
function answerLayout(layout, record, traits = []) {
|
|
2640
|
-
const frames = record.children.map(() => null);
|
|
2641
|
-
const subviews = record.children.map((measurement, index) => {
|
|
2642
|
-
const min = toSize(measurement.min);
|
|
2643
|
-
const ideal = toSize(measurement.ideal);
|
|
2644
|
-
const max = toSize(measurement.max);
|
|
2645
|
-
const sizeThatFits = (proposal) => ({
|
|
2646
|
-
width: proposal.width === null ? ideal.width : clamp(proposal.width, min.width, max.width),
|
|
2647
|
-
height: proposal.height === null ? ideal.height : clamp(proposal.height, min.height, max.height)
|
|
2648
|
-
});
|
|
2649
|
-
return {
|
|
2650
|
-
min,
|
|
2651
|
-
ideal,
|
|
2652
|
-
max,
|
|
2653
|
-
priority: traits[index]?.priority ?? 0,
|
|
2654
|
-
values: traits[index]?.values ?? {},
|
|
2655
|
-
spacing: DEFAULT_VIEW_SPACING,
|
|
2656
|
-
sizeThatFits,
|
|
2657
|
-
place: ({ x, y, anchor, proposal }) => {
|
|
2658
|
-
const size2 = sizeThatFits(proposal ?? { width: null, height: null });
|
|
2659
|
-
const point = unitPoint(anchor ?? "topLeading");
|
|
2660
|
-
frames[index] = { x: x - point.x * size2.width, y: y - point.y * size2.height, ...size2 };
|
|
2661
|
-
}
|
|
2662
|
-
};
|
|
2663
|
-
});
|
|
2664
|
-
const cache = layout.makeCache ? layout.makeCache(subviews) : void 0;
|
|
2665
|
-
const measure = (proposal) => layout.sizeThatFits(proposal, subviews, cache);
|
|
2666
|
-
const size = measure(record.proposal);
|
|
2667
|
-
layout.placeSubviews({ x: 0, y: 0, ...size }, record.proposal, subviews, cache);
|
|
2668
|
-
const placed = frames.map((frame2, index) => {
|
|
2669
|
-
if (frame2) return frame2;
|
|
2670
|
-
const own = subviews[index].sizeThatFits({ width: size.width, height: size.height });
|
|
2671
|
-
return { x: (size.width - own.width) / 2, y: (size.height - own.height) / 2, ...own };
|
|
2672
|
-
});
|
|
2673
|
-
const guides = {};
|
|
2674
|
-
if (layout.explicitAlignment) {
|
|
2675
|
-
const bounds = { x: 0, y: 0, ...size };
|
|
2676
|
-
for (const guide of GUIDES) {
|
|
2677
|
-
const value = layout.explicitAlignment(guide, bounds, record.proposal, subviews, cache);
|
|
2678
|
-
if (value !== null && value !== void 0 && Number.isFinite(value)) guides[guide] = value;
|
|
2679
|
-
}
|
|
2680
|
-
}
|
|
2681
|
-
return {
|
|
2682
|
-
size,
|
|
2683
|
-
frames: placed,
|
|
2684
|
-
guides,
|
|
2685
|
-
sizes: {
|
|
2686
|
-
min: measure({ width: 0, height: 0 }),
|
|
2687
|
-
ideal: measure({ width: null, height: null }),
|
|
2688
|
-
max: measure({ width: Infinity, height: Infinity })
|
|
2689
|
-
}
|
|
2690
|
-
};
|
|
2691
|
-
}
|
|
2692
|
-
function Layout(props) {
|
|
2693
|
-
const { own, modifiers } = splitProps(props);
|
|
2694
|
-
const [record, setRecord] = useState(null);
|
|
2695
|
-
let layoutProps = { proposal: null, size: null, frames: null };
|
|
2696
|
-
const guideModifiers = [];
|
|
2697
|
-
if (record) {
|
|
2698
|
-
const answer = answerLayout(own.layout, record, subviewTraits(own.children));
|
|
2699
|
-
for (const [guide, value] of Object.entries(answer.guides)) guideModifiers.push(["alignmentGuide", { guide, value: () => value }]);
|
|
2700
|
-
const encode = (size) => ({ width: toDimension(size.width), height: toDimension(size.height) });
|
|
2701
|
-
const round = (value) => Math.round(value * 100) / 100;
|
|
2702
|
-
layoutProps = {
|
|
2703
|
-
proposal: {
|
|
2704
|
-
width: record.proposal.width === null ? null : toDimension(record.proposal.width),
|
|
2705
|
-
height: record.proposal.height === null ? null : toDimension(record.proposal.height)
|
|
2706
|
-
},
|
|
2707
|
-
size: { width: round(answer.size.width), height: round(answer.size.height) },
|
|
2708
|
-
frames: answer.frames.map((frame2) => ({ x: round(frame2.x), y: round(frame2.y), width: round(frame2.width), height: round(frame2.height) })),
|
|
2709
|
-
sizes: { min: encode(answer.sizes.min), ideal: encode(answer.sizes.ideal), max: encode(answer.sizes.max) }
|
|
2710
|
-
};
|
|
2711
|
-
}
|
|
2712
|
-
return applyModifiers(
|
|
2713
|
-
sb(
|
|
2714
|
-
"layout",
|
|
2715
|
-
layoutProps,
|
|
2716
|
-
{
|
|
2717
|
-
layout: (event) => {
|
|
2718
|
-
const proposal = event.proposal;
|
|
2719
|
-
setRecord({
|
|
2720
|
-
proposal: { width: fromDimension(proposal.width), height: fromDimension(proposal.height) },
|
|
2721
|
-
children: event.children
|
|
2722
|
-
});
|
|
2723
|
-
}
|
|
2724
|
-
},
|
|
2725
|
-
own.children
|
|
2726
|
-
),
|
|
2727
|
-
[...guideModifiers, ...modifiers]
|
|
2728
|
-
);
|
|
2729
|
-
}
|
|
2730
3084
|
function Menu(props) {
|
|
2731
3085
|
const { own, modifiers } = splitProps(props);
|
|
2732
3086
|
const label = own.title !== void 0 ? /* @__PURE__ */ jsx(Text, { children: own.title }) : own.label;
|
|
2733
3087
|
return applyModifiers(
|
|
2734
3088
|
sb("menu", {}, void 0, [
|
|
2735
|
-
/* @__PURE__ */ jsx(Fragment
|
|
2736
|
-
/* @__PURE__ */ jsx(Fragment
|
|
3089
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb("zstack", { alignment: "center" }, void 0, label) }, "label"),
|
|
3090
|
+
/* @__PURE__ */ jsx(Fragment, { children: own.children }, "items")
|
|
2737
3091
|
]),
|
|
2738
3092
|
modifiers
|
|
2739
3093
|
);
|
|
@@ -3006,9 +3360,9 @@ function Chart(props) {
|
|
|
3006
3360
|
}
|
|
3007
3361
|
const xScale = scaleFor(xValues, { domain: own.xScale?.domain });
|
|
3008
3362
|
const yScale = scaleFor(yValues, { includesZero: own.yScale?.includesZero ?? true, domain: own.yScale?.domain });
|
|
3009
|
-
const
|
|
3010
|
-
const ux = (v) =>
|
|
3011
|
-
const uy = (v) =>
|
|
3363
|
+
const round2 = (n) => Math.round(n * 1e6) / 1e6;
|
|
3364
|
+
const ux = (v) => round2(xScale.unit(v));
|
|
3365
|
+
const uy = (v) => round2(1 - yScale.unit(v));
|
|
3012
3366
|
let continuousBand = 1;
|
|
3013
3367
|
if (xScale.kind !== "band") {
|
|
3014
3368
|
const centers = [...new Set(marks.filter((m) => m.kind === "bar").map((m) => ux(m.props.x)))].sort((a, b) => a - b);
|
|
@@ -3020,7 +3374,7 @@ function Chart(props) {
|
|
|
3020
3374
|
const annotation = mark.props.annotation;
|
|
3021
3375
|
if (!annotation) return;
|
|
3022
3376
|
items.push(
|
|
3023
|
-
/* @__PURE__ */ jsx(Fragment
|
|
3377
|
+
/* @__PURE__ */ jsx(Fragment, { children: sb(
|
|
3024
3378
|
"chartitem",
|
|
3025
3379
|
{
|
|
3026
3380
|
role: "annotation",
|
|
@@ -3054,15 +3408,15 @@ function Chart(props) {
|
|
|
3054
3408
|
case "bar": {
|
|
3055
3409
|
const style = common(mark);
|
|
3056
3410
|
const [b0, b1] = xScale.kind === "band" ? xScale.band(p.x) : [ux(p.x) - continuousBand / 2, ux(p.x) + continuousBand / 2];
|
|
3057
|
-
const center =
|
|
3058
|
-
const half =
|
|
3411
|
+
const center = round2((b0 + b1) / 2);
|
|
3412
|
+
const half = round2((b1 - b0) * 0.8 / 2);
|
|
3059
3413
|
const top = uy(Math.max(asNumber(p.y), p.yStart ?? 0));
|
|
3060
3414
|
const bottom = uy(Math.min(asNumber(p.y), p.yStart ?? 0));
|
|
3061
3415
|
const rect = {
|
|
3062
3416
|
kind: "rect",
|
|
3063
3417
|
...style,
|
|
3064
|
-
x0: p.width !== void 0 ? center :
|
|
3065
|
-
x1: p.width !== void 0 ? center :
|
|
3418
|
+
x0: p.width !== void 0 ? center : round2(center - half),
|
|
3419
|
+
x1: p.width !== void 0 ? center : round2(center + half),
|
|
3066
3420
|
y0: top,
|
|
3067
3421
|
y1: bottom,
|
|
3068
3422
|
cornerRadius: p.cornerRadius ?? 0,
|
|
@@ -3133,7 +3487,7 @@ function Chart(props) {
|
|
|
3133
3487
|
}
|
|
3134
3488
|
}
|
|
3135
3489
|
const axis = (scale, position, flipY) => {
|
|
3136
|
-
const flip = (u) =>
|
|
3490
|
+
const flip = (u) => round2(flipY ? 1 - u : u);
|
|
3137
3491
|
return {
|
|
3138
3492
|
position,
|
|
3139
3493
|
gridLines: scale.gridLines.map(flip),
|
|
@@ -3158,8 +3512,8 @@ function Gauge(props) {
|
|
|
3158
3512
|
const value = (own.value - min) / (max - min || 1);
|
|
3159
3513
|
const children = [];
|
|
3160
3514
|
const asView = (node) => typeof node === "string" || typeof node === "number" ? /* @__PURE__ */ jsx(Text, { children: node }) : node;
|
|
3161
|
-
if (own.label !== void 0) children.push(/* @__PURE__ */ jsx(Fragment
|
|
3162
|
-
if (own.currentValueLabel !== void 0) children.push(/* @__PURE__ */ jsx(Fragment
|
|
3515
|
+
if (own.label !== void 0) children.push(/* @__PURE__ */ jsx(Fragment, { children: asView(own.label) }, "label"));
|
|
3516
|
+
if (own.currentValueLabel !== void 0) children.push(/* @__PURE__ */ jsx(Fragment, { children: asView(own.currentValueLabel) }, "current"));
|
|
3163
3517
|
return applyModifiers(
|
|
3164
3518
|
sb(
|
|
3165
3519
|
"gauge",
|
|
@@ -3233,7 +3587,7 @@ function GroupBox(props) {
|
|
|
3233
3587
|
}
|
|
3234
3588
|
function ControlGroup(props) {
|
|
3235
3589
|
const { own, modifiers } = splitProps(props);
|
|
3236
|
-
return modifiers.length ? applyModifiers(/* @__PURE__ */ jsx(Fragment, { children: own.children }), modifiers) : own.children;
|
|
3590
|
+
return modifiers.length ? applyModifiers(/* @__PURE__ */ jsx(Fragment$1, { children: own.children }), modifiers) : own.children;
|
|
3237
3591
|
}
|
|
3238
3592
|
function DisclosureGroup(props) {
|
|
3239
3593
|
const { own, modifiers } = splitProps(props);
|
|
@@ -3567,10 +3921,10 @@ function Canvas(props) {
|
|
|
3567
3921
|
if (draw.scale.x !== 1 || draw.scale.y !== 1) view = styled({ scale: draw.scale }, view);
|
|
3568
3922
|
if (Math.abs(draw.rotation) > 1e-6) view = styled({ rotation: draw.rotation }, view);
|
|
3569
3923
|
if (draw.opacity !== 1) view = styled({ opacity: draw.opacity }, view);
|
|
3570
|
-
return /* @__PURE__ */ jsx(Fragment
|
|
3924
|
+
return /* @__PURE__ */ jsx(Fragment, { children: styled({ position: { x: draw.x, y: draw.y } }, view) }, index);
|
|
3571
3925
|
});
|
|
3572
3926
|
return applyModifiers(
|
|
3573
|
-
sb("zstack", { alignment: "topLeading" }, void 0, [/* @__PURE__ */ jsx(Fragment
|
|
3927
|
+
sb("zstack", { alignment: "topLeading" }, void 0, [/* @__PURE__ */ jsx(Fragment, { children: reader }, "canvas"), ...symbols]),
|
|
3574
3928
|
modifiers
|
|
3575
3929
|
);
|
|
3576
3930
|
}
|
|
@@ -3788,7 +4142,7 @@ function VideoPlayer(props) {
|
|
|
3788
4142
|
);
|
|
3789
4143
|
if (own.videoOverlay === void 0) return applyModifiers(video, modifiers);
|
|
3790
4144
|
return applyModifiers(
|
|
3791
|
-
sb("zstack", { alignment: "center" }, void 0, [/* @__PURE__ */ jsx(Fragment
|
|
4145
|
+
sb("zstack", { alignment: "center" }, void 0, [/* @__PURE__ */ jsx(Fragment, { children: video }, "video"), /* @__PURE__ */ jsx(Fragment, { children: own.videoOverlay }, "overlay")]),
|
|
3792
4146
|
modifiers
|
|
3793
4147
|
);
|
|
3794
4148
|
}
|
|
@@ -3948,6 +4302,7 @@ export {
|
|
|
3948
4302
|
Label,
|
|
3949
4303
|
LabeledContent,
|
|
3950
4304
|
Layout,
|
|
4305
|
+
LazyHGrid,
|
|
3951
4306
|
LazyHStack,
|
|
3952
4307
|
LazyVGrid,
|
|
3953
4308
|
LazyVStack,
|
|
@@ -3956,9 +4311,11 @@ export {
|
|
|
3956
4311
|
Link,
|
|
3957
4312
|
List,
|
|
3958
4313
|
Menu,
|
|
4314
|
+
NO_GEOMETRY,
|
|
3959
4315
|
NavigationLink,
|
|
3960
4316
|
NavigationSplitView,
|
|
3961
4317
|
NavigationStack,
|
|
4318
|
+
OutsideSplit,
|
|
3962
4319
|
Path,
|
|
3963
4320
|
PhaseAnimator,
|
|
3964
4321
|
Picker,
|
|
@@ -3994,6 +4351,7 @@ export {
|
|
|
3994
4351
|
VStack,
|
|
3995
4352
|
VideoPlayer,
|
|
3996
4353
|
ViewThatFits,
|
|
4354
|
+
VisualEffect,
|
|
3997
4355
|
ZStack,
|
|
3998
4356
|
answerLayout,
|
|
3999
4357
|
color,
|
|
@@ -4001,22 +4359,26 @@ export {
|
|
|
4001
4359
|
flattenChildren,
|
|
4002
4360
|
font,
|
|
4003
4361
|
frame,
|
|
4362
|
+
geometryProxy,
|
|
4004
4363
|
gradient,
|
|
4005
4364
|
hex,
|
|
4006
4365
|
insets,
|
|
4007
4366
|
keyframeValues,
|
|
4008
4367
|
mount,
|
|
4009
4368
|
moveItems,
|
|
4369
|
+
nextGeometry,
|
|
4010
4370
|
niceStep,
|
|
4011
4371
|
opacity,
|
|
4012
4372
|
openURL,
|
|
4013
4373
|
padding,
|
|
4014
4374
|
placeholder,
|
|
4015
4375
|
plainText,
|
|
4376
|
+
providingScrollSettings,
|
|
4016
4377
|
readBinding,
|
|
4017
4378
|
rgb,
|
|
4018
4379
|
shapeStyle,
|
|
4019
4380
|
system,
|
|
4381
|
+
takeScrollSettings,
|
|
4020
4382
|
timeTicks,
|
|
4021
4383
|
unitPoint,
|
|
4022
4384
|
useAVPlayer,
|