Skip to content

Commit a1c099c

Browse files
committed
Merge branch 'staging' into fix/urgent-billing-isolated
Made-with: Cursor # Conflicts: # apps/sim/lib/copilot/tools/server/files/edit-content.ts # apps/sim/lib/copilot/tools/server/files/workspace-file.ts # apps/sim/lib/execution/doc-vm.ts # apps/sim/lib/execution/pptx-vm.ts
2 parents 198ae7e + 948cdbc commit a1c099c

File tree

356 files changed

+1938
-1277
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

356 files changed

+1938
-1277
lines changed

.claude/rules/global.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,25 @@ const shortId = generateShortId()
3030
const tiny = generateShortId(8)
3131
```
3232

33+
## Common Utilities
34+
Use shared helpers from `@/lib/core/utils/helpers` instead of writing inline implementations:
35+
36+
- `sleep(ms)` — async delay. Never write `new Promise(resolve => setTimeout(resolve, ms))`
37+
- `toError(value)` — normalize unknown caught values to `Error`. Never write `e instanceof Error ? e : new Error(String(e))`
38+
- `toError(value).message` — get error message safely. Never write `e instanceof Error ? e.message : String(e)`
39+
40+
```typescript
41+
// ✗ Bad
42+
await new Promise(resolve => setTimeout(resolve, 1000))
43+
const msg = error instanceof Error ? error.message : String(error)
44+
const err = error instanceof Error ? error : new Error(String(error))
45+
46+
// ✓ Good
47+
import { sleep, toError } from '@/lib/core/utils/helpers'
48+
await sleep(1000)
49+
const msg = toError(error).message
50+
const err = toError(error)
51+
```
52+
3353
## Package Manager
3454
Use `bun` and `bunx`, not `npm` and `npx`.

.cursor/rules/global.mdc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,25 @@ const shortId = generateShortId()
3737
const tiny = generateShortId(8)
3838
```
3939

40+
## Common Utilities
41+
Use shared helpers from `@/lib/core/utils/helpers` instead of writing inline implementations:
42+
43+
- `sleep(ms)` — async delay. Never write `new Promise(resolve => setTimeout(resolve, ms))`
44+
- `toError(value)` — normalize unknown caught values to `Error`. Never write `e instanceof Error ? e : new Error(String(e))`
45+
- `toError(value).message` — get error message safely. Never write `e instanceof Error ? e.message : String(e)`
46+
47+
```typescript
48+
// ✗ Bad
49+
await new Promise(resolve => setTimeout(resolve, 1000))
50+
const msg = error instanceof Error ? error.message : String(error)
51+
const err = error instanceof Error ? error : new Error(String(error))
52+
53+
// ✓ Good
54+
import { sleep, toError } from '@/lib/core/utils/helpers'
55+
await sleep(1000)
56+
const msg = toError(error).message
57+
const err = toError(error)
58+
```
59+
4060
## Package Manager
4161
Use `bun` and `bunx`, not `npm` and `npx`.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ You are a professional software engineer. All code must follow best practices: a
88
- **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments
99
- **Styling**: Never update global styles. Keep all styling local to components
1010
- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid`
11+
- **Common Utilities**: Use shared helpers from `@/lib/core/utils/helpers` instead of inline implementations. `sleep(ms)` for delays, `toError(e)` to normalize caught values.
1112
- **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx`
1213

1314
## Architecture

apps/docs/components/ui/action-media.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useState } from 'react'
3+
import { useRef, useState } from 'react'
44
import { cn, getAssetUrl } from '@/lib/utils'
55
import { Lightbox } from './lightbox'
66

@@ -50,18 +50,22 @@ export function ActionImage({ src, alt, enableLightbox = true }: ActionImageProp
5050
}
5151

