diff --git a/.github/actions/submodules-checkout/action.yml b/.github/actions/submodules-checkout/action.yml new file mode 100644 index 000000000000..0b47233e94ce --- /dev/null +++ b/.github/actions/submodules-checkout/action.yml @@ -0,0 +1,46 @@ +name: CI setup + +description: | + Sets up the CI environment for the project. + +inputs: + submodules-ssh-key: + description: "The SSH key to private submodules to use for the checkout" + required: true + +runs: + using: "composite" + + steps: + - name: Set up SSH for Git + if: ${{ inputs.submodules-ssh-key }} + run: | + mkdir -p ~/.ssh + echo "${{ inputs.submodules-ssh-key }}" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + ssh-keyscan github.com >> ~/.ssh/known_hosts + shell: bash + + - name: Verify SSH Connection (Optional) + if: ${{ inputs.submodules-ssh-key }} + run: | + ssh -T git@github.com || true + shell: bash + + - name: Verify SSH Connection (Optional) + if: ${{ inputs.submodules-ssh-key }} + run: | + echo Branch is ${{ github.event.pull_request.head.ref || github.ref_name }} + shell: bash + + - name: Try checkout submodules to the same branch as main repo + if: ${{ inputs.submodules-ssh-key }} + run: | + ./submodules.sh ${{ github.event.pull_request.head.ref || github.ref_name }} + shell: bash + + - name: Show main readme + if: ${{ inputs.submodules-ssh-key }} + run: | + cat ./packages/sdk-components-animation/private-src/README.md || echo "No README found" + shell: bash diff --git a/.github/workflows/check-submodules.yml b/.github/workflows/check-submodules.yml new file mode 100644 index 000000000000..c97bdf016b2c --- /dev/null +++ b/.github/workflows/check-submodules.yml @@ -0,0 +1,67 @@ +name: Check submodules + +on: + pull_request: + +# cancel in-progress runs on new commits to same PR (gitub.event.number) +concurrency: + group: ${{ github.workflow }}-${{ github.event.number || github.sha }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + checks: + timeout-minutes: 20 + + environment: + name: development + + env: + DATABASE_URL: postgres:// + AUTH_SECRET: test + + runs-on: ubuntu-24.04-arm + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} + + - name: Check if any submodule branch matches github.ref_name + run: | + echo "C ${{ github.workflow }}-${{ github.event.number || github.sha }}" + # Get the current branch or tag name + REF_NAME="${{ github.event.pull_request.head.ref || github.ref_name }}" + + echo "Branch is:" $REF_NAME + + # List all submodule paths + SUBMODULES=$(git submodule status | awk '{print $2}') + + # Check each submodule's branch + for SUBMODULE in $SUBMODULES; do + echo "Checking submodule: $SUBMODULE" + ( + cd "$SUBMODULE" + # Get the current branch of the submodule + SUBMODULE_BRANCH=$(git rev-parse --abbrev-ref HEAD) + echo "Submodule branch: $SUBMODULE_BRANCH" + + # Compare the submodule branch to the ref_name + if [ "$SUBMODULE_BRANCH" = "$REF_NAME" ]; then + echo "::error::Submodule '$SUBMODULE' is on branch '$SUBMODULE_BRANCH', which matches the current ref '$REF_NAME'." + exit 1 + fi + ) + if [ $? -ne 0 ]; then + exit 1 # Fail the workflow if any submodule branch matches + fi + done + + echo "No submodule is on the same branch as the current ref '$REF_NAME'." diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 8f166944635f..549d9a0c634f 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -20,12 +20,20 @@ jobs: runs-on: ubuntu-latest + environment: + name: development + steps: - uses: actions/checkout@v4 with: fetch-depth: 2 # we need to fetch at least parent commit to satisfy Chromatic ref: ${{ github.event.pull_request.head.sha || github.sha }} # HEAD commit instead of merge commit + # Storybook with submodules + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} + - uses: ./.github/actions/ci-setup - name: Chromatic diff --git a/.github/workflows/cli-r2-static.yaml b/.github/workflows/cli-r2-static.yaml index bbf61abfabbb..d21ecd265bc4 100644 --- a/.github/workflows/cli-r2-static.yaml +++ b/.github/workflows/cli-r2-static.yaml @@ -30,6 +30,8 @@ jobs: with: ref: ${{ github.sha }} # HEAD commit instead of merge commit + # Do not checkout submodules, they are not needed for this workflow + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/cli-r2.yaml b/.github/workflows/cli-r2.yaml index 4b36b5087bc6..b8e3247cf035 100644 --- a/.github/workflows/cli-r2.yaml +++ b/.github/workflows/cli-r2.yaml @@ -31,6 +31,11 @@ jobs: with: ref: ${{ github.sha }} # HEAD commit instead of merge commit + # We need submodules here as this is used for the cloudflare build + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/fixtures-test.yml b/.github/workflows/fixtures-test.yml index 5f37750af516..e627224a96f3 100644 --- a/.github/workflows/fixtures-test.yml +++ b/.github/workflows/fixtures-test.yml @@ -9,6 +9,12 @@ on: builder-host: required: true type: string + environment: + required: true + type: string + secrets: + PRIVATE_GITHUB_DEPLOY_TOKEN: + required: true permissions: contents: read # to fetch code (actions/checkout) @@ -23,6 +29,9 @@ jobs: runs-on: ${{ matrix.os }} + environment: + name: ${{ inputs.environment }} + env: DATABASE_URL: postgres:// AUTH_SECRET: test @@ -32,7 +41,11 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} # HEAD commit instead of merge commit + ref: ${{ github.event.pull_request.head.sha || github.sha }} + # Test that everything is working with submodules + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} - uses: ./.github/actions/ci-setup diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3fec2ba4d15f..ef5082bca988 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,6 +18,15 @@ jobs: checks: timeout-minutes: 20 + strategy: + matrix: + environment: + - empty + - development + + environment: + name: ${{ matrix.environment }} + env: DATABASE_URL: postgres:// AUTH_SECRET: test @@ -27,7 +36,12 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} # HEAD commit instead of merge commit + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + # Will not checkout submodules on empty environment, and will on development + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} - uses: ./.github/actions/ci-setup @@ -41,21 +55,35 @@ jobs: - run: echo ===SHA USED=== ${{ github.event.pull_request.head.sha || github.sha }} # todo: remove after check whats happening on main - - run: pnpm prettier --cache --check "**/*.{js,md,ts,tsx}" + - run: | + pnpm prettier --cache --check "**/*.{js,md,ts,tsx}" + + - name: Lint + run: | + pnpm lint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslint-cache - - run: pnpm lint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslint-cache + - name: Test + run: | + pnpm -r test - - run: pnpm -r test - - run: pnpm --filter=@webstudio-is/prisma-client build - - run: pnpm -r typecheck + - name: Typecheck + run: | + pnpm -r typecheck check-size: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04-arm + + environment: + name: development steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} # HEAD commit instead of merge commit + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} - uses: ./.github/actions/ci-setup diff --git a/.github/workflows/vercel-deploy-staging.yml b/.github/workflows/vercel-deploy-staging.yml index ba79625ac6ec..883ccc710235 100644 --- a/.github/workflows/vercel-deploy-staging.yml +++ b/.github/workflows/vercel-deploy-staging.yml @@ -5,7 +5,7 @@ on: # cancel in-progress runs on new commits to same PR (gitub.event.number) concurrency: - group: vercel-deploy-${{ github.workflow }}-${{ github.event.number || github.sha }} + group: vercel-deploy-${{ github.workflow }}-${{ github.sha }} cancel-in-progress: true permissions: @@ -38,9 +38,14 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} # HEAD commit instead of merge commit + ref: ${{ github.sha }} + + - uses: ./.github/actions/submodules-checkout + with: + submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 with: node-version: 20 @@ -85,6 +90,11 @@ jobs: with: builder-url: ${{ needs.deployment.outputs.builder-url }} builder-host: ${{ needs.deployment.outputs.builder-host }} + environment: development + secrets: + # We are not passing the secret here (as it does not exist in the current environment). + # Instead, this serves as a signal to the calling workflow that it has permission to extract it from the environment. + PRIVATE_GITHUB_DEPLOY_TOKEN: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }} delete-github-deployments: needs: fixtures-test diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..76cab76f4653 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "packages/sdk-components-animation/private-src"] + path = packages/sdk-components-animation/private-src + url = git@github.com:webstudio-is/sdk-components-animation.git + branch = main diff --git a/.storybook/main.ts b/.storybook/main.ts index 191dd8425b15..9bbdb895e7a7 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,5 +1,19 @@ import * as path from "node:path"; import type { StorybookConfig } from "@storybook/react-vite"; +import { existsSync, readdirSync } from "node:fs"; + +const isFolderEmpty = (folderPath: string) => { + if (!existsSync(folderPath)) { + return true; // Folder does not exist + } + const contents = readdirSync(folderPath); + + return contents.length === 0; +}; + +const hasPrivateFolders = !isFolderEmpty( + path.join(__dirname, "../../packages/sdk-components-animation/private-src") +); const visualTestingStories: StorybookConfig["stories"] = [ { @@ -37,6 +51,10 @@ export default { directory: "../packages/sdk-components-react-radix", titlePrefix: "SDK Components React Radix", }, + { + directory: "../packages/sdk-components-animation", + titlePrefix: "SDK Components Animation", + }, ], framework: { name: "@storybook/react-vite", @@ -50,6 +68,10 @@ export default { async viteFinal(config) { return { ...config, + optimizeDeps: { + exclude: ["scroll-timeline-polyfill"], + }, + define: { ...config.define, // storybook use "util" package internally which is bundled with stories @@ -59,7 +81,17 @@ export default { }, resolve: { ...config.resolve, - conditions: ["webstudio", "import", "module", "browser", "default"], + conditions: hasPrivateFolders + ? [ + "webstudio-private", + "webstudio", + "import", + "module", + "browser", + "default", + ] + : ["webstudio", "import", "module", "browser", "default"], + alias: [ { find: "~", diff --git a/@types/scroll-timeline.d.ts b/@types/scroll-timeline.d.ts new file mode 100644 index 000000000000..eea03a78a8f6 --- /dev/null +++ b/@types/scroll-timeline.d.ts @@ -0,0 +1,14 @@ +type ScrollAxis = "block" | "inline" | "x" | "y"; + +interface ScrollTimelineOptions { + source?: Element | Document | null; + axis?: ScrollAxis; +} + +declare class ScrollTimeline extends AnimationTimeline { + constructor(options?: ScrollTimelineOptions); +} + +declare class ViewTimeline extends ScrollTimeline { + constructor(options?: ScrollTimelineOptions); +} diff --git a/apps/builder/app/routes/_ui.playground.tsx b/apps/builder/app/routes/_ui.playground.tsx new file mode 100644 index 000000000000..1336ca563972 --- /dev/null +++ b/apps/builder/app/routes/_ui.playground.tsx @@ -0,0 +1,92 @@ +import { Scroll } from "@webstudio-is/sdk-components-animation"; +import { parseCssValue } from "@webstudio-is/css-data"; +import { Box, styled } from "@webstudio-is/design-system"; + +const H1 = styled("h1"); + +const DEBUG = false; + +const Playground = () => { + return ( + + +

