mirror of
https://github.com/logseq/logseq.git
synced 2026-02-01 22:47:36 +00:00
chore: remove silkhq components
This commit is contained in:
156
deps/shui/src/logseq/shui/silkhq.cljs
vendored
156
deps/shui/src/logseq/shui/silkhq.cljs
vendored
@@ -1,156 +0,0 @@
|
|||||||
(ns logseq.shui.silkhq
|
|
||||||
(:require [goog.object :refer [getValueByKeys] :as gobj]
|
|
||||||
[logseq.shui.util :refer [component-wrap] :as util]))
|
|
||||||
|
|
||||||
(goog-define NODETEST false)
|
|
||||||
|
|
||||||
(def silkhq-wrap
|
|
||||||
(partial component-wrap js/window.LSSilkhq))
|
|
||||||
|
|
||||||
(defn silkhq-get
|
|
||||||
[name]
|
|
||||||
(if NODETEST
|
|
||||||
#js {}
|
|
||||||
(let [path (util/get-path name)]
|
|
||||||
(some-> js/window.LSSilkhq (gobj/getValueByKeys (clj->js path))))))
|
|
||||||
|
|
||||||
(def fixed (silkhq-wrap "Fixed.Root"))
|
|
||||||
(def fixed-content (silkhq-wrap "Fixed.Content"))
|
|
||||||
|
|
||||||
(def scroll (silkhq-wrap "Scroll.Root"))
|
|
||||||
(def scroll-trigger (silkhq-wrap "Scroll.Trigger"))
|
|
||||||
(def scroll-content (silkhq-wrap "Scroll.Content"))
|
|
||||||
(def scroll-view (silkhq-wrap "Scroll.View"))
|
|
||||||
|
|
||||||
(def sheet (silkhq-wrap "Sheet.Root"))
|
|
||||||
(def sheet-bleeding-background (silkhq-wrap "Sheet.BleedingBackground"))
|
|
||||||
(def sheet-portal (silkhq-wrap "Sheet.Portal"))
|
|
||||||
(def sheet-handle (silkhq-wrap "Sheet.Handle"))
|
|
||||||
(def sheet-content (silkhq-wrap "Sheet.Content"))
|
|
||||||
(def sheet-title (silkhq-wrap "Sheet.Title"))
|
|
||||||
(def sheet-description (silkhq-wrap "Sheet.Description"))
|
|
||||||
(def sheet-trigger (silkhq-wrap "Sheet.Trigger"))
|
|
||||||
(def sheet-outlet (silkhq-wrap "Sheet.Outlet"))
|
|
||||||
(def sheet-backdrop (silkhq-wrap "Sheet.Backdrop"))
|
|
||||||
(def sheet-view (silkhq-wrap "Sheet.View"))
|
|
||||||
|
|
||||||
(def bottom-sheet (silkhq-wrap "BottomSheet.Root"))
|
|
||||||
(def bottom-sheet-portal (silkhq-wrap "BottomSheet.Portal"))
|
|
||||||
(def bottom-sheet-handle (silkhq-wrap "BottomSheet.Handle"))
|
|
||||||
(def bottom-sheet-content (silkhq-wrap "BottomSheet.Content"))
|
|
||||||
(def bottom-sheet-title (silkhq-wrap "BottomSheet.Title"))
|
|
||||||
(def bottom-sheet-description (silkhq-wrap "BottomSheet.Description"))
|
|
||||||
(def bottom-sheet-trigger (silkhq-wrap "BottomSheet.Trigger"))
|
|
||||||
(def bottom-sheet-outlet (silkhq-wrap "BottomSheet.Outlet"))
|
|
||||||
(def bottom-sheet-backdrop (silkhq-wrap "BottomSheet.Backdrop"))
|
|
||||||
(def bottom-sheet-view (silkhq-wrap "BottomSheet.View"))
|
|
||||||
|
|
||||||
(def depth-sheet (silkhq-wrap "SheetWithDepth.Root"))
|
|
||||||
(def depth-sheet-portal (silkhq-wrap "SheetWithDepth.Portal"))
|
|
||||||
(def depth-sheet-handle (silkhq-wrap "SheetWithDepth.Handle"))
|
|
||||||
(def depth-sheet-content (silkhq-wrap "SheetWithDepth.Content"))
|
|
||||||
(def depth-sheet-title (silkhq-wrap "SheetWithDepth.Title"))
|
|
||||||
(def depth-sheet-description (silkhq-wrap "SheetWithDepth.Description"))
|
|
||||||
(def depth-sheet-trigger (silkhq-wrap "SheetWithDepth.Trigger"))
|
|
||||||
(def depth-sheet-outlet (silkhq-wrap "SheetWithDepth.Outlet"))
|
|
||||||
(def depth-sheet-backdrop (silkhq-wrap "SheetWithDepth.Backdrop"))
|
|
||||||
(def depth-sheet-view (silkhq-wrap "SheetWithDepth.View"))
|
|
||||||
(def depth-sheet-stack (silkhq-wrap "SheetWithDepthStack.Root"))
|
|
||||||
(def depth-sheet-scenery-outlets
|
|
||||||
(silkhq-wrap "SheetWithDepthStack.SceneryOutlets" {:static? true}))
|
|
||||||
|
|
||||||
(def detent-sheet (silkhq-wrap "SheetWithDetent.Root"))
|
|
||||||
(def detent-sheet-portal (silkhq-wrap "SheetWithDetent.Portal"))
|
|
||||||
(def detent-sheet-handle (silkhq-wrap "SheetWithDetent.Handle"))
|
|
||||||
(def detent-sheet-content (silkhq-wrap "SheetWithDetent.Content"))
|
|
||||||
(def detent-sheet-title (silkhq-wrap "SheetWithDetent.Title"))
|
|
||||||
(def detent-sheet-description (silkhq-wrap "SheetWithDetent.Description"))
|
|
||||||
(def detent-sheet-trigger (silkhq-wrap "SheetWithDetent.Trigger"))
|
|
||||||
(def detent-sheet-outlet (silkhq-wrap "SheetWithDetent.Outlet"))
|
|
||||||
(def detent-sheet-backdrop (silkhq-wrap "SheetWithDetent.Backdrop"))
|
|
||||||
(def detent-sheet-view (silkhq-wrap "SheetWithDetent.View"))
|
|
||||||
(def detent-sheet-scroll (silkhq-wrap "SheetWithDetent.ScrollRoot"))
|
|
||||||
(def detent-sheet-scroll-content (silkhq-wrap "SheetWithDetent.ScrollContent"))
|
|
||||||
(def detent-sheet-scroll-view (silkhq-wrap "SheetWithDetent.ScrollView"))
|
|
||||||
|
|
||||||
(def stacking-sheet (silkhq-wrap "SheetWithStacking.Root"))
|
|
||||||
(def stacking-sheet-portal (silkhq-wrap "SheetWithStacking.Portal"))
|
|
||||||
(def stacking-sheet-handle (silkhq-wrap "SheetWithStacking.Handle"))
|
|
||||||
(def stacking-sheet-content (silkhq-wrap "SheetWithStacking.Content"))
|
|
||||||
(def stacking-sheet-title (silkhq-wrap "SheetWithStacking.Title"))
|
|
||||||
(def stacking-sheet-description (silkhq-wrap "SheetWithStacking.Description"))
|
|
||||||
(def stacking-sheet-trigger (silkhq-wrap "SheetWithStacking.Trigger"))
|
|
||||||
(def stacking-sheet-outlet (silkhq-wrap "SheetWithStacking.Outlet"))
|
|
||||||
(def stacking-sheet-backdrop (silkhq-wrap "SheetWithStacking.Backdrop"))
|
|
||||||
(def stacking-sheet-view (silkhq-wrap "SheetWithStacking.View"))
|
|
||||||
(def stacking-sheet-stack (silkhq-wrap "SheetWithStackingStack.Root"))
|
|
||||||
|
|
||||||
(def parallax-page (silkhq-wrap "ParallaxPage.Root"))
|
|
||||||
(def parallax-page-portal (silkhq-wrap "ParallaxPage.Portal"))
|
|
||||||
(def parallax-page-handle (silkhq-wrap "ParallaxPage.Handle"))
|
|
||||||
(def parallax-page-content (silkhq-wrap "ParallaxPage.Content"))
|
|
||||||
(def parallax-page-description (silkhq-wrap "ParallaxPage.Description"))
|
|
||||||
(def parallax-page-title (silkhq-wrap "ParallaxPage.Title"))
|
|
||||||
(def parallax-page-trigger (silkhq-wrap "ParallaxPage.Trigger"))
|
|
||||||
(def parallax-page-outlet (silkhq-wrap "ParallaxPage.Outlet"))
|
|
||||||
(def parallax-page-backdrop (silkhq-wrap "ParallaxPage.Backdrop"))
|
|
||||||
(def parallax-page-view (silkhq-wrap "ParallaxPage.View"))
|
|
||||||
(def parallax-page-view-portal (silkhq-wrap "ParallaxPage.ViewPortal"))
|
|
||||||
(def parallax-page-topbar-title (silkhq-wrap "ParallaxPage.TopBarTitle"))
|
|
||||||
(def parallax-page-topbar-portal (silkhq-wrap "ParallaxPage.TopBarTitlePortal"))
|
|
||||||
(def parallax-page-topbar-dismiss-trigger (silkhq-wrap "ParallaxPage.TopBarDismissTrigger"))
|
|
||||||
(def parallax-page-topbar-dismiss-trigger-portal (silkhq-wrap "ParallaxPage.TopBarDismissTriggerPortal"))
|
|
||||||
|
|
||||||
(def parallax-page-stack (silkhq-wrap "ParallaxPageStack.Root"))
|
|
||||||
(def parallax-page-stack-scenery-outlet (silkhq-wrap "ParallaxPageStack.SceneryOutlet"))
|
|
||||||
;; stack topbar components
|
|
||||||
(def parallax-page-stack-island (silkhq-wrap "ParallaxPageStack.IslandRoot"))
|
|
||||||
(def parallax-page-stack-island-content (silkhq-wrap "ParallaxPageStack.IslandContent"))
|
|
||||||
(def parallax-page-stack-topbar-dismiss-trigger-container (silkhq-wrap "ParallaxPageStack.TopBarDismissTriggerContainer"))
|
|
||||||
(def parallax-page-stack-topbar-title-outlet (silkhq-wrap "ParallaxPageStack.TopBarTitleOutlet"))
|
|
||||||
(def parallax-page-stack-topbar-title-container (silkhq-wrap "ParallaxPageStack.TopBarTitleContainer"))
|
|
||||||
|
|
||||||
(def page (silkhq-wrap "Page.Root"))
|
|
||||||
(def page-portal (silkhq-wrap "Page.Portal"))
|
|
||||||
(def page-handle (silkhq-wrap "Page.Handle"))
|
|
||||||
(def page-content (silkhq-wrap "Page.Content"))
|
|
||||||
(def page-title (silkhq-wrap "Page.Title"))
|
|
||||||
(def page-description (silkhq-wrap "Page.Description"))
|
|
||||||
(def page-trigger (silkhq-wrap "Page.Trigger"))
|
|
||||||
(def page-outlet (silkhq-wrap "Page.Outlet"))
|
|
||||||
(def page-backdrop (silkhq-wrap "Page.Backdrop"))
|
|
||||||
(def page-view (silkhq-wrap "Page.View"))
|
|
||||||
|
|
||||||
(def card-sheet (silkhq-wrap "CardSheet.Root"))
|
|
||||||
(def card-sheet-portal (silkhq-wrap "CardSheet.Portal"))
|
|
||||||
(def card-sheet-handle (silkhq-wrap "CardSheet.Handle"))
|
|
||||||
(def card-sheet-content (silkhq-wrap "CardSheet.Content"))
|
|
||||||
(def card-sheet-title (silkhq-wrap "CardSheet.Title"))
|
|
||||||
(def card-sheet-description (silkhq-wrap "CardSheet.Description"))
|
|
||||||
(def card-sheet-trigger (silkhq-wrap "CardSheet.Trigger"))
|
|
||||||
(def card-sheet-outlet (silkhq-wrap "CardSheet.Outlet"))
|
|
||||||
(def card-sheet-backdrop (silkhq-wrap "CardSheet.Backdrop"))
|
|
||||||
(def card-sheet-view (silkhq-wrap "CardSheet.View"))
|
|
||||||
|
|
||||||
(def sidebar-sheet (silkhq-wrap "Sidebar.Root"))
|
|
||||||
(def sidebar-sheet-portal (silkhq-wrap "Sidebar.Portal"))
|
|
||||||
(def sidebar-sheet-view (silkhq-wrap "Sidebar.View"))
|
|
||||||
(def sidebar-sheet-backdrop (silkhq-wrap "Sidebar.Backdrop"))
|
|
||||||
(def sidebar-sheet-content (silkhq-wrap "Sidebar.Content"))
|
|
||||||
(def sidebar-sheet-trigger (silkhq-wrap "Sidebar.Trigger"))
|
|
||||||
(def sidebar-sheet-handle (silkhq-wrap "Sidebar.Handle"))
|
|
||||||
(def sidebar-sheet-outlet (silkhq-wrap "Sidebar.Outlet"))
|
|
||||||
(def sidebar-sheet-title (silkhq-wrap "Sidebar.Title"))
|
|
||||||
(def sidebar-sheet-description (silkhq-wrap "Sidebar.Description"))
|
|
||||||
|
|
||||||
(def persistent-sheet (silkhq-wrap "PersistentSheetWithDetent.Root"))
|
|
||||||
(def persistent-sheet-portal (silkhq-wrap "PersistentSheetWithDetent.Portal"))
|
|
||||||
(def persistent-sheet-view (silkhq-wrap "PersistentSheetWithDetent.View"))
|
|
||||||
(def persistent-sheet-content (silkhq-wrap "PersistentSheetWithDetent.Content"))
|
|
||||||
(def persistent-sheet-trigger (silkhq-wrap "PersistentSheetWithDetent.Trigger"))
|
|
||||||
(def persistent-sheet-handle (silkhq-wrap "PersistentSheetWithDetent.Handle"))
|
|
||||||
(def persistent-sheet-retracted-content (silkhq-wrap "PersistentSheetWithDetent.RetractedContent"))
|
|
||||||
(def persistent-sheet-expanded-content (silkhq-wrap "PersistentSheetWithDetent.ExpandedContent"))
|
|
||||||
(def persistent-sheet-outlet (silkhq-wrap "PersistentSheetWithDetent.Outlet"))
|
|
||||||
(def persistent-sheet-title (silkhq-wrap "PersistentSheetWithDetent.Title"))
|
|
||||||
(def persistent-sheet-description (silkhq-wrap "PersistentSheetWithDetent.Description"))
|
|
||||||
@@ -6,8 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"watch:ui:examples": "parcel serve ./examples/index.html",
|
"watch:ui:examples": "parcel serve ./examples/index.html",
|
||||||
"build:ui:only": "parcel build --target ui",
|
"build:ui:only": "parcel build --target ui",
|
||||||
"build:silkhq:only": "parcel build --target silkhq",
|
"build:ui": "rm -rf .parcel-cache && yarn build:ui:only",
|
||||||
"build:ui": "rm -rf .parcel-cache && yarn build:ui:only && yarn build:silkhq:only",
|
|
||||||
"watch:storybook": "storybook dev -p 6006",
|
"watch:storybook": "storybook dev -p 6006",
|
||||||
"postinstall": "yarn build:ui"
|
"postinstall": "yarn build:ui"
|
||||||
},
|
},
|
||||||
@@ -33,7 +32,6 @@
|
|||||||
"@radix-ui/react-toggle": "^1.1.6",
|
"@radix-ui/react-toggle": "^1.1.6",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.7",
|
"@radix-ui/react-toggle-group": "^1.1.7",
|
||||||
"@radix-ui/react-tooltip": "^1.2.4",
|
"@radix-ui/react-tooltip": "^1.2.4",
|
||||||
"@silk-hq/components": "^0.9.10",
|
|
||||||
"aws-amplify": "^6.15.6",
|
"aws-amplify": "^6.15.6",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
@@ -101,14 +99,6 @@
|
|||||||
"react": false,
|
"react": false,
|
||||||
"react-dom": false
|
"react-dom": false
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"silkhq": {
|
|
||||||
"source": "src/silkhq/silkhq.ts",
|
|
||||||
"outputFormat": "global",
|
|
||||||
"includeNodeModules": {
|
|
||||||
"react": false,
|
|
||||||
"react-dom": false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
.BottomSheet-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.BottomSheet-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: auto;
|
|
||||||
min-height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.BottomSheet-bleedingBackground {
|
|
||||||
/* APPEARANCE */
|
|
||||||
border-radius: 24px;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.BottomSheet-handle {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
width: 50px;
|
|
||||||
height: 6px;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
border: 0;
|
|
||||||
border-radius: 9999px;
|
|
||||||
background-color: rgb(209, 213, 219);
|
|
||||||
|
|
||||||
/* INTERACTIVITY */
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import { Sheet } from "@silk-hq/components";
|
|
||||||
import "./BottomSheet.css";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type BottomSheetRootProps = Omit<SheetRootProps, "license"> & {
|
|
||||||
license?: SheetRootProps["license"];
|
|
||||||
};
|
|
||||||
|
|
||||||
const BottomSheetRoot = React.forwardRef<React.ElementRef<typeof Sheet.Root>, BottomSheetRootProps>(
|
|
||||||
({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root license="commercial" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
BottomSheetRoot.displayName = "BottomSheet.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const BottomSheetView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`BottomSheet-view ${className ?? ""}`.trim()}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
BottomSheetView.displayName = "BottomSheet.View";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const BottomSheetBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`BottomSheet-backdrop ${className ?? ""}`.trim()}
|
|
||||||
themeColorDimming="auto"
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
BottomSheetBackdrop.displayName = "BottomSheet.Backdrop";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const BottomSheetContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`BottomSheet-content ${className ?? ""}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<Sheet.BleedingBackground className="BottomSheet-bleedingBackground" />
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
BottomSheetContent.displayName = "BottomSheet.Content";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Handle
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const BottomSheetHandle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Handle>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Handle>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Handle
|
|
||||||
className={`BottomSheet-handle ${className ?? ""}`.trim()}
|
|
||||||
action="dismiss"
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
BottomSheetHandle.displayName = "BottomSheet.Handle";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const BottomSheetPortal = Sheet.Portal;
|
|
||||||
const BottomSheetTrigger = Sheet.Trigger;
|
|
||||||
const BottomSheetOutlet = Sheet.Outlet;
|
|
||||||
const BottomSheetTitle = Sheet.Title;
|
|
||||||
const BottomSheetDescription = Sheet.Description;
|
|
||||||
|
|
||||||
export const BottomSheet = {
|
|
||||||
Root: BottomSheetRoot,
|
|
||||||
Portal: BottomSheetPortal,
|
|
||||||
View: BottomSheetView,
|
|
||||||
Backdrop: BottomSheetBackdrop,
|
|
||||||
Content: BottomSheetContent,
|
|
||||||
Trigger: BottomSheetTrigger,
|
|
||||||
Handle: BottomSheetHandle,
|
|
||||||
Outlet: BottomSheetOutlet,
|
|
||||||
Title: BottomSheetTitle,
|
|
||||||
Description: BottomSheetDescription,
|
|
||||||
};
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
.Card-view {
|
|
||||||
--card-radius: 36px;
|
|
||||||
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Card-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: min(600px, calc(100% - 2 * 1rem));
|
|
||||||
height: auto;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
border-radius: var(--card-radius);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Sheet } from '@silk-hq/components'
|
|
||||||
import './Card.css'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type CardRootProps = Omit<SheetRootProps, 'license'> & {
|
|
||||||
license?: SheetRootProps['license'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const CardRoot = React.forwardRef<React.ElementRef<typeof Sheet.Root>, CardRootProps>(
|
|
||||||
({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root license="commercial" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
CardRoot.displayName = 'Card.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const CardView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`Card-view ${className ?? ''}`.trim()}
|
|
||||||
contentPlacement="center"
|
|
||||||
tracks="top"
|
|
||||||
enteringAnimationSettings={{
|
|
||||||
easing: 'spring',
|
|
||||||
stiffness: 260,
|
|
||||||
damping: 20,
|
|
||||||
mass: 1,
|
|
||||||
}}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
CardView.displayName = 'Card.View'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const CardBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`Card-backdrop ${className ?? ''}`.trim()}
|
|
||||||
travelAnimation={{
|
|
||||||
opacity: ({ progress }) => Math.min(0.4 * progress, 0.4),
|
|
||||||
}}
|
|
||||||
themeColorDimming="auto"
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
CardBackdrop.displayName = 'Card.Backdrop'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const CardContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`Card-content ${className ?? ''}`.trim()}
|
|
||||||
travelAnimation={{ scale: [0.8, 1] }}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
CardContent.displayName = 'Card.Content'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const CardPortal = Sheet.Portal
|
|
||||||
const CardTrigger = Sheet.Trigger
|
|
||||||
const CardHandle = Sheet.Handle
|
|
||||||
const CardOutlet = Sheet.Outlet
|
|
||||||
const CardTitle = Sheet.Title
|
|
||||||
const CardDescription = Sheet.Description
|
|
||||||
|
|
||||||
export const Card = {
|
|
||||||
Root: CardRoot,
|
|
||||||
Portal: CardPortal,
|
|
||||||
View: CardView,
|
|
||||||
Backdrop: CardBackdrop,
|
|
||||||
Content: CardContent,
|
|
||||||
Trigger: CardTrigger,
|
|
||||||
Handle: CardHandle,
|
|
||||||
Outlet: CardOutlet,
|
|
||||||
Title: CardTitle,
|
|
||||||
Description: CardDescription,
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
.Page-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Page-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Sheet } from '@silk-hq/components'
|
|
||||||
import './Page.css'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type PageRootProps = Omit<SheetRootProps, 'license'> & {
|
|
||||||
license?: SheetRootProps['license'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const PageRoot = React.forwardRef<React.ElementRef<typeof Sheet.Root>, PageRootProps>(
|
|
||||||
({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root license="commercial" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
PageRoot.displayName = 'Page.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PageView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`Page-view ${className ?? ''}`.trim()}
|
|
||||||
contentPlacement="right"
|
|
||||||
swipeOvershoot={false}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
PageView.displayName = 'Page.View'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PageBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`Page-backdrop ${className ?? ''}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
PageBackdrop.displayName = 'Page.Backdrop'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PageContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content className={`Page-content ${className ?? ''}`.trim()} {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
PageContent.displayName = 'Page.Content'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PagePortal = Sheet.Portal
|
|
||||||
const PageTrigger = Sheet.Trigger
|
|
||||||
const PageHandle = Sheet.Handle
|
|
||||||
const PageOutlet = Sheet.Outlet
|
|
||||||
const PageTitle = Sheet.Title
|
|
||||||
const PageDescription = Sheet.Description
|
|
||||||
|
|
||||||
export const Page = {
|
|
||||||
Root: PageRoot,
|
|
||||||
Portal: PagePortal,
|
|
||||||
View: PageView,
|
|
||||||
Backdrop: PageBackdrop,
|
|
||||||
Content: PageContent,
|
|
||||||
Trigger: PageTrigger,
|
|
||||||
Handle: PageHandle,
|
|
||||||
Outlet: PageOutlet,
|
|
||||||
Title: PageTitle,
|
|
||||||
Description: PageDescription,
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
/* Stack top bar elements */
|
|
||||||
|
|
||||||
.ParallaxPage-stackTopBarDismissTriggerContainer {
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ParallaxPage-stackTopBarTitleContainer {
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Page */
|
|
||||||
|
|
||||||
.ParallaxPage-view {
|
|
||||||
--header-height: 49px;
|
|
||||||
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's bottom UI */
|
|
||||||
/* Subtracting 1px to avoid sub-pixel gap in Safari */
|
|
||||||
height: calc(
|
|
||||||
var(--silk-100-lvh-dvh-pct) + 60px -
|
|
||||||
(env(safe-area-inset-top, 0px) + var(--header-height) + 1px)
|
|
||||||
);
|
|
||||||
top: calc(env(safe-area-inset-top, 0px) + var(--header-height) - 1px);
|
|
||||||
}
|
|
||||||
@media (min-width: 1000px) {
|
|
||||||
.ParallaxPage-view {
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) - var(--header-height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ParallaxPage-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Page top bar elements */
|
|
||||||
|
|
||||||
.ParallaxPage-topBarDismissTrigger {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
grid-area: 1 / 1;
|
|
||||||
align-self: center;
|
|
||||||
margin-left: -14px;
|
|
||||||
width: 36px;
|
|
||||||
height: 44px;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
border-radius: 12px;
|
|
||||||
outline-offset: -5px;
|
|
||||||
appearance: none;
|
|
||||||
border: none;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
/* INTERACTIVITY */
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
/* TRANSFORMATION */
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
padding: 0;
|
|
||||||
display: grid;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ParallaxPage-topBarDismissIcon {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
color: rgb(75, 85, 99);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ParallaxPage-topBarTitle {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
grid-area: 1 / 1;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
/* TEXT */
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 17.25px;
|
|
||||||
font-weight: 620;
|
|
||||||
color: rgb(31, 41, 55);
|
|
||||||
}
|
|
||||||
@@ -1,464 +0,0 @@
|
|||||||
import React, { createContext, useContext, useRef, useState } from 'react'
|
|
||||||
import { createComponentId, Island, Sheet, SheetStack } from '@silk-hq/components'
|
|
||||||
import './ParallaxPage.css'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Utils
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const setRefs = <T, >(...refs: (React.Ref<T> | undefined)[]): ((node: T) => void) => {
|
|
||||||
return (node: T) => {
|
|
||||||
refs.forEach((ref) => {
|
|
||||||
if (typeof ref === 'function') {
|
|
||||||
ref(node)
|
|
||||||
} else if (ref) {
|
|
||||||
// @ts-ignore - intentionally breaking the readonly nature for compatibility
|
|
||||||
ref.current = node
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Id
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPageExampleStackId = createComponentId()
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// StackRoot Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type ParallaxPageStackRootContextValue = {
|
|
||||||
pageContainer: HTMLElement | null;
|
|
||||||
setPageContainer: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
|
|
||||||
dismissTriggerContainerRef: React.RefObject<HTMLDivElement>;
|
|
||||||
topBarTitleContainerRef: React.RefObject<HTMLDivElement>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ParallaxPageStackRootContext = createContext<ParallaxPageStackRootContextValue | null>(null)
|
|
||||||
const useParallaxPageStackRootContext = () => {
|
|
||||||
const context = useContext(ParallaxPageStackRootContext)
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
'useParallaxPageStackRootContext must be used within a ParallaxPageStackRootContext'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// In this component, the stack root is designed to receive the
|
|
||||||
// parallax page Views.
|
|
||||||
|
|
||||||
const ParallaxPageStackRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetStack.Root>
|
|
||||||
>(({ componentId, ...restProps }, ref) => {
|
|
||||||
const [pageContainer, setPageContainer] = useState<HTMLElement | null>(null)
|
|
||||||
const dismissTriggerContainerRef = useRef<HTMLDivElement>(null)
|
|
||||||
const topBarTitleContainerRef = useRef<HTMLDivElement>(null)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ParallaxPageStackRootContext.Provider
|
|
||||||
value={{
|
|
||||||
pageContainer,
|
|
||||||
setPageContainer,
|
|
||||||
dismissTriggerContainerRef,
|
|
||||||
topBarTitleContainerRef,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SheetStack.Root
|
|
||||||
// Using a componentId to associate the SheetStack
|
|
||||||
// with the ParallaxPageStackIslandRoot
|
|
||||||
componentId={componentId ?? ParallaxPageExampleStackId}
|
|
||||||
{...restProps}
|
|
||||||
ref={setRefs(ref, setPageContainer)}
|
|
||||||
/>
|
|
||||||
</ParallaxPageStackRootContext.Provider>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageStackRoot.displayName = 'ParallaxPageStack.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Scenery Outlet
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// An outlet meant to wrap the content below the stack for the
|
|
||||||
// initial parallax effect.
|
|
||||||
|
|
||||||
const ParallaxPageStackSceneryOutlet = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Outlet>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetStack.Outlet>
|
|
||||||
>((props, ref) => {
|
|
||||||
return (
|
|
||||||
<SheetStack.Outlet
|
|
||||||
stackingAnimation={{
|
|
||||||
transformOrigin: '50% 0px',
|
|
||||||
translateX: ({ progress }) => (progress <= 1 ? progress * -80 + 'px' : '-80px'),
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageStackSceneryOutlet.displayName = 'ParallaxPageStack.SceneryOutlet'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Island Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// An Island meant to wrap the top bar, but which can be used
|
|
||||||
// elsewhere as well.
|
|
||||||
|
|
||||||
const ParallaxPageStackIslandRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Island.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Island.Root>
|
|
||||||
>(({ forComponent, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Island.Root
|
|
||||||
forComponent={forComponent ?? ParallaxPageExampleStackId}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageStackIslandRoot.displayName = 'ParallaxPageStack.IslandRoot'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Island Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPageStackIslandContent = Island.Content
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Top Bar Dismiss Trigger Container
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// A container meant to receive the parallax pages dismiss
|
|
||||||
// triggers in the top bar.
|
|
||||||
|
|
||||||
const ParallaxPageStackTopBarDismissTriggerContainer = ({
|
|
||||||
className,
|
|
||||||
...restProps
|
|
||||||
}: React.ComponentPropsWithoutRef<'div'>) => {
|
|
||||||
const { dismissTriggerContainerRef } = useParallaxPageStackRootContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`ParallaxPage-stackTopBarDismissTriggerContainer ${className ?? ''}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={dismissTriggerContainerRef}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ParallaxPageStackTopBarDismissTriggerContainer.displayName =
|
|
||||||
'ParallaxPageStack.TopBarDismissTriggerContainer'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Top Bar Title Outlet
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// An outlet meant to wrap the initial title of the top bar.
|
|
||||||
|
|
||||||
const ParallaxPageStackTopBarTitleOutlet = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Outlet>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetStack.Outlet>
|
|
||||||
>(({ stackingAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<SheetStack.Outlet
|
|
||||||
stackingAnimation={{
|
|
||||||
opacity: ({ progress }) => 0.75 - (1 / 0.75) * (progress - 0.25),
|
|
||||||
...stackingAnimation,
|
|
||||||
}}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageStackTopBarTitleOutlet.displayName = 'ParallaxPageStack.TopBarTitleOutlet'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Top Bar Title Container
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// A container meant to receive the parallax pages titles in the
|
|
||||||
// top bar.
|
|
||||||
|
|
||||||
const ParallaxPageStackTopBarTitleContainer = ({
|
|
||||||
className,
|
|
||||||
...restProps
|
|
||||||
}: React.ComponentPropsWithoutRef<'div'>) => {
|
|
||||||
const { topBarTitleContainerRef } = useParallaxPageStackRootContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`ParallaxPage-stackTopBarTitleContainer ${className ?? ''}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={topBarTitleContainerRef}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ParallaxPageStackTopBarTitleContainer.displayName = 'ParallaxPageStack.TopBarTitleContainer'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type ParallaxPageRootProps = Omit<SheetRootProps, 'license'> & {
|
|
||||||
license?: SheetRootProps['license'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const ParallaxPageRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Root>,
|
|
||||||
ParallaxPageRootProps
|
|
||||||
>((props, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root
|
|
||||||
license="commercial"
|
|
||||||
// By default, the Sheet will be associated with the
|
|
||||||
// closest SheetStack
|
|
||||||
forComponent="closest"
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageRoot.displayName = 'ParallaxPage.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View Portal
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// A portal that will render the View in the stack root by
|
|
||||||
// default.
|
|
||||||
|
|
||||||
const ParallaxPageViewPortal = (props: React.ComponentPropsWithoutRef<typeof Sheet.Portal>) => {
|
|
||||||
const { pageContainer } = useParallaxPageStackRootContext()
|
|
||||||
|
|
||||||
return <Sheet.Portal container={pageContainer as HTMLElement} {...props} />
|
|
||||||
}
|
|
||||||
ParallaxPageViewPortal.displayName = 'ParallaxPage.ViewPortal'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPageView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{ className, contentPlacement, swipeOvershoot, nativeEdgeSwipePrevention, ...restProps },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`ParallaxPage-view ${className ?? ''}`.trim()}
|
|
||||||
contentPlacement={contentPlacement ?? 'right'}
|
|
||||||
swipeOvershoot={swipeOvershoot ?? false}
|
|
||||||
nativeEdgeSwipePrevention={nativeEdgeSwipePrevention ?? true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ParallaxPageView.displayName = 'ParallaxPage.View'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPageBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ travelAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
travelAnimation={{ opacity: [0, 0.25], ...travelAnimation }}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
ParallaxPageBackdrop.displayName = 'ParallaxPage.Backdrop'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPageContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ stackingAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className="ParallaxPage-content"
|
|
||||||
stackingAnimation={{
|
|
||||||
translateX: ({ progress }) => (progress <= 1 ? progress * -80 + 'px' : '-80px'),
|
|
||||||
...stackingAnimation,
|
|
||||||
}}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageContent.displayName = 'ParallaxPage.Content'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Top Bar Dismiss Trigger Portal
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// A portal that will render the dismiss trigger in the top bar
|
|
||||||
// dismiss trigger container by default.
|
|
||||||
|
|
||||||
const ParallaxPageTopBarDismissTriggerPortal = ({
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.ComponentPropsWithoutRef<typeof Sheet.Portal>) => {
|
|
||||||
const { dismissTriggerContainerRef } = useParallaxPageStackRootContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.Portal container={dismissTriggerContainerRef.current as HTMLElement} {...props}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Portal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ParallaxPageTopBarDismissTriggerPortal.displayName = 'ParallaxPage.TopBarDismissTriggerPortal'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Top Bar Dismiss Trigger
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// The top bar dismiss trigger associated with the parallax page.
|
|
||||||
|
|
||||||
const ParallaxPageTopBarDismissTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Trigger>
|
|
||||||
>(({ className, action, travelAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Trigger
|
|
||||||
className={`ParallaxPage-topBarDismissTrigger ${className ?? ''}`.trim()}
|
|
||||||
action={action ?? 'dismiss'}
|
|
||||||
travelAnimation={{
|
|
||||||
visibility: 'visible',
|
|
||||||
opacity: ({ progress }) => (1 / 0.75) * (progress - 0.25),
|
|
||||||
...travelAnimation,
|
|
||||||
}}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
className="ParallaxPage-topBarDismissIcon"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"
|
|
||||||
clipRule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</Sheet.Trigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageTopBarDismissTrigger.displayName = 'ParallaxPage.TopBarDismissTrigger'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Top Bar Title Portal
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// A portal that will render the top bar title in the top bar
|
|
||||||
// title container by default.
|
|
||||||
|
|
||||||
const ParallaxPageTopBarTitlePortal = ({
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.ComponentPropsWithoutRef<typeof Sheet.Outlet>) => {
|
|
||||||
const { topBarTitleContainerRef } = useParallaxPageStackRootContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.Portal container={topBarTitleContainerRef.current as HTMLElement} {...props}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Portal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ParallaxPageTopBarTitlePortal.displayName = 'ParallaxPage.TopBarTitlePortal'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Top Bar Title
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// The top bar title associated with the parallax page.
|
|
||||||
|
|
||||||
const ParallaxPageTopBarTitle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Outlet>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Outlet>
|
|
||||||
>(({ className, travelAnimation, stackingAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Outlet
|
|
||||||
className={`ParallaxPage-topBarTitle ${className ?? ''}`.trim()}
|
|
||||||
travelAnimation={{
|
|
||||||
opacity: ({ progress }) => (1 / 0.75) * (progress - 0.25),
|
|
||||||
...travelAnimation,
|
|
||||||
}}
|
|
||||||
stackingAnimation={{
|
|
||||||
opacity: ({ progress }) => 0.75 - (1 / 0.75) * (progress - 0.25),
|
|
||||||
...stackingAnimation,
|
|
||||||
}}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ParallaxPageTopBarTitle.displayName = 'ParallaxPage.TopBarTitle'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ParallaxPagePortal = Sheet.Portal
|
|
||||||
const ParallaxPageTrigger = Sheet.Trigger
|
|
||||||
const ParallaxPageHandle = Sheet.Handle
|
|
||||||
const ParallaxPageOutlet = Sheet.Outlet
|
|
||||||
const ParallaxPageTitle = Sheet.Title
|
|
||||||
const ParallaxPageDescription = Sheet.Description
|
|
||||||
|
|
||||||
export const ParallaxPageStack = {
|
|
||||||
// Stack
|
|
||||||
Root: ParallaxPageStackRoot,
|
|
||||||
SceneryOutlet: ParallaxPageStackSceneryOutlet,
|
|
||||||
// Stack top bar components
|
|
||||||
IslandRoot: ParallaxPageStackIslandRoot,
|
|
||||||
IslandContent: ParallaxPageStackIslandContent,
|
|
||||||
TopBarDismissTriggerContainer: ParallaxPageStackTopBarDismissTriggerContainer,
|
|
||||||
TopBarTitleOutlet: ParallaxPageStackTopBarTitleOutlet,
|
|
||||||
TopBarTitleContainer: ParallaxPageStackTopBarTitleContainer,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ParallaxPage = {
|
|
||||||
// Page
|
|
||||||
Root: ParallaxPageRoot,
|
|
||||||
ViewPortal: ParallaxPageViewPortal,
|
|
||||||
View: ParallaxPageView,
|
|
||||||
Backdrop: ParallaxPageBackdrop,
|
|
||||||
Content: ParallaxPageContent,
|
|
||||||
Trigger: ParallaxPageTrigger,
|
|
||||||
Handle: ParallaxPageHandle,
|
|
||||||
Outlet: ParallaxPageOutlet,
|
|
||||||
Portal: ParallaxPagePortal,
|
|
||||||
Title: ParallaxPageTitle,
|
|
||||||
Description: ParallaxPageDescription,
|
|
||||||
// Top Bar page components
|
|
||||||
TopBarDismissTriggerPortal: ParallaxPageTopBarDismissTriggerPortal,
|
|
||||||
TopBarDismissTrigger: ParallaxPageTopBarDismissTrigger,
|
|
||||||
TopBarTitlePortal: ParallaxPageTopBarTitlePortal,
|
|
||||||
TopBarTitle: ParallaxPageTopBarTitle,
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
.PersistentSheetWithDetent-customBackdrop {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: black;
|
|
||||||
|
|
||||||
/* INTERACTIVITY */
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
/* TRANSFORMATION */
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-themeColorDimmingController {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1;
|
|
||||||
top: -10px;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 10px;
|
|
||||||
background-color: rgba(63, 165, 225, 1);
|
|
||||||
box-shadow: 0 2px 6px -2px rgb(0, 0, 0, 0.25);
|
|
||||||
|
|
||||||
/* TRANSFORMATION */
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-view {
|
|
||||||
--retracted-height: 76px;
|
|
||||||
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 2;
|
|
||||||
bottom: -1px; /* Avoid subpixel misalignment in Safari */
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.PersistentSheetWithDetent-view.onDetent2-true {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
/* When resting on the detent 2, we switch the side the view is
|
|
||||||
anchored to to the top. It looks better when mobile browsers'
|
|
||||||
UI expand/collapse. */
|
|
||||||
bottom: initial;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 -2px 6px -2px rgb(0, 0, 0, 0.25);
|
|
||||||
background-color: rgba(63, 165, 225, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-innerContent {
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
position: relative;
|
|
||||||
padding-top: env(safe-area-inset-top, 0px);
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-retractedContent {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: var(--retracted-height);
|
|
||||||
}
|
|
||||||
|
|
||||||
.PersistentSheetWithDetent-expandedContent {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
place-self: stretch;
|
|
||||||
}
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import React, { useState, useRef, useCallback, useEffect, useMemo } from "react";
|
|
||||||
import { Sheet, useThemeColorDimmingOverlay } from "@silk-hq/components";
|
|
||||||
import "./PersistentSheetWithDetent.css";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Utils
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const setRefs = <T,>(...refs: (React.Ref<T> | undefined)[]): ((node: T) => void) => {
|
|
||||||
return (node: T) => {
|
|
||||||
refs.forEach((ref) => {
|
|
||||||
if (typeof ref === "function") {
|
|
||||||
ref(node);
|
|
||||||
} else if (ref) {
|
|
||||||
// @ts-ignore - intentionally breaking the readonly nature for compatibility
|
|
||||||
ref.current = node;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type PersistentSheetWithDetentContextValue = {
|
|
||||||
range: { start: number; end: number };
|
|
||||||
setRange: React.Dispatch<React.SetStateAction<{ start: number; end: number }>>;
|
|
||||||
backdropRef: React.RefObject<HTMLDivElement>;
|
|
||||||
themeColorDimmingControllerRef: React.RefObject<HTMLDivElement>;
|
|
||||||
rectractedContentRef: React.RefObject<HTMLDivElement>;
|
|
||||||
expandedContentRef: React.RefObject<HTMLDivElement>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentContext =
|
|
||||||
React.createContext<PersistentSheetWithDetentContextValue | null>(null);
|
|
||||||
|
|
||||||
const usePersistentSheetWithDetentContext = () => {
|
|
||||||
const context = React.useContext(PersistentSheetWithDetentContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"usePersistentSheetWithDetentContext must be used within a PersistentSheetWithDetentContextProvider"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type PersistentSheetWithDetentRootProps = Omit<SheetRootProps, "license"> & {
|
|
||||||
license?: SheetRootProps["license"];
|
|
||||||
};
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Root>,
|
|
||||||
PersistentSheetWithDetentRootProps
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
const [range, setRange] = useState({ start: 0, end: 0 });
|
|
||||||
const backdropRef = useRef<HTMLDivElement>(null);
|
|
||||||
const themeColorDimmingControllerRef = useRef<HTMLDivElement>(null);
|
|
||||||
const rectractedContentRef = useRef<HTMLDivElement>(null);
|
|
||||||
const expandedContentRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PersistentSheetWithDetentContext.Provider
|
|
||||||
value={{
|
|
||||||
range,
|
|
||||||
setRange,
|
|
||||||
backdropRef,
|
|
||||||
themeColorDimmingControllerRef,
|
|
||||||
rectractedContentRef,
|
|
||||||
expandedContentRef,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sheet.Root license="commercial" {...restProps} ref={ref}>
|
|
||||||
<Sheet.Portal>
|
|
||||||
{/* Using a custom backdrop because the real one's features are
|
|
||||||
not needed, and to be able to put it outside of the view */}
|
|
||||||
{range.end > 1 && (
|
|
||||||
<>
|
|
||||||
<Sheet.Outlet
|
|
||||||
className="PersistentSheetWithDetent-customBackdrop"
|
|
||||||
ref={backdropRef}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="PersistentSheetWithDetent-themeColorDimmingController"
|
|
||||||
ref={themeColorDimmingControllerRef}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Sheet.Portal>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
</PersistentSheetWithDetentContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PersistentSheetWithDetentRoot.displayName = "PersistentSheetWithDetent.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View> & {
|
|
||||||
dimmingColor?: string;
|
|
||||||
}
|
|
||||||
>(({ children, className, dimmingColor, onTravel, ...restProps }, ref) => {
|
|
||||||
const viewRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [inertOutside, setInertOutside] = useState(restProps.inertOutside);
|
|
||||||
|
|
||||||
const {
|
|
||||||
range,
|
|
||||||
setRange,
|
|
||||||
backdropRef,
|
|
||||||
themeColorDimmingControllerRef,
|
|
||||||
rectractedContentRef,
|
|
||||||
expandedContentRef,
|
|
||||||
} = usePersistentSheetWithDetentContext();
|
|
||||||
|
|
||||||
const rangeChangeHandler: NonNullable<
|
|
||||||
React.ComponentProps<typeof Sheet.View>["onTravelRangeChange"]
|
|
||||||
> = useCallback(
|
|
||||||
(newRange) => {
|
|
||||||
setRange(newRange);
|
|
||||||
setInertOutside(newRange.start === 2 && newRange.end === 2);
|
|
||||||
},
|
|
||||||
[setRange]
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Height setter
|
|
||||||
|
|
||||||
// We set the height only when the sheet is resting on a
|
|
||||||
// detent.
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const updateHeight = () => {
|
|
||||||
if (viewRef.current && range.start === range.end) {
|
|
||||||
const height = window.innerHeight;
|
|
||||||
viewRef.current.style.height = `${height + 1}px`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (range.start === range.end) {
|
|
||||||
updateHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
visualViewport?.addEventListener("resize", updateHeight);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
visualViewport?.removeEventListener("resize", updateHeight);
|
|
||||||
};
|
|
||||||
}, [range.start, range.end]);
|
|
||||||
|
|
||||||
useEffect(() => {setInertOutside(restProps.inertOutside)}, [restProps.inertOutside]);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Travel handler
|
|
||||||
|
|
||||||
// We use a travel handler instead of travel animations because
|
|
||||||
// it is not (yet) to define animation based on the progress
|
|
||||||
// during a specific range.
|
|
||||||
|
|
||||||
const { setDimmingOverlayOpacity } = useThemeColorDimmingOverlay({
|
|
||||||
elementRef: themeColorDimmingControllerRef,
|
|
||||||
dimmingColor: dimmingColor ?? "rgba(63, 165, 225, 1)",
|
|
||||||
});
|
|
||||||
|
|
||||||
const travelHandler: NonNullable<React.ComponentProps<typeof Sheet.View>["onTravel"]> =
|
|
||||||
useCallback(
|
|
||||||
(data) => {
|
|
||||||
if (typeof onTravel === 'function') {
|
|
||||||
onTravel(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const { progress, range, progressAtDetents } = data
|
|
||||||
if (!progressAtDetents) return;
|
|
||||||
|
|
||||||
if (range.end > 1) {
|
|
||||||
const normalisedProgress = (progress - progressAtDetents[1]) / (1 - progressAtDetents[1]);
|
|
||||||
|
|
||||||
setDimmingOverlayOpacity(normalisedProgress);
|
|
||||||
|
|
||||||
rectractedContentRef.current?.style.setProperty(
|
|
||||||
"opacity",
|
|
||||||
(1 - normalisedProgress) as unknown as string
|
|
||||||
);
|
|
||||||
backdropRef.current?.style.setProperty(
|
|
||||||
"opacity",
|
|
||||||
(normalisedProgress * 0.25) as unknown as string
|
|
||||||
);
|
|
||||||
expandedContentRef.current?.style.setProperty(
|
|
||||||
"opacity",
|
|
||||||
normalisedProgress as unknown as string
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setDimmingOverlayOpacity]
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return
|
|
||||||
|
|
||||||
const onDetent2 = useMemo(() => range.start === 2 && range.end === 2, [range.start, range.end]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
ref={setRefs(viewRef, ref)}
|
|
||||||
className={`PersistentSheetWithDetent-view onDetent2-${onDetent2} ${className ?? ""}`.trim()}
|
|
||||||
detents="max(env(safe-area-inset-bottom, 0px) - 10px + var(--retracted-height), var(--retracted-height))"
|
|
||||||
swipeOvershoot={false}
|
|
||||||
swipeDismissal={false}
|
|
||||||
onTravelRangeChange={rangeChangeHandler}
|
|
||||||
inertOutside={inertOutside}
|
|
||||||
onClickOutside={{ dismiss: range.end === 2 }}
|
|
||||||
onTravel={travelHandler}
|
|
||||||
nativeEdgeSwipePrevention={range.end !== 1}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PersistentSheetWithDetentView.displayName = "PersistentSheetWithDetent.View";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`PersistentSheetWithDetent-content ${className ?? ""}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<Sheet.SpecialWrapper.Root>
|
|
||||||
<Sheet.SpecialWrapper.Content>
|
|
||||||
<div className="PersistentSheetWithDetent-innerContent">{children}</div>
|
|
||||||
</Sheet.SpecialWrapper.Content>
|
|
||||||
</Sheet.SpecialWrapper.Root>
|
|
||||||
</Sheet.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PersistentSheetWithDetentContent.displayName = "PersistentSheetWithDetent.Content";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Retracted Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentRetractedContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.HTMLAttributes<HTMLDivElement>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const { range, rectractedContentRef } = usePersistentSheetWithDetentContext();
|
|
||||||
|
|
||||||
if (range.start >= 2) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`PersistentSheetWithDetent-retractedContent ${className ?? ""}`.trim()}
|
|
||||||
ref={setRefs(rectractedContentRef, ref)}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PersistentSheetWithDetentRetractedContent.displayName =
|
|
||||||
"PersistentSheetWithDetent.RetractedContent";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Expanded Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentExpandedContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.HTMLAttributes<HTMLDivElement>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const { range, expandedContentRef } = usePersistentSheetWithDetentContext();
|
|
||||||
|
|
||||||
if (range.end <= 1) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`PersistentSheetWithDetent-expandedContent ${className ?? ""}`.trim()}
|
|
||||||
ref={setRefs(expandedContentRef, ref)}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PersistentSheetWithDetentExpandedContent.displayName = "PersistentSheetWithDetent.ExpandedContent";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const PersistentSheetWithDetentPortal = Sheet.Portal;
|
|
||||||
const PersistentSheetWithDetentTrigger = Sheet.Trigger;
|
|
||||||
const PersistentSheetWithDetentHandle = Sheet.Handle;
|
|
||||||
const PersistentSheetWithOutlet = Sheet.Outlet;
|
|
||||||
const PersistentSheetWithTitle = Sheet.Title;
|
|
||||||
const PersistentSheetWithDescription = Sheet.Description;
|
|
||||||
|
|
||||||
export const PersistentSheetWithDetent = {
|
|
||||||
Root: PersistentSheetWithDetentRoot,
|
|
||||||
Portal: PersistentSheetWithDetentPortal,
|
|
||||||
View: PersistentSheetWithDetentView,
|
|
||||||
Content: PersistentSheetWithDetentContent,
|
|
||||||
Trigger: PersistentSheetWithDetentTrigger,
|
|
||||||
Handle: PersistentSheetWithDetentHandle,
|
|
||||||
RetractedContent: PersistentSheetWithDetentRetractedContent,
|
|
||||||
ExpandedContent: PersistentSheetWithDetentExpandedContent,
|
|
||||||
Outlet: PersistentSheetWithOutlet,
|
|
||||||
Title: PersistentSheetWithTitle,
|
|
||||||
Description: PersistentSheetWithDescription,
|
|
||||||
};
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/* Stack Scenery */
|
|
||||||
|
|
||||||
.SheetWithDepth-stackSceneryBackground {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: black;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
will-change: opacity;
|
|
||||||
}
|
|
||||||
.SheetWithDepth-stackSceneryBackground.nativePageScrollReplaced-true {
|
|
||||||
/* APPEARANCE */
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDepth-stackSceneryContainer {
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDepth-stackSceneryFirstSheetBackdrop {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
inset: 0;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: rgb(0, 0, 0);
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
/* INTERACTIVITY */
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
/* MISCELLANEOUS */
|
|
||||||
will-change: opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sheet */
|
|
||||||
|
|
||||||
.SheetWithDepth-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
top: 0;
|
|
||||||
bottom: initial;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's
|
|
||||||
bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDepth-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: calc(100% - max(calc(env(safe-area-inset-top) + 1.3vh), 2.6vh));
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDepth-bleedingBackground {
|
|
||||||
/* APPEARANCE */
|
|
||||||
border-radius: 24px 24px 0 0;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
}
|
|
||||||
@@ -1,434 +0,0 @@
|
|||||||
import React, {
|
|
||||||
createContext,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
import {
|
|
||||||
Sheet,
|
|
||||||
SheetStack,
|
|
||||||
animate,
|
|
||||||
useThemeColorDimmingOverlay,
|
|
||||||
usePageScrollData,
|
|
||||||
SheetViewProps,
|
|
||||||
createComponentId,
|
|
||||||
} from '@silk-hq/components'
|
|
||||||
import './SheetWithDepth.css'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Id
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const sheetWithDepthStackId = createComponentId()
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// StackRoot Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetWithDepthStackRootContextValue = {
|
|
||||||
stackBackgroundRef: React.RefObject<HTMLDivElement>;
|
|
||||||
stackFirstSheetBackdropRef: React.RefObject<HTMLDivElement>;
|
|
||||||
stackingCount: number;
|
|
||||||
setStackingCount: React.Dispatch<React.SetStateAction<number>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithDepthStackRootContext = createContext<SheetWithDepthStackRootContextValue | null>(
|
|
||||||
null
|
|
||||||
)
|
|
||||||
const useSheetWithDepthStackRootContext = () => {
|
|
||||||
const context = useContext(SheetWithDepthStackRootContext)
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
'useSheetWithDepthStackRootContext must be used within a SheetWithDepthStackRootContext'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDepthViewContext = createContext<{
|
|
||||||
indexInStack: number;
|
|
||||||
} | null>(null)
|
|
||||||
const useSheetWithDepthViewContext = () => {
|
|
||||||
const context = useContext(SheetWithDepthViewContext)
|
|
||||||
if (!context) {
|
|
||||||
throw new Error('useSheetWithDepthViewContext must be used within a SheetWithDepthViewContext')
|
|
||||||
}
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// StackRoot
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDepthStackRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Root>,
|
|
||||||
React.ComponentProps<typeof SheetStack.Root>
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
const stackBackgroundRef = useRef<HTMLDivElement | null>(null)
|
|
||||||
const stackFirstSheetBackdropRef = useRef<HTMLDivElement | null>(null)
|
|
||||||
|
|
||||||
const [stackingCount, setStackingCount] = useState(0)
|
|
||||||
|
|
||||||
const contextValue = useMemo(
|
|
||||||
() => ({
|
|
||||||
stackBackgroundRef,
|
|
||||||
stackFirstSheetBackdropRef,
|
|
||||||
stackingCount,
|
|
||||||
setStackingCount,
|
|
||||||
}),
|
|
||||||
[stackingCount]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SheetWithDepthStackRootContext.Provider value={contextValue}>
|
|
||||||
<SheetStack.Root componentId={sheetWithDepthStackId} {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</SheetStack.Root>
|
|
||||||
</SheetWithDepthStackRootContext.Provider>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SheetWithDepthStackRoot.displayName = 'SheetWithDepthStack.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// StackSceneryOutlets
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// The SheetStack outlets that define the scenery of the stack
|
|
||||||
// (i.e. the content underneath) for the depth effect.
|
|
||||||
|
|
||||||
const isIOS = window.navigator.userAgent?.match(/iPhone|iPad/i)
|
|
||||||
const initialTopOffset = isIOS ?
|
|
||||||
'max(env(safe-area-inset-top), 1.3vh)' : 'max(var(--safe-area-inset-top), 1.3vh)'
|
|
||||||
|
|
||||||
const SheetWithDepthStackSceneryOutlets = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Outlet>,
|
|
||||||
Omit<React.ComponentProps<typeof SheetStack.Outlet>, 'asChild'>
|
|
||||||
>(({ children, className, stackingAnimation: stackingAnimationFromProps, ...restProps }, ref) => {
|
|
||||||
const { stackBackgroundRef, stackFirstSheetBackdropRef } = useSheetWithDepthStackRootContext()
|
|
||||||
|
|
||||||
const { nativePageScrollReplaced } = usePageScrollData()
|
|
||||||
|
|
||||||
const [iOSStandalone, setiOSStandalone] = useState(false)
|
|
||||||
useEffect(() => {
|
|
||||||
setiOSStandalone(
|
|
||||||
// @ts-ignore
|
|
||||||
window.navigator.standalone && window.navigator.userAgent?.match(/iPhone|iPad/i)
|
|
||||||
)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const stackingAnimation: React.ComponentPropsWithoutRef<
|
|
||||||
typeof Sheet.Outlet
|
|
||||||
>['stackingAnimation'] = {
|
|
||||||
// Clipping & border-radius. We have a different animation
|
|
||||||
// when the native page scroll is replaced, and in iOS
|
|
||||||
// standalone mode.
|
|
||||||
...(nativePageScrollReplaced
|
|
||||||
? iOSStandalone
|
|
||||||
? // In iOS standalone mode we don't need to animate the
|
|
||||||
// border-radius because the corners are hidden by the
|
|
||||||
// screen corners. So we just set the border-radius to
|
|
||||||
// the needed value.
|
|
||||||
{
|
|
||||||
overflow: 'clip',
|
|
||||||
borderRadius: '24px',
|
|
||||||
transformOrigin: '50% 0',
|
|
||||||
}
|
|
||||||
: // Outside of iOS standalone mode we do animate
|
|
||||||
// the border-radius because the scenery is a visible
|
|
||||||
// rectangle.
|
|
||||||
{
|
|
||||||
overflow: 'clip',
|
|
||||||
borderRadius: ({ progress }: any) => Math.min(progress * 24, 24) + 'px',
|
|
||||||
transformOrigin: '50% 0',
|
|
||||||
}
|
|
||||||
: // When the native page scroll is not replaced we
|
|
||||||
// need to use the Silk's special clip properties to cut
|
|
||||||
// off the rest of the page.
|
|
||||||
{
|
|
||||||
clipBoundary: 'layout-viewport',
|
|
||||||
clipBorderRadius: '24px',
|
|
||||||
clipTransformOrigin: '50% 0',
|
|
||||||
}),
|
|
||||||
|
|
||||||
// Translate & scale
|
|
||||||
translateY: ({ progress }) =>
|
|
||||||
progress <= 1
|
|
||||||
? 'calc(' + progress + ' * ' + initialTopOffset + ')'
|
|
||||||
: // prettier-ignore
|
|
||||||
'calc(' + initialTopOffset + ' + 0.65vh * ' + (progress - 1) + ')',
|
|
||||||
scale: [1, 0.91],
|
|
||||||
|
|
||||||
// We merge animations coming from the props
|
|
||||||
...stackingAnimationFromProps,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Element used as a black background representing the void under the stack. */}
|
|
||||||
<div
|
|
||||||
className={`SheetWithDepth-stackSceneryBackground nativePageScrollReplaced-${nativePageScrollReplaced}`}
|
|
||||||
ref={stackBackgroundRef}
|
|
||||||
/>
|
|
||||||
{/* Element used as a container for the content under the stack. */}
|
|
||||||
<SheetStack.Outlet
|
|
||||||
className={`SheetWithDepth-stackSceneryContainer ${className ?? ''}`.trim()}
|
|
||||||
forComponent={sheetWithDepthStackId}
|
|
||||||
stackingAnimation={stackingAnimation}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
{/* Element used as the first sheet's backdrop, which only covers the stackSceneryContainer, not the entire viewport. */}
|
|
||||||
<div
|
|
||||||
className="SheetWithDepth-stackSceneryFirstSheetBackdrop"
|
|
||||||
ref={stackFirstSheetBackdropRef}
|
|
||||||
/>
|
|
||||||
</SheetStack.Outlet>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SheetWithDepthStackSceneryOutlets.displayName = 'SheetWithDepthStack.SceneryOutlets'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type SheetWithDepthRootProps = Omit<SheetRootProps, 'license'> & {
|
|
||||||
license?: SheetRootProps['license'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithDepthRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Root>,
|
|
||||||
SheetWithDepthRootProps
|
|
||||||
>((props, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root license="commercial" forComponent={sheetWithDepthStackId} {...props} ref={ref}/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SheetWithDepthRoot.displayName = 'SheetWithDepth.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
// We use animate(), animateDimmingOverlayOpacity() and the
|
|
||||||
// travelHandler instead of relying on stackingAnimation for the
|
|
||||||
// stackSceneryBackground and stackSceneryFirstSheetBackdrop
|
|
||||||
// elements in order to have a different (the default CSS
|
|
||||||
// "ease"), less abrupt animation easing for them.
|
|
||||||
|
|
||||||
const SheetWithDepthView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{ children, className, onTravelStatusChange, onTravel: travelHandlerFromProps, ...restProps },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const {
|
|
||||||
stackingCount,
|
|
||||||
setStackingCount,
|
|
||||||
|
|
||||||
stackBackgroundRef,
|
|
||||||
stackFirstSheetBackdropRef,
|
|
||||||
} = useSheetWithDepthStackRootContext()
|
|
||||||
|
|
||||||
const [indexInStack, setIndexInStack] = useState(0)
|
|
||||||
const [travelStatus, setTravelStatus] = useState('idleOutside')
|
|
||||||
|
|
||||||
//
|
|
||||||
// Define a dimming overlay
|
|
||||||
|
|
||||||
const { setDimmingOverlayOpacity, animateDimmingOverlayOpacity } = useThemeColorDimmingOverlay({
|
|
||||||
elementRef: stackBackgroundRef,
|
|
||||||
dimmingColor: 'rgb(0, 0, 0)',
|
|
||||||
})
|
|
||||||
|
|
||||||
//
|
|
||||||
// travelStatusChangeHandler
|
|
||||||
|
|
||||||
const travelStatusChangeHandler = useCallback<
|
|
||||||
NonNullable<SheetViewProps['onTravelStatusChange']>
|
|
||||||
>(
|
|
||||||
(newTravelStatus) => {
|
|
||||||
// Set indexInStack & stackingCount
|
|
||||||
if (travelStatus !== 'stepping' && newTravelStatus === 'idleInside') {
|
|
||||||
setStackingCount((prevStackingCount: number) => prevStackingCount + 1)
|
|
||||||
if (indexInStack === 0) {
|
|
||||||
setIndexInStack(stackingCount + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
else if (newTravelStatus === 'idleOutside') {
|
|
||||||
setStackingCount((prevStackingCount: number) => prevStackingCount - 1)
|
|
||||||
setIndexInStack(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Animate on entering
|
|
||||||
if (newTravelStatus === 'entering' && stackingCount === 0) {
|
|
||||||
animateDimmingOverlayOpacity({ keyframes: [0, 1] })
|
|
||||||
animate(stackFirstSheetBackdropRef.current as HTMLElement, {
|
|
||||||
opacity: [0, 0.33],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Animate on exiting
|
|
||||||
if (newTravelStatus === 'exiting' && stackingCount === 1) {
|
|
||||||
animateDimmingOverlayOpacity({ keyframes: [1, 0] })
|
|
||||||
animate(stackFirstSheetBackdropRef.current as HTMLElement, {
|
|
||||||
opacity: [0.33, 0],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the state
|
|
||||||
onTravelStatusChange?.(newTravelStatus)
|
|
||||||
setTravelStatus(newTravelStatus)
|
|
||||||
},
|
|
||||||
[
|
|
||||||
travelStatus,
|
|
||||||
indexInStack,
|
|
||||||
stackingCount,
|
|
||||||
setStackingCount,
|
|
||||||
stackFirstSheetBackdropRef,
|
|
||||||
animateDimmingOverlayOpacity,
|
|
||||||
onTravelStatusChange,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
//
|
|
||||||
// travelHandler
|
|
||||||
|
|
||||||
const travelHandler = useMemo(() => {
|
|
||||||
if (indexInStack === 1 && travelStatus !== 'entering' && travelStatus !== 'exiting') {
|
|
||||||
const handler: NonNullable<SheetViewProps['onTravel']> = ({ progress, ...rest }) => {
|
|
||||||
setDimmingOverlayOpacity(progress)
|
|
||||||
stackFirstSheetBackdropRef.current?.style.setProperty(
|
|
||||||
'opacity',
|
|
||||||
(progress * 0.33) as unknown as string
|
|
||||||
)
|
|
||||||
travelHandlerFromProps?.({ progress, ...rest })
|
|
||||||
}
|
|
||||||
return handler
|
|
||||||
} else {
|
|
||||||
return travelHandlerFromProps
|
|
||||||
}
|
|
||||||
}, [indexInStack, travelStatus, stackFirstSheetBackdropRef, setDimmingOverlayOpacity])
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SheetWithDepthViewContext.Provider value={{ indexInStack }}>
|
|
||||||
<Sheet.View
|
|
||||||
className={`SheetWithDepth-view ${className ?? ''}`.trim()}
|
|
||||||
contentPlacement="bottom"
|
|
||||||
onTravelStatusChange={travelStatusChangeHandler}
|
|
||||||
onTravel={travelHandler}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
</SheetWithDepthViewContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
SheetWithDepthView.displayName = 'SheetWithDepth.View'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDepthBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
// @ts-ignore
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
const { stackingCount } = useSheetWithDepthStackRootContext()
|
|
||||||
const { indexInStack } = useSheetWithDepthViewContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
// We don't render the Backdrop for the first sheet in the
|
|
||||||
// stack, instead we use the stackSceneryFirstSheetBackdrop
|
|
||||||
// element.
|
|
||||||
stackingCount > 0 &&
|
|
||||||
indexInStack !== 1 && (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`SheetWithDepth-backdrop ${className ?? ''}`.trim()}
|
|
||||||
travelAnimation={{ opacity: [0, 0.33] }}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SheetWithDepthBackdrop.displayName = 'SheetWithDepth.Backdrop'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDepthContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentProps<typeof Sheet.Content>
|
|
||||||
>(({ children, className, stackingAnimation, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`SheetWithDepth-content ${className ?? ''}`.trim()}
|
|
||||||
stackingAnimation={{
|
|
||||||
translateY: ({ progress }) =>
|
|
||||||
progress <= 1
|
|
||||||
? progress * -1.3 + 'vh'
|
|
||||||
: // prettier-ignore
|
|
||||||
'calc(-1.3vh + 0.65vh * ' + (progress - 1) + ')',
|
|
||||||
scale: [1, 0.91],
|
|
||||||
transformOrigin: '50% 0',
|
|
||||||
...stackingAnimation,
|
|
||||||
}}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<Sheet.BleedingBackground className="SheetWithDepth-bleedingBackground"/>
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SheetWithDepthContent.displayName = 'SheetWithDepth.Content'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDepthPortal = Sheet.Portal
|
|
||||||
const SheetWithDepthTrigger = Sheet.Trigger
|
|
||||||
const SheetWithDepthHandle = Sheet.Handle
|
|
||||||
const SheetWithDepthOutlet = Sheet.Outlet
|
|
||||||
const SheetWithDepthTitle = Sheet.Title
|
|
||||||
const SheetWithDepthDescription = Sheet.Description
|
|
||||||
|
|
||||||
export const SheetWithDepthStack = {
|
|
||||||
Root: SheetWithDepthStackRoot,
|
|
||||||
SceneryOutlets: SheetWithDepthStackSceneryOutlets,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SheetWithDepth = {
|
|
||||||
Root: SheetWithDepthRoot,
|
|
||||||
Portal: SheetWithDepthPortal,
|
|
||||||
View: SheetWithDepthView,
|
|
||||||
Content: SheetWithDepthContent,
|
|
||||||
Backdrop: SheetWithDepthBackdrop,
|
|
||||||
Trigger: SheetWithDepthTrigger,
|
|
||||||
Handle: SheetWithDepthHandle,
|
|
||||||
Outlet: SheetWithDepthOutlet,
|
|
||||||
Title: SheetWithDepthTitle,
|
|
||||||
Description: SheetWithDepthDescription,
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
.SheetWithDetent-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
top: 0;
|
|
||||||
bottom: initial;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's
|
|
||||||
bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDetent-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: calc(100% - max(env(safe-area-inset-top), 6px));
|
|
||||||
max-width: 800px;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
border-radius: 24px 24px 0 0;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
@media (min-width: 800px) {
|
|
||||||
.SheetWithDetent-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
height: calc(100% - max(env(safe-area-inset-top), 5vh));
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
border-radius: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithDetent-handle {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
width: 50px;
|
|
||||||
height: 6px;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
border: 0;
|
|
||||||
border-radius: 9999px;
|
|
||||||
background-color: rgb(209, 213, 219);
|
|
||||||
|
|
||||||
/* INTERACTIVITY */
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
import React, { createContext, useContext, useMemo, useRef, useState } from "react";
|
|
||||||
import { Sheet, Scroll, type SheetViewProps } from "@silk-hq/components";
|
|
||||||
import "./SheetWithDetent.css";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetWithDetentContextValue = {
|
|
||||||
reachedLastDetent: boolean;
|
|
||||||
setReachedLastDetent: React.Dispatch<React.SetStateAction<boolean>>;
|
|
||||||
viewRef: React.RefObject<HTMLElement>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithDetentContext = createContext<SheetWithDetentContextValue | null>(null);
|
|
||||||
|
|
||||||
const useSheetWithDetentContext = () => {
|
|
||||||
const context = useContext(SheetWithDetentContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useSheetWithDetentContext must be used within a SheetWithDetentContextProvider"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type SheetWithDetentRootProps = Omit<SheetRootProps, "license"> & {
|
|
||||||
license?: SheetRootProps["license"];
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithDetentRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Root>,
|
|
||||||
SheetWithDetentRootProps
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
const [reachedLastDetent, setReachedLastDetent] = useState(false);
|
|
||||||
const viewRef = useRef<HTMLElement>(null);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SheetWithDetentContext.Provider
|
|
||||||
value={{
|
|
||||||
reachedLastDetent,
|
|
||||||
setReachedLastDetent,
|
|
||||||
viewRef,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sheet.Root license="commercial" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
</SheetWithDetentContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentRoot.displayName = "SheetWithDetent.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{ children, className, onTravelStatusChange, onTravelRangeChange, onTravel, ...restProps },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const { reachedLastDetent, setReachedLastDetent, viewRef } = useSheetWithDetentContext();
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
const travelHandler = useMemo(() => {
|
|
||||||
if (!reachedLastDetent) return onTravel;
|
|
||||||
|
|
||||||
const handler: SheetViewProps["onTravel"] = ({ progress, ...rest }) => {
|
|
||||||
if (!viewRef.current) return onTravel?.({ progress, ...rest });
|
|
||||||
|
|
||||||
// Dismiss the on-screen keyboard.
|
|
||||||
if (progress < 0.999) {
|
|
||||||
viewRef.current.focus();
|
|
||||||
}
|
|
||||||
onTravel?.({ progress, ...rest });
|
|
||||||
};
|
|
||||||
return handler;
|
|
||||||
}, [reachedLastDetent, onTravel, viewRef]);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
const setRefs = React.useCallback((node: HTMLElement | null) => {
|
|
||||||
// @ts-ignore - intentionally breaking the readonly nature for compatibility
|
|
||||||
viewRef.current = node;
|
|
||||||
|
|
||||||
if (typeof ref === "function") {
|
|
||||||
ref(node);
|
|
||||||
} else if (ref) {
|
|
||||||
ref.current = node;
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`SheetWithDetent-view ${className ?? ""}`.trim()}
|
|
||||||
detents={!reachedLastDetent ? "66vh" : undefined}
|
|
||||||
swipeOvershoot={false}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
onTravelStatusChange={(travelStatus) => {
|
|
||||||
if (travelStatus === "idleOutside") setReachedLastDetent(false);
|
|
||||||
onTravelStatusChange?.(travelStatus);
|
|
||||||
}}
|
|
||||||
onTravelRangeChange={(range) => {
|
|
||||||
if (range.start === 2) setReachedLastDetent(true);
|
|
||||||
onTravelRangeChange?.(range);
|
|
||||||
}}
|
|
||||||
onTravel={travelHandler}
|
|
||||||
ref={setRefs}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
SheetWithDetentView.displayName = "SheetWithDetent.View";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`SheetWithDetent-backdrop ${className ?? ""}`.trim()}
|
|
||||||
themeColorDimming="auto"
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentBackdrop.displayName = "SheetWithDetent.Backdrop";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`SheetWithDetent-content ${className ?? ""}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentContent.displayName = "SheetWithDetent.Content";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Handle
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentHandle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Handle>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Handle>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
const { reachedLastDetent } = useSheetWithDetentContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.Handle
|
|
||||||
className={`SheetWithDetent-handle ${className ?? ""}`.trim()}
|
|
||||||
action={reachedLastDetent ? "dismiss" : "step"}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentHandle.displayName = "SheetWithDetent.Handle";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Scroll Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentScrollRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Scroll.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Scroll.Root>
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Scroll.Root {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Scroll.Root>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentScrollRoot.displayName = "SheetWithDetent.ScrollRoot";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Scroll View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentScrollView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Scroll.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Scroll.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const { reachedLastDetent } = useSheetWithDetentContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Scroll.View
|
|
||||||
className={`SheetWithDetent-scrollView ${className ?? ""}`.trim()}
|
|
||||||
scrollGestureTrap={{ yEnd: true }}
|
|
||||||
scrollGesture={!reachedLastDetent ? false : "auto"}
|
|
||||||
safeArea="layout-viewport"
|
|
||||||
onScrollStart={{ dismissKeyboard: true }}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Scroll.View>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentScrollView.displayName = "SheetWithDetent.ScrollView";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Scroll Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentScrollContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Scroll.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Scroll.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Scroll.Content
|
|
||||||
className={`SheetWithDetent-scrollContent ${className ?? ""}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Scroll.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithDetentScrollContent.displayName = "SheetWithDetent.ScrollContent";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithDetentPortal = Sheet.Portal;
|
|
||||||
const SheetWithDetentTrigger = Sheet.Trigger;
|
|
||||||
const SheetWithDetentOutlet = Sheet.Outlet;
|
|
||||||
const SheetWithDetentTitle = Sheet.Title;
|
|
||||||
const SheetWithDetentDescription = Sheet.Description;
|
|
||||||
|
|
||||||
export const SheetWithDetent = {
|
|
||||||
Root: SheetWithDetentRoot,
|
|
||||||
Portal: SheetWithDetentPortal,
|
|
||||||
View: SheetWithDetentView,
|
|
||||||
Backdrop: SheetWithDetentBackdrop,
|
|
||||||
Content: SheetWithDetentContent,
|
|
||||||
Trigger: SheetWithDetentTrigger,
|
|
||||||
Handle: SheetWithDetentHandle,
|
|
||||||
Outlet: SheetWithDetentOutlet,
|
|
||||||
Title: SheetWithDetentTitle,
|
|
||||||
Description: SheetWithDetentDescription,
|
|
||||||
//
|
|
||||||
ScrollRoot: SheetWithDetentScrollRoot,
|
|
||||||
ScrollView: SheetWithDetentScrollView,
|
|
||||||
ScrollContent: SheetWithDetentScrollContent,
|
|
||||||
};
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
.SheetWithStacking-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's
|
|
||||||
bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
.SheetWithStacking-view.contentPlacement-right {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
height: var(--silk-100-lvh-dvh-pct);
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithStacking-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: calc(min(500px, 90svh) + env(safe-area-inset-bottom, 0px));
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
padding-inline: 0.5rem;
|
|
||||||
padding-block: 0.5rem max(env(safe-area-inset-bottom, 0px), 0.5rem);
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
.SheetWithStacking-content.contentPlacement-right {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
height: 100%;
|
|
||||||
width: min(80%, 700px);
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.SheetWithStacking-innerContent {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
height: 100%;
|
|
||||||
min-height: 0;
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
overflow: hidden;
|
|
||||||
overflow: clip;
|
|
||||||
border-radius: 24px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
import React, { createContext, useContext } from "react";
|
|
||||||
import {
|
|
||||||
Sheet,
|
|
||||||
SheetStack,
|
|
||||||
useClientMediaQuery,
|
|
||||||
type SheetContentProps,
|
|
||||||
} from "@silk-hq/components";
|
|
||||||
import "./SheetWithStacking.css";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetWithStackingContextValue = {
|
|
||||||
travelStatus: string;
|
|
||||||
setTravelStatus: (status: string) => void;
|
|
||||||
contentPlacement: "right" | "bottom";
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithStackingContext = createContext<SheetWithStackingContextValue | null>(null);
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Stack Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithStackingStackRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetStack.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetStack.Root>
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<SheetStack.Root {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</SheetStack.Root>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithStackingStackRoot.displayName = "SheetWithStackingStack.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type SheetWithStackingRootProps = Omit<SheetRootProps, "license"> & {
|
|
||||||
license?: SheetRootProps["license"];
|
|
||||||
};
|
|
||||||
|
|
||||||
const SheetWithStackingRoot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Root>,
|
|
||||||
SheetWithStackingRootProps
|
|
||||||
>(({ children, ...restProps }, ref) => {
|
|
||||||
const [travelStatus, setTravelStatus] = React.useState("idleOutside");
|
|
||||||
const largeViewport = useClientMediaQuery("(min-width: 700px)");
|
|
||||||
const contentPlacement = largeViewport ? "right" : "bottom";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SheetWithStackingContext.Provider
|
|
||||||
value={{
|
|
||||||
travelStatus,
|
|
||||||
setTravelStatus,
|
|
||||||
contentPlacement,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sheet.Root license="commercial" forComponent="closest" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
</SheetWithStackingContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithStackingRoot.displayName = "SheetWithStacking.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithStackingView = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const context = useContext(SheetWithStackingContext);
|
|
||||||
if (!context)
|
|
||||||
throw new Error(
|
|
||||||
"SheetWithStackingView must be used within a SheetWithStackingContext.Provider"
|
|
||||||
);
|
|
||||||
const { setTravelStatus, contentPlacement } = context;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`SheetWithStacking-view contentPlacement-${contentPlacement} ${className ?? ""}`}
|
|
||||||
contentPlacement={contentPlacement}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
onTravelStatusChange={setTravelStatus}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithStackingView.displayName = "SheetWithStacking.View";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithStackingBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>((props, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
travelAnimation={{ opacity: [0, 0.2] }}
|
|
||||||
themeColorDimming="auto"
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithStackingBackdrop.displayName = "SheetWithStacking.Backdrop";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithStackingContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, stackingAnimation: stackingAnimationFromProps, ...restProps }, ref) => {
|
|
||||||
const context = useContext(SheetWithStackingContext);
|
|
||||||
if (!context)
|
|
||||||
throw new Error(
|
|
||||||
"SheetWithStackingContent must be used within a SheetWithStackingContext.Provider"
|
|
||||||
);
|
|
||||||
const { contentPlacement } = context;
|
|
||||||
|
|
||||||
const stackingAnimation: SheetContentProps["stackingAnimation"] =
|
|
||||||
contentPlacement === "right"
|
|
||||||
? {
|
|
||||||
translateX: ({ progress }: { progress: number }) =>
|
|
||||||
progress <= 1
|
|
||||||
? progress * -10 + "px"
|
|
||||||
: // prettier-ignore
|
|
||||||
"calc(-12.5px + 2.5px *" + progress + ")",
|
|
||||||
scale: [1, 0.933],
|
|
||||||
transformOrigin: "0 50%",
|
|
||||||
...stackingAnimationFromProps,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
translateY: ({ progress }: { progress: number }) =>
|
|
||||||
progress <= 1
|
|
||||||
? progress * -10 + "px"
|
|
||||||
: // prettier-ignore
|
|
||||||
"calc(-12.5px + 2.5px *" + progress + ")",
|
|
||||||
scale: [1, 0.933],
|
|
||||||
transformOrigin: "50% 0",
|
|
||||||
...stackingAnimationFromProps,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`SheetWithStacking-content contentPlacement-${contentPlacement} ${
|
|
||||||
className ?? ""
|
|
||||||
}`}
|
|
||||||
stackingAnimation={stackingAnimation}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<div className="SheetWithStacking-innerContent">{children}</div>
|
|
||||||
</Sheet.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SheetWithStackingContent.displayName = "SheetWithStacking.Content";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SheetWithStackingPortal = Sheet.Portal;
|
|
||||||
const SheetWithStackingTrigger = Sheet.Trigger;
|
|
||||||
const SheetWithStackingHandle = Sheet.Handle;
|
|
||||||
const SheetWithStackingOutlet = Sheet.Outlet;
|
|
||||||
const SheetWithStackingTitle = Sheet.Title;
|
|
||||||
const SheetWithStackingDescription = Sheet.Description;
|
|
||||||
|
|
||||||
export const SheetWithStackingStack = {
|
|
||||||
Root: SheetWithStackingStackRoot,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SheetWithStacking = {
|
|
||||||
Root: SheetWithStackingRoot,
|
|
||||||
View: SheetWithStackingView,
|
|
||||||
Portal: SheetWithStackingPortal,
|
|
||||||
Backdrop: SheetWithStackingBackdrop,
|
|
||||||
Content: SheetWithStackingContent,
|
|
||||||
Trigger: SheetWithStackingTrigger,
|
|
||||||
Handle: SheetWithStackingHandle,
|
|
||||||
Outlet: SheetWithStackingOutlet,
|
|
||||||
Title: SheetWithStackingTitle,
|
|
||||||
Description: SheetWithStackingDescription,
|
|
||||||
};
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
.Sidebar-view {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
z-index: 1;
|
|
||||||
/* Adding 60px to make it fully visible below iOS Safari's bottom UI */
|
|
||||||
height: calc(var(--silk-100-lvh-dvh-pct) + 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Sidebar-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: min(90vw, 325px);
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import React from "react";
|
|
||||||
import { Sheet, VisuallyHidden } from "@silk-hq/components";
|
|
||||||
import "./Sidebar.css";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type SidebarRootProps = Omit<SheetRootProps, "license"> & {
|
|
||||||
license?: SheetRootProps["license"];
|
|
||||||
};
|
|
||||||
|
|
||||||
const SidebarRoot = React.forwardRef<React.ElementRef<typeof Sheet.Root>, SidebarRootProps>(
|
|
||||||
({ children, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Root license="commercial" sheetRole="dialog" {...restProps} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
SidebarRoot.displayName = "Sidebar.Root";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SidebarView = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.View>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.View
|
|
||||||
className={`Sidebar-view ${className ?? ""}`.trim()}
|
|
||||||
contentPlacement="left"
|
|
||||||
swipeOvershoot={false}
|
|
||||||
nativeEdgeSwipePrevention={true}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarView.displayName = "Sidebar.View";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Backdrop
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SidebarBackdrop = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Backdrop>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Backdrop>
|
|
||||||
>(({ className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Backdrop
|
|
||||||
className={`Sidebar-backdrop ${className ?? ""}`.trim()}
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarBackdrop.displayName = "Sidebar.Backdrop";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SidebarContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<Sheet.Content className={`Sidebar-content ${className ?? ""}`.trim()} {...restProps} ref={ref}>
|
|
||||||
<VisuallyHidden.Root>
|
|
||||||
<Sheet.Title>Sidebar Example</Sheet.Title>
|
|
||||||
<Sheet.Trigger action="dismiss">Close Sidebar example</Sheet.Trigger>
|
|
||||||
</VisuallyHidden.Root>
|
|
||||||
{children}
|
|
||||||
</Sheet.Content>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarContent.displayName = "Sidebar.Content";
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const SidebarPortal = Sheet.Portal;
|
|
||||||
const SidebarTrigger = Sheet.Trigger;
|
|
||||||
const SidebarHandle = Sheet.Handle;
|
|
||||||
const SidebarOutlet = Sheet.Outlet;
|
|
||||||
const SidebarTitle = Sheet.Title;
|
|
||||||
const SidebarDescription = Sheet.Description;
|
|
||||||
|
|
||||||
export const Sidebar = {
|
|
||||||
Root: SidebarRoot,
|
|
||||||
Portal: SidebarPortal,
|
|
||||||
View: SidebarView,
|
|
||||||
Backdrop: SidebarBackdrop,
|
|
||||||
Content: SidebarContent,
|
|
||||||
Trigger: SidebarTrigger,
|
|
||||||
Handle: SidebarHandle,
|
|
||||||
Outlet: SidebarOutlet,
|
|
||||||
Title: SidebarTitle,
|
|
||||||
Description: SidebarDescription,
|
|
||||||
};
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
.Toast-container {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
position: fixed;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Toast-view {
|
|
||||||
--padding-x: 0.75rem;
|
|
||||||
--padding-top: 0.75rem;
|
|
||||||
--padding-bottom: 2.75rem;
|
|
||||||
--max-height: 90px;
|
|
||||||
--contentHeight: calc(
|
|
||||||
max(env(safe-area-inset-top, 0px), var(--padding-top)) + var(--max-height) +
|
|
||||||
var(--padding-bottom)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@media (min-width: 1000px) {
|
|
||||||
.Toast-view {
|
|
||||||
--padding-x: 0.875rem;
|
|
||||||
--padding-top: 0.875rem;
|
|
||||||
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
height: var(--contentHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Toast-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 560px;
|
|
||||||
height: var(--contentHeight);
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
padding: var(--padding-x);
|
|
||||||
padding-top: max(env(safe-area-inset-top), var(--padding-top));
|
|
||||||
padding-bottom: var(--padding-bottom);
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
@media (min-width: 1000px) {
|
|
||||||
.Toast-content {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
max-width: 400px;
|
|
||||||
|
|
||||||
/* INNER-LAYOUT */
|
|
||||||
padding-top: var(--padding-top);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Toast-innerContent {
|
|
||||||
/* SELF-LAYOUT */
|
|
||||||
max-height: var(--max-height);
|
|
||||||
|
|
||||||
/* APPEARANCE */
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
||||||
border-radius: 24px;
|
|
||||||
border: 1px solid rgb(240, 240, 240);
|
|
||||||
background-color: rgba(255, 255, 255, 0.95);
|
|
||||||
backdrop-filter: saturate(5) blur(20px);
|
|
||||||
}
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
import React, { useEffect, useState, useRef, createContext, useContext } from 'react'
|
|
||||||
import { Sheet, useClientMediaQuery } from '@silk-hq/components'
|
|
||||||
import './Toast.css'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Context
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type ToastContextValue = {
|
|
||||||
presented: boolean;
|
|
||||||
setPresented: (presented: boolean) => void;
|
|
||||||
pointerOver: boolean;
|
|
||||||
setPointerOver: (pointerOver: boolean) => void;
|
|
||||||
travelStatus: string;
|
|
||||||
setTravelStatus: (status: string) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ToastContext = createContext<ToastContextValue | null>(null)
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Root
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
type SheetRootProps = React.ComponentPropsWithoutRef<typeof Sheet.Root>;
|
|
||||||
type ToastRootProps = Omit<SheetRootProps, 'license'> & {
|
|
||||||
license?: SheetRootProps['license'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const ToastRoot = React.forwardRef<React.ElementRef<typeof Sheet.Root>, ToastRootProps>(
|
|
||||||
({ children, ...restProps }, ref) => {
|
|
||||||
const [presented, setPresented] = useState(false)
|
|
||||||
const [pointerOver, setPointerOver] = useState(false)
|
|
||||||
const [travelStatus, setTravelStatus] = useState('idleOutside')
|
|
||||||
const autoCloseTimeout = useRef<ReturnType<typeof setTimeout> | undefined>()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const startAutoCloseTimeout = () => {
|
|
||||||
autoCloseTimeout.current = setTimeout(() => setPresented(false), 5000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearAutoCloseTimeout = () => {
|
|
||||||
clearTimeout(autoCloseTimeout.current)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presented) {
|
|
||||||
if (travelStatus === 'idleInside' && !pointerOver) {
|
|
||||||
startAutoCloseTimeout()
|
|
||||||
} else {
|
|
||||||
clearAutoCloseTimeout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clearAutoCloseTimeout
|
|
||||||
}, [presented, travelStatus, pointerOver])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToastContext.Provider
|
|
||||||
value={{
|
|
||||||
presented,
|
|
||||||
setPresented,
|
|
||||||
pointerOver,
|
|
||||||
setPointerOver,
|
|
||||||
travelStatus,
|
|
||||||
setTravelStatus,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sheet.Root
|
|
||||||
license="commercial"
|
|
||||||
presented={presented}
|
|
||||||
onPresentedChange={setPresented}
|
|
||||||
sheetRole=""
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.Root>
|
|
||||||
</ToastContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ToastRoot.displayName = 'Toast.Root'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// View
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ToastView = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.View>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const largeViewport = useClientMediaQuery('(min-width: 1000px)')
|
|
||||||
const contentPlacement = largeViewport ? 'right' : 'top'
|
|
||||||
|
|
||||||
const context = useContext(ToastContext)
|
|
||||||
if (!context) throw new Error('ToastView must be used within a ToastContext.Provider')
|
|
||||||
const { setTravelStatus } = context
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`Toast-container ${className ?? ''}`.trim()}
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<Sheet.View
|
|
||||||
className={`Toast-view ${className ?? ''}`.trim()}
|
|
||||||
contentPlacement={contentPlacement}
|
|
||||||
inertOutside={false}
|
|
||||||
onPresentAutoFocus={{ focus: false }}
|
|
||||||
onDismissAutoFocus={{ focus: false }}
|
|
||||||
onClickOutside={{
|
|
||||||
dismiss: false,
|
|
||||||
stopOverlayPropagation: false,
|
|
||||||
}}
|
|
||||||
onEscapeKeyDown={{
|
|
||||||
dismiss: false,
|
|
||||||
stopOverlayPropagation: false,
|
|
||||||
}}
|
|
||||||
onTravelStatusChange={setTravelStatus}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.View>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ToastView.displayName = 'Toast.View'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Content
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ToastContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Sheet.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Sheet.Content>
|
|
||||||
>(({ children, className, ...restProps }, ref) => {
|
|
||||||
const context = useContext(ToastContext)
|
|
||||||
if (!context) throw new Error('ToastContent must be used within ToastRoot')
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sheet.Content
|
|
||||||
className={`Toast-content ${className ?? ''}`.trim()}
|
|
||||||
asChild
|
|
||||||
{...restProps}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<Sheet.SpecialWrapper.Root>
|
|
||||||
<Sheet.SpecialWrapper.Content
|
|
||||||
className="Toast-innerContent"
|
|
||||||
onPointerEnter={() => context.setPointerOver(true)}
|
|
||||||
onPointerLeave={() => context.setPointerOver(false)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Sheet.SpecialWrapper.Content>
|
|
||||||
</Sheet.SpecialWrapper.Root>
|
|
||||||
</Sheet.Content>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ToastContent.displayName = 'Toast.Content'
|
|
||||||
|
|
||||||
// ================================================================================================
|
|
||||||
// Unchanged Components
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
const ToastPortal = Sheet.Portal
|
|
||||||
const ToastTrigger = Sheet.Trigger
|
|
||||||
const ToastHandle = Sheet.Handle
|
|
||||||
const ToastOutlet = Sheet.Outlet
|
|
||||||
const ToastTitle = Sheet.Title
|
|
||||||
const ToastDescription = Sheet.Description
|
|
||||||
|
|
||||||
export const Toast = {
|
|
||||||
Root: ToastRoot,
|
|
||||||
Portal: ToastPortal,
|
|
||||||
View: ToastView,
|
|
||||||
Content: ToastContent,
|
|
||||||
Trigger: ToastTrigger,
|
|
||||||
Title: ToastTitle,
|
|
||||||
Description: ToastDescription,
|
|
||||||
Handle: ToastHandle,
|
|
||||||
Outlet: ToastOutlet,
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import '@silk-hq/components/dist/main-unlayered.css'
|
|
||||||
import { Fixed, Scroll, Sheet } from '@silk-hq/components'
|
|
||||||
import { BottomSheet } from './BottomSheet'
|
|
||||||
import { SheetWithDepth, SheetWithDepthStack } from './SheetWithDepth'
|
|
||||||
import { SheetWithDetent } from './SheetWithDetent'
|
|
||||||
import { SheetWithStacking, SheetWithStackingStack } from './SheetWithStacking'
|
|
||||||
import { ParallaxPage, ParallaxPageStack } from './ParallaxPage'
|
|
||||||
import { Toast } from './Toast'
|
|
||||||
import { Card } from './Card'
|
|
||||||
import { Page } from './Page'
|
|
||||||
import { Sidebar } from './Sidebar'
|
|
||||||
import { PersistentSheetWithDetent } from './PersistentSheetWithDetent'
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
var LSSilkhq: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const silkhq = {
|
|
||||||
Sheet, Fixed, Scroll, BottomSheet,
|
|
||||||
SheetWithDepth, SheetWithDepthStack,
|
|
||||||
SheetWithStacking, SheetWithDetent,
|
|
||||||
SheetWithStackingStack,
|
|
||||||
ParallaxPage, ParallaxPageStack,
|
|
||||||
Toast, CardSheet: Card, Page, Sidebar, PersistentSheetWithDetent
|
|
||||||
}
|
|
||||||
|
|
||||||
window.LSSilkhq = silkhq
|
|
||||||
|
|
||||||
export default silkhq
|
|
||||||
@@ -3786,11 +3786,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
|
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
|
||||||
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
|
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
|
||||||
|
|
||||||
"@silk-hq/components@^0.9.10":
|
|
||||||
version "0.9.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/@silk-hq/components/-/components-0.9.10.tgz#ed6baa898b4f36ce0e5ecadabfecef748546db74"
|
|
||||||
integrity sha512-dr6NRdGR2vovh4Uv27IhnkvpcUwHR9D7YZLCxTE6fyl4Zb6K6cGUlWVo3b3tgfCHVyirvrRvqWOF2nxMVlmVXg==
|
|
||||||
|
|
||||||
"@sinclair/typebox@^0.27.8":
|
"@sinclair/typebox@^0.27.8":
|
||||||
version "0.27.8"
|
version "0.27.8"
|
||||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
|
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
|
||||||
|
|||||||
Reference in New Issue
Block a user