5252
export function ActionVideo({ src, alt, enableLightbox = true }: ActionVideoProps) {
53+
const videoRef = useRef<HTMLVideoElement>(null)
54+
const startTimeRef = useRef(0)
5355
const [isLightboxOpen, setIsLightboxOpen] = useState(false)
5456
const resolvedSrc = getAssetUrl(src)
5557

5658
const handleClick = () => {
5759
if (enableLightbox) {
60+
startTimeRef.current = videoRef.current?.currentTime ?? 0
5861
setIsLightboxOpen(true)
5962
}
6063
}
6164

6265
return (
6366
<>
6467
<video
68+
ref={videoRef}
6569
src={resolvedSrc}
6670
autoPlay
6771
loop
@@ -80,6 +84,7 @@ export function ActionVideo({ src, alt, enableLightbox = true }: ActionVideoProp
8084
src={src}
8185
alt={alt}
8286
type='video'
87+
startTime={startTimeRef.current}
8388
/>
8489
)}
8590
</>

apps/docs/components/ui/animated-blocks.tsx

Lines changed: 0 additions & 195 deletions
This file was deleted.

apps/docs/components/ui/faq.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useState } from 'react'
44
import { ChevronRight } from 'lucide-react'
5+
import { cn } from '@/lib/utils'
56

67
interface FAQItem {
78
question: string
@@ -31,9 +32,10 @@ function FAQItemRow({
3132
className='flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left font-[470] text-[0.875rem] text-[rgba(0,0,0,0.8)] transition-colors hover:bg-[rgba(0,0,0,0.02)] dark:text-[rgba(255,255,255,0.85)] dark:hover:bg-[rgba(255,255,255,0.03)]'
3233
>
3334
<ChevronRight
34-
className={`h-3.5 w-3.5 shrink-0 text-[rgba(0,0,0,0.3)] transition-transform duration-200 dark:text-[rgba(255,255,255,0.3)] ${
35-
isOpen ? 'rotate-90' : ''
36-
}`}
35+
className={cn(
36+
'h-3.5 w-3.5 shrink-0 text-[rgba(0,0,0,0.3)] transition-transform duration-200 dark:text-[rgba(255,255,255,0.3)]',
37+
isOpen && 'rotate-90'
38+
)}
3739
/>
3840
{item.question}
3941
</button>
@@ -81,11 +83,10 @@ export function FAQ({ items, title = 'Common Questions' }: FAQProps) {
8183
{items.map((item, index) => (
8284
<div
8385
key={index}
84-
className={
85-
index !== items.length - 1
86-
? 'border-[rgba(0,0,0,0.08)] border-b dark:border-[rgba(255,255,255,0.08)]'
87-
: ''
88-
}
86+
className={cn(
87+
index !== items.length - 1 &&
88+
'border-[rgba(0,0,0,0.08)] border-b dark:border-[rgba(255,255,255,0.08)]'
89+
)}
8990
>
9091
<FAQItemRow
9192
item={item}

apps/docs/components/ui/language-dropdown.tsx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client'
22

3-
import { useEffect, useState } from 'react'
43
import { Check } from 'lucide-react'
54
import { useParams, usePathname, useRouter } from 'next/navigation'
65
import {
@@ -25,24 +24,9 @@ export function LanguageDropdown() {
2524
const params = useParams()
2625
const router = useRouter()
2726

28-
const [currentLang, setCurrentLang] = useState(() => {
29-
const langFromParams = params?.lang as string
30-
return langFromParams && Object.keys(languages).includes(langFromParams) ? langFromParams : 'en'
31-
})
32-
33-
useEffect(() => {
34-
const langFromParams = params?.lang as string
35-
36-
if (langFromParams && Object.keys(languages).includes(langFromParams)) {
37-
if (langFromParams !== currentLang) {
38-
setCurrentLang(langFromParams)
39-
}
40-
} else {
41-
if (currentLang !== 'en') {
42-
setCurrentLang('en')
43-
}
44-
}
45-
}, [params])
27+
const langFromParams = params?.lang as string
28+
const currentLang =
29+
langFromParams && Object.keys(languages).includes(langFromParams) ? langFromParams : 'en'
4630

4731
const handleLanguageChange = (locale: string) => {
4832
if (locale === currentLang) return

0 commit comments

Comments
 (0)