+ HELLO WORLD +

+
+ + Start scrolling, and when the current box scrolls out, the “HELLO WORLD” + header will fly in and become hoverable. (During the animation, it won’t + be hoverable.) + + + + When you see this box, the “HELLO WORLD” header will fly out. + +
+ ); +}; + +export default Playground; + +// Reduces Vercel function size from 29MB to 9MB for unknown reasons; effective when used in limited files. +export const config = { + maxDuration: 30, +}; diff --git a/apps/builder/vite.config.ts b/apps/builder/vite.config.ts index 3357db040a3d..eced690c8c74 100644 --- a/apps/builder/vite.config.ts +++ b/apps/builder/vite.config.ts @@ -1,4 +1,4 @@ -import { resolve } from "node:path"; +import path, { resolve } from "node:path"; import { defineConfig, type CorsOptions } from "vite"; import { vitePlugin as remix } from "@remix-run/dev"; import { vercelPreset } from "@vercel/remix/vite"; @@ -9,13 +9,28 @@ import { getAuthorizationServerOrigin, isBuilderUrl, } from "./app/shared/router-utils/origins"; -import { readFileSync } from "node:fs"; +import { readFileSync, readdirSync, existsSync } from "node:fs"; + +const isFolderEmpty = (folderPath: string) => { + if (!existsSync(folderPath)) { + return true; // Folder does not exist + } + const contents = readdirSync(folderPath); + + return contents.length === 0; +}; + +const hasPrivateFolders = !isFolderEmpty( + path.join(__dirname, "../../packages/sdk-components-animation/private-src") +); export default defineConfig(({ mode }) => { if (mode === "test") { return { resolve: { - conditions: ["webstudio"], + conditions: hasPrivateFolders + ? ["webstudio-private", "webstudio"] + : ["webstudio"], alias: [ { find: "~", @@ -69,7 +84,10 @@ export default defineConfig(({ mode }) => { }, ], resolve: { - conditions: ["webstudio"], + conditions: hasPrivateFolders + ? ["webstudio-private", "webstudio"] + : ["webstudio"], + alias: [ { find: "~", diff --git a/package.json b/package.json index 32bac180599e..5418bee673da 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,8 @@ "css-tree@2.3.1": "patches/css-tree@2.3.1.patch", "@types/css-tree@2.3.1": "patches/@types__css-tree@2.3.1.patch", "@radix-ui/react-scroll-area@1.0.5": "patches/@radix-ui__react-scroll-area@1.0.5.patch", - "@remix-run/dev": "patches/@remix-run__dev.patch" + "@remix-run/dev": "patches/@remix-run__dev.patch", + "scroll-timeline-polyfill@1.1.0": "patches/scroll-timeline-polyfill@1.1.0.patch" } } } diff --git a/packages/sdk-components-animation/package.json b/packages/sdk-components-animation/package.json index b130dc72275c..4c32dda89905 100644 --- a/packages/sdk-components-animation/package.json +++ b/packages/sdk-components-animation/package.json @@ -14,6 +14,7 @@ ], "exports": { ".": { + "webstudio-private": "./private-src/components.ts", "webstudio": "./src/components.ts", "types": "./lib/types/components.d.ts", "import": "./lib/components.js" @@ -51,9 +52,12 @@ "react-dom": "18.3.0-canary-14898b6a9-20240318" }, "dependencies": { + "@webstudio-is/css-engine": "workspace:*", "@webstudio-is/icons": "workspace:*", "@webstudio-is/react-sdk": "workspace:*", - "@webstudio-is/sdk": "workspace:*" + "@webstudio-is/sdk": "workspace:*", + "react-error-boundary": "^5.0.0", + "scroll-timeline-polyfill": "^1.1.0" }, "devDependencies": { "@types/react": "^18.2.70", @@ -63,7 +67,10 @@ "@webstudio-is/sdk-components-react": "workspace:*", "@webstudio-is/template": "workspace:*", "@webstudio-is/tsconfig": "workspace:*", + "@webstudio-is/css-data": "workspace:*", + "@webstudio-is/design-system": "workspace:*", "react": "18.3.0-canary-14898b6a9-20240318", - "react-dom": "18.3.0-canary-14898b6a9-20240318" + "react-dom": "18.3.0-canary-14898b6a9-20240318", + "type-fest": "^4.32.0" } } diff --git a/packages/sdk-components-animation/private-src b/packages/sdk-components-animation/private-src new file mode 160000 index 000000000000..80edfcb8e401 --- /dev/null +++ b/packages/sdk-components-animation/private-src @@ -0,0 +1 @@ +Subproject commit 80edfcb8e4019f360c06622ff7543c78794b7a22 diff --git a/packages/sdk-components-animation/src/components.ts b/packages/sdk-components-animation/src/components.ts index cb0ff5c3b541..b8a77f059a67 100644 --- a/packages/sdk-components-animation/src/components.ts +++ b/packages/sdk-components-animation/src/components.ts @@ -1 +1 @@ -export {}; +export { Scroll } from "./scroll"; diff --git a/packages/sdk-components-animation/src/scroll.tsx b/packages/sdk-components-animation/src/scroll.tsx new file mode 100644 index 000000000000..17e0cc3f5aab --- /dev/null +++ b/packages/sdk-components-animation/src/scroll.tsx @@ -0,0 +1,14 @@ +import { forwardRef, type ElementRef } from "react"; +import type { AnimationAction } from "./shared/animation-types"; + +type ScrollProps = { + debug?: boolean; + children?: React.ReactNode; + action: AnimationAction; +}; + +export const Scroll = forwardRef, ScrollProps>( + ({ debug = false, action, ...props }, ref) => { + return
; + } +); diff --git a/packages/sdk-components-animation/src/shared/animation-types.tsx b/packages/sdk-components-animation/src/shared/animation-types.tsx new file mode 100644 index 000000000000..e997c6e9f661 --- /dev/null +++ b/packages/sdk-components-animation/src/shared/animation-types.tsx @@ -0,0 +1,113 @@ +import type { StyleValue, UnitValue } from "@webstudio-is/css-engine"; + +export type KeyframeStyles = { [property: string]: StyleValue | undefined }; + +export type AnimationKeyframe = { + offset: number | undefined; + // We are using composite: auto as the default value for now + // composite?: CompositeOperationOrAuto; + styles: KeyframeStyles; +}; + +const RANGE_UNITS = [ + "%", + "px", + // Does not supported by polyfill and we are converting it to px ourselfs + "cm", + "mm", + "q", + "in", + "pt", + "pc", + "em", + "rem", + "ex", + "rex", + "cap", + "rcap", + "ch", + "rch", + "lh", + "rlh", + "vw", + "svw", + "lvw", + "dvw", + "vh", + "svh", + "lvh", + "dvh", + "vi", + "svi", + "lvi", + "dvi", + "vb", + "svb", + "lvb", + "dvb", + "vmin", + "svmin", + "lvmin", + "dvmin", + "vmax", + "svmax", + "lvmax", + "dvmax", +] as const; + +export type RangeUnit = (typeof RANGE_UNITS)[number]; + +export const isRangeUnit = (value: unknown): value is RangeUnit => + RANGE_UNITS.includes(value as RangeUnit); + +export type RangeUnitValue = { type: "unit"; value: number; unit: RangeUnit }; + +({}) as RangeUnitValue satisfies UnitValue; + +type KeyframeEffectOptions = { + easing?: string; + fill?: FillMode; +}; + +/** + * Scroll does not support https://drafts.csswg.org/scroll-animations/#named-ranges + * However, for simplicity and type unification with the view, we will use the names "start" and "end," + * which will be transformed as follows: + * - "start" → `calc(0% + range)` + * - "end" → `calc(100% - range)` + */ +type ScrollNamedRange = "start" | "end"; + +/** + * Scroll does not support https://drafts.csswg.org/scroll-animations/#named-ranges + * However, for simplicity and type unification with the view, we will use the names "start" and "end," + * See ScrollNamedRange type for more information. + */ +export type ScrollRangeValue = [name: ScrollNamedRange, value: RangeUnitValue]; + +type ScrollRangeOptions = { + rangeStart?: ScrollRangeValue | undefined; + rangeEnd?: ScrollRangeValue | undefined; +}; + +/* +type AnimationTiming = { + delay?: number; + duration?: number; + easing?: string; + fill?: FillMode; +}; +*/ + +type ScrollAction = { + type: "scroll"; + source?: "closest" | "nearest" | "root"; + axis?: "block" | "inline" | "x" | "y"; + animations: { + timing: KeyframeEffectOptions & ScrollRangeOptions; + keyframes: AnimationKeyframe[]; + }[]; +}; + +// | ViewAction | ... +export type AnimationAction = ScrollAction; diff --git a/packages/sdk-components-animation/src/shared/proxy.ts b/packages/sdk-components-animation/src/shared/proxy.ts deleted file mode 100644 index 8145a83a563f..000000000000 --- a/packages/sdk-components-animation/src/shared/proxy.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createProxy } from "@webstudio-is/template"; - -export const animation = createProxy("@webstudio-is/sdk-components-animation:"); diff --git a/packages/sdk-components-animation/tsconfig.json b/packages/sdk-components-animation/tsconfig.json index d2e5040f8f2c..a7f8652f07c9 100644 --- a/packages/sdk-components-animation/tsconfig.json +++ b/packages/sdk-components-animation/tsconfig.json @@ -1,3 +1,12 @@ { - "extends": "@webstudio-is/tsconfig/base.json" + "extends": "@webstudio-is/tsconfig/base.json", + "include": [ + "src", + "../../@types/**/scroll-timeline.d.ts", + "private-src/scroll.stories.tsx", + "private-src/scroll.tsx" + ], + "compilerOptions": { + "types": ["react/experimental", "react-dom/experimental", "@types/node"] + } } diff --git a/patches/scroll-timeline-polyfill@1.1.0.patch b/patches/scroll-timeline-polyfill@1.1.0.patch new file mode 100644 index 000000000000..8b78d3071d0d --- /dev/null +++ b/patches/scroll-timeline-polyfill@1.1.0.patch @@ -0,0 +1,25 @@ +diff --git a/src/scroll-timeline-base.js b/src/scroll-timeline-base.js +index 2c854928701c5dae23c985eb04f73a6ca2b661c3..abf1a7629568f411dd83dd509640850706d59528 100644 +--- a/src/scroll-timeline-base.js ++++ b/src/scroll-timeline-base.js +@@ -162,13 +162,19 @@ function isValidAxis(axis) { + */ + export function measureSource (source) { + const style = getComputedStyle(source); ++ const clientHeight = source.clientHeight; + return { + scrollLeft: source.scrollLeft, + scrollTop: source.scrollTop, + scrollWidth: source.scrollWidth, + scrollHeight: source.scrollHeight, + clientWidth: source.clientWidth, +- clientHeight: source.clientHeight, ++ get clientHeight() { ++ if (document.scrollingElement === source) { ++ return window.innerHeight; ++ } ++ return clientHeight; ++ }, + writingMode: style.writingMode, + direction: style.direction, + scrollPaddingTop: style.scrollPaddingTop, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57c6cc58877e..19dc6862febf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ patchedDependencies: css-tree@2.3.1: hash: epgcmebti7rfrc2ej4odb3t4jy path: patches/css-tree@2.3.1.patch + scroll-timeline-polyfill@1.1.0: + hash: i4g3vdpump4efgy2hri5l5rsfm + path: patches/scroll-timeline-polyfill@1.1.0.patch importers: @@ -1914,6 +1917,9 @@ importers: packages/sdk-components-animation: dependencies: + '@webstudio-is/css-engine': + specifier: workspace:* + version: link:../css-engine '@webstudio-is/icons': specifier: workspace:* version: link:../icons @@ -1923,6 +1929,12 @@ importers: '@webstudio-is/sdk': specifier: workspace:* version: link:../sdk + react-error-boundary: + specifier: ^5.0.0 + version: 5.0.0(react@18.3.0-canary-14898b6a9-20240318) + scroll-timeline-polyfill: + specifier: ^1.1.0 + version: 1.1.0(patch_hash=i4g3vdpump4efgy2hri5l5rsfm) devDependencies: '@types/react': specifier: ^18.2.70 @@ -1930,6 +1942,12 @@ importers: '@types/react-dom': specifier: ^18.2.25 version: 18.2.25 + '@webstudio-is/css-data': + specifier: workspace:* + version: link:../css-data + '@webstudio-is/design-system': + specifier: workspace:* + version: link:../design-system '@webstudio-is/generate-arg-types': specifier: workspace:* version: link:../generate-arg-types @@ -1951,6 +1969,9 @@ importers: react-dom: specifier: 18.3.0-canary-14898b6a9-20240318 version: 18.3.0-canary-14898b6a9-20240318(react@18.3.0-canary-14898b6a9-20240318) + type-fest: + specifier: ^4.32.0 + version: 4.32.0 packages/sdk-components-react: dependencies: @@ -8398,6 +8419,9 @@ packages: scheduler@0.24.0-canary-14898b6a9-20240318: resolution: {integrity: sha512-ifDO3bUdooS4OlxvGxMyoDEC/aq14MvJLDd0thjrUSZGeLJA7WBc+sr9NZxIxrXfVqMl1GTGGPwXqRJZDNW76w==} + scroll-timeline-polyfill@1.1.0: + resolution: {integrity: sha512-BpL3gk3Ynt/5VYaDFUNUP/FTkDldwKQnWcA07g/mDHkMVS9pQUyUXBpsy4RZYAgsfFeI1tWcnPNrEFtCpQoO9Q==} + selfsigned@2.1.1: resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==} engines: {node: '>=10'} @@ -16336,6 +16360,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + scroll-timeline-polyfill@1.1.0(patch_hash=i4g3vdpump4efgy2hri5l5rsfm): {} + selfsigned@2.1.1: dependencies: node-forge: 1.3.1 diff --git a/submodules.sh b/submodules.sh new file mode 100755 index 000000000000..0c624f2d6cc0 --- /dev/null +++ b/submodules.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +BRANCH="$1" + + +git submodule update --init --recursive + +git submodule foreach ' + # If a branch parameter is provided, use it; otherwise, determine the branch dynamically + if [ -n "'"$BRANCH"'" ]; then + SUBMODULE_BRANCH="'"$BRANCH"'" + else + SUBMODULE_BRANCH=$(git -C $toplevel rev-parse --abbrev-ref HEAD) + fi + + echo "Checking out \"$SUBMODULE_BRANCH\" branch in \"$name\" submodule" + + # Check if the branch exists in the remote + if git ls-remote --exit-code --heads origin "$SUBMODULE_BRANCH" > /dev/null; then + git checkout "$SUBMODULE_BRANCH" && git pull origin "$SUBMODULE_BRANCH" + else + # Fallback to "main" if the branch does not exist + git checkout "main" && git pull origin "main" + fi +' \ No newline at end of file