Commit Graph
3206 Commits
Author SHA1 Message Date
Oleg Isonen 4dfe557aa7 feat: add project transfer and move functionality
- Add transfer dialog with workspace selector and email input
- Support moving projects between workspaces (instant) and
  transferring to another user via notification (async)
- Add project transfer notification type with accept/decline flow
- Verify sender ownership and auto-decline stale transfers
- Add audit logging for ownership changes
- Add canTransfer permission for owners and admins
- Use camelCase notification types (workspaceInvite, projectTransfer)
- Use .select("id").single() on all notification status updates
- Debounce email search with stale response rejection
- Use Set-based loading state for concurrent notification actions
- Filter unknown notification types before rendering
- Use theme tokens for all spacing values
2026-03-17 13:14:45 +00:00
Oleg Isonen b43f67701d feat: notification pipeline and workspace invite flow
- Add Notification model with pending/accepted/declined status
- Add WorkspaceMember soft-delete via removedAt column
- Create notification CRUD (create, list, count, accept, decline)
- Wire addMember to create notifications instead of direct insert
- Accept handler upserts WorkspaceMember, verifies workspace exists
- 7-day TTL expiration on all notification queries
- Idempotent duplicate detection for pending invites
- Add bell icon with dot indicator and notification popover
- Add notification tRPC router (list, count, accept, decline)
- Refactor dashboard findMany to object params with UUID validation
- Add toast errors on accept/decline failures
- Anti-enumeration: silent succeed for non-existent emails
2026-03-17 01:01:06 +00:00
Oleg Isonen efb81f69e9 feat: make workspaces non-optional in getPermissions and DashboardData 2026-03-16 21:04:23 +00:00
Oleg Isonen ff06f58e32 feat: workspace downgrade — revoke member access when owner's plan drops
When a workspace owner's plan no longer supports workspaces (maxWorkspaces <= 1),
member access is revoked while preserving workspace data and memberships:

- Add getOwnerPlanFeatures callback to AppContext for cross-user plan lookups
- Check workspace owner plan in hasProjectPermit to deny non-owner access
- Mark member workspaces as isDowngraded in findMany based on owner plan
- Gate updateWorkspaceRelation behind maxWorkspaces check
- Block downgraded workspace members in builder route loader
- Show ProBadge "Suspended" and disable selection for downgraded workspaces
2026-03-16 19:43:51 +00:00
Oleg Isonen b8d4e60928 feat: always show workspace selector, minimum 1 workspace, gate members on plan 2026-03-16 18:30:47 +00:00
Oleg Isonen aa32e08c53 feat: refactor dashboard sidebar to Grid layout with workspace separator and update neutral notification color 2026-03-16 16:53:06 +00:00
Oleg Isonen ab8b0ab429 fix: filter null relations in workspace authorization query 2026-03-16 16:01:09 +00:00
Oleg Isonen b8d07af7e6 feat: gate workspace features behind maxWorkspaces plan limit
- Replace workspaces feature flag with maxWorkspaces-based gating
- Default maxWorkspaces to 0 (controlled via MAX_WORKSPACES env var)
- Skip workspace queries in dashboard loader when maxWorkspaces is 0
- Extract pure functions (resolveCurrentWorkspace, isWorkspaceRelationPermitted, getView) with tests
- Remove workspaces feature flag from all files
2026-03-16 15:58:16 +00:00
Oleg Isonen 67153dba0e feat: dashboard welcome view, profile name, and template approval bypass
- Show user name next to profile avatar in dashboard sidebar
- Separate welcome view from templates into its own component
- Welcome subtitle with create blank project button (permission-gated)
- Allow PROJECT_TEMPLATES to skip marketplace approval check
- Templates view shows clean "Starter templates" title
2026-03-16 10:08:05 +00:00
Oleg Isonen d542352a6c Merge branch 'feat/workspaces' into feat/workspaces-rebased
# Conflicts:
#	apps/builder/app/builder/features/menu/menu.tsx
#	apps/builder/app/dashboard/dashboard.stories.tsx
2026-03-16 00:17:07 +00:00
Oleg Isonen c4d26cbf62 chore: more stories updates (#5646)
## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-03-15 22:19:30 +01:00
Oleg Isonen 91d2136921 refactor(stories): consolidate exports, add StorySection/StoryGrid everywhere, remove argTypes/args 2026-03-15 19:21:33 +00:00
Oleg Isonen 2216adf4f0 fix: expand story coverage and apply sentence case to all story titles
- Add new story variants across ~100 files covering previously untested props
- Fix all story titles to use sentence case per UI label guidelines
- Consolidate duplicate card, thumbnail, and value-text stories into parent files
- Add interactive/controlled variants for checkbox, radio, switch, select, etc.
- Add style source, disabled, icon, placeholder, unit options variants to CssValueInput
- Add sub-menu, radio group, destructive, and disabled variants to dropdown/context menus
- Add dialog resize, maximize, actions, and non-draggable variants
- Add popover title, actions, and side placement variants
- Add tooltip side placements and content variant stories
2026-03-15 15:34:17 +00:00
Oleg Isonen 9d9331cb32 chore: update sdk-components-animation submodule 2026-03-15 13:53:28 +00:00
Oleg Isonen 8cab7763d5 fix: rename single-story exports, add sidebarWidth wrapping, improve variant coverage\n\nRename 22 single-story exports to match their title (e.g. Basic/Story/Default\n→ ComponentName) to eliminate unnecessary Storybook sidebar nesting.\n\nWrap all settings-panel and style-panel stories in theme.sizes.sidebarWidth\nfor realistic rendering width.\n\nImprove variant coverage in kbd, style-source-badge, and other stories." 2026-03-15 13:48:56 +00:00
Oleg Isonen 211f4e9b2d improve story variant coverage and fix TS errors
- separator: add horizontal + vertical orientations
- kbd: add color variants, regular variant, diverse key combos
- search-field: add autoFocus and disabled states
- component-card: add description/tooltip, state labels, remove storyName
- enhanced-tooltip: add JSX content, side placements, custom delay
- style-source-badge: add all 5 source variants + truncation test
- text: add full variant, color, alignment, truncate, userSelect coverage
- fix keyboard-shortcuts-dialog import alias conflict
- fix inset-layout renderCell signature and CssProperty types
- fix asset-manager broken component reference
2026-03-15 13:43:03 +00:00
Oleg Isonen f62a34bbff fix: resolve naming conflicts in story exports and fix TS errors\n\nAlias component imports to avoid conflicts with story export names\n(e.g., import { Card as CardComponent }). Fix unused imports/variables\nin about.stories.tsx and css-value-input.stories.tsx. Fix CssProperty\ntype, help-center icon, and typeof self-references. 2026-03-15 12:46:51 +00:00
Oleg Isonen 64e5c17129 fix: stories render open by default, remove Demo nesting, use data URLs for images
- Make interaction-requiring stories render content immediately:
  - import-redirects-dialog: render dialog open directly
  - context-menu: use DropdownMenu with defaultOpen
  - enhanced-tooltip: add defaultOpen prop
  - tooltip: add open prop, pre-populate error state
  - command-panel: call openCommandPanel() on mount
  - toast: remove interactive InAction story

- Rename single 'Demo' exports to match component names,
  eliminating redundant navigation nesting in Storybook
  (e.g. 'Search Preview / Demo' → 'Search Preview')

- Replace external image URLs with inline data:image/svg+xml:
  - avatar: pravatar.cc → inline SVG
  - marketplace/card: placehold.co → inline SVG
  - search-preview: favicon.ico → inline SVG
  - animate-children-scroll: unsplash → inline gradient SVG
  - toast: Blob/createObjectURL → inline data URL
2026-03-15 12:29:53 +00:00
Oleg Isonen f733bdf20a more stories 2026-03-15 11:28:23 +00:00
Oleg Isonen 0107eb8c4d fix: support data URIs in Image component, clean up stories
- Skip loader/optimization for data: src in getImageAttributes
- Replace external picsum.photos URL with inline SVG data URI in social-preview story
- Remove unnecessary ThumbnailWrapper from thumbnail stories
2026-03-15 09:02:56 +00:00
Oleg Isonen b67aaafe15 chore: delete unused ai-command-bar components and stories 2026-03-15 08:51:42 +00:00
Oleg Isonen 8292755fb6 fix: remove redundant title prefixes and use design system wrappers in stories\n\n- Remove redundant Builder/ prefix from 9 builder story titles (titlePrefix already adds it)\n- Remove redundant Design System/ prefix from 6 design-system story titles\n- Replace raw <div style={}> with Box/Flex and theme tokens in dashboard card/thumbnail stories 2026-03-14 16:14:14 +00:00
Oleg Isonen 2bdd6fd8e1 refactor: dissolve features/topbar into standalone features\n\n- Move share, clone, safe-mode, builder-mode, view-mode, sync-status directly under features/\n- Move publish cluster (publish, domains, add-domain, entri, cname) into features/publish/\n- Move menu into features/menu/\n- Move topbar-layout (utility) and topbar (composition) into shared/\n- Remove spinner story (animated SVG causes flaky visual tests)\n- Remove avatar NoImageNoFallback variant (invalid state)\n- Update story titles to reflect new structure 2026-03-14 15:47:19 +00:00
Oleg Isonen a06bedb8fc feat: add visual regression stories for style panel, dashboard, and design system components 2026-03-14 14:59:00 +00:00
Oleg Isonen 8880da1ac4 refactor: rename MemberRelation → WorkspaceRelation, remove permissions prop-drilling, unify shared stores
- Rename userRelation → workspaceRelation across schema, DB, router, and UI
- Rename MemberRelation type → WorkspaceRelation everywhere
- Create canonical UserPlanFeatures/UserPurchase module in trpc-interface
- Make userPlanFeatures non-optional in AppContext
- Separate purchases from UserPlanFeatures
- Compute workspaceRelation in route loaders instead of consumer sites
- Add $workspaceRelation atom, use real relation in $permissions computed
- Remove permissions prop-drilling from all dashboard components
- Leaf components use useStore($permissions) directly
- Create setSharedStores() for unified store initialization
- Combine workspace + membership into single PostgREST query in builder route
- Replace purchases.length checks with canDownloadAssets/canRestoreBackups
- getUserPlanFeatures() → getUserPlanInfo() returning { userPlanFeatures, purchases }
2026-03-14 14:14:14 +00:00
Oleg Isonen bd3f596247 feat: workspace member permissions and plan-based action gating
- Add unified getPermissions() combining role + plan permissions
- Gate project actions (create, delete, publish, share, etc.) by workspace role
- Introduce MemberRelation schema (owners/admins/builders/viewers)
- Compute $permissions from $userPlanFeatures + $authPermit in nano-states
- Set $userPlanFeatures globally in DashboardSetup (matching builder pattern)
- Add workspace dialogs for managing members and invitations
- Enforce permissions across dashboard, builder, and settings UI
2026-03-14 11:57:07 +00:00
Oleg Isonen c47672144d feat: add workspace selector and dialogs stories, fix missing feature-flags dep 2026-03-14 01:58:08 +00:00
Oleg Isonen aac71ffaa8 fix: add WorkspaceMember FK/index, clone workspace inheritance, addMember response parity 2026-03-14 01:47:35 +00:00
Oleg Isonen ed6ffc24f1 fix: workspace security hardening and cleanup\n\n- Add membership check when creating projects in a workspace\n- Remove placeholder user creation on invite (prevent DB pollution)\n- Show invited emails client-side to prevent email enumeration\n- Show only email in member rows (no username leak)\n- Throw on workspace plan resolution error instead of silent fallback\n- DRY navigation items in dashboard sidebar\n- Replace null with empty string in listMembers return\n- Restore useEffect in DashboardSetup to fix React render warning 2026-03-14 01:27:53 +00:00
Oleg Isonen 8a7f98b3f9 fix: code review fixes — shared soft-delete, project ownership, cleanup
- Extract softDeleteProject helper so unique domain invariant lives in one place
- Projects created in a workspace are owned by workspace owner, not creator
- Remove unnecessary useEffect around $data.set
- Remove unused parseTrpcError helper
- Remove unsafe `as TokenAuthPermit` cast
- Add sortWorkspaces tests
- Document idempotent retry safety in workspace remove()
2026-03-14 00:46:40 +00:00
Oleg Isonen ee6a830d82 feat: delete workspace with projects and redirect on stale workspace URL
- Backend: accept deleteProjects flag to soft-delete all projects before removing workspace
- Frontend: warning text mentions all projects will be deleted, with 'All projects' in red
- Dashboard: detect stale workspaceId in URL and redirect to default workspace
2026-03-13 23:36:46 +00:00
Oleg Isonen 0fde5063fb feat: workspace ownership-based UI restrictions and avatar
- Pass userId to WorkspaceSelector for ownership checks
- Disable Rename/Delete menu items for non-owners
- Hide invite input and remove buttons for non-owners in ManageMembersDialog
- Add empty state for member list
- Add Avatar with small size variant (data-size attribute) to workspace selector
- Use userId prop instead of isOwner boolean for future role extensibility
2026-03-13 21:40:03 +00:00
Oleg Isonen a1a4410353 feat: workspace management dialogs and UI improvements
- Add workspace dialogs: create, rename, manage members, delete
- Rewrite workspace selector as dropdown menu with action items
- Support comma-separated multi-email member invites
- Create placeholder users for non-existing email invites
- Add ScrollAreaNative component with native thin scrollbar
- Show newest members first in member list
- Preserve workspaceId query param in navigation links
- Fix DashboardSetup to use useEffect for data sync
2026-03-13 12:33:55 +00:00
Oleg Isonen ed493d1e3a feat: workspace selector with ghost Select, remove collapsible section\n\n- Add color='ghost' variant to SelectButton (transparent bg, hover highlight)\n- Pass color prop through Select to SelectButton\n- Rewrite workspace selector to use Select with color='ghost'\n- Render workspace selector directly in sidebar nav (no CollapsibleSection) 2026-03-12 22:11:27 +00:00
Oleg Isonen 2a04b0eb50 feat: workspace members get access to workspace projects\n\n- Add WorkspaceProjectAuthorization SQL view (workspace owner = own, members = their relation)\n- Update authorization check() to query workspace view when flag is on\n- Dashboard findMany filters by workspaceId instead of userId for workspace members\n- Builder resolves plan features from workspace owner when project belongs to a workspace\n- Add @webstudio-is/feature-flags dependency to trpc-interface and dashboard packages 2026-03-12 21:22:51 +00:00
Oleg Isonen 4748940abd feat(workspaces): workspace member management backend (Stage 6)
Add/remove/list workspace members by email.

- addMember: owner-only, looks up user by email, inserts as
  administrator, rejects duplicates and self-add
- removeMember: owner-only, prevents removing the owner
- listMembers: visible to owner and members, returns user email/username

tRPC procedures: workspace.addMember, workspace.removeMember,
workspace.listMembers.
2026-03-12 20:59:28 +00:00
Oleg Isonen 0cf22c7639 feat(workspaces): project-workspace binding (Stage 5)
Projects are created inside a workspace and listed per workspace.

- project.create accepts optional workspaceId, sets it on the new project
- dashboard findMany accepts optional workspaceId filter
- Dashboard route loader loads workspaces list and reads selected
  workspace from cookie when the workspaces flag is on
- DashboardData type extended with workspaces and currentWorkspaceId

When the flag is off, all behavior is unchanged.
2026-03-12 20:52:06 +00:00
Oleg Isonen b8e8b401d5 feat(workspaces): workspace CRUD backend (Stage 4)
Add create, rename, remove, and findMany functions for workspaces.
- create: non-default workspace with name validation (min 2 chars)
- rename: owner-only, with name validation
- remove: owner-only, rejects default workspace and non-empty workspaces
- findMany: returns owned + member-of workspaces, default first

Wire workspace tRPC router into the app router with matching
procedures: workspace.create, workspace.rename, workspace.delete,
workspace.list.
2026-03-12 20:38:16 +00:00
Oleg Isonen b545d2a1b4 feat(workspaces): rename default workspace to "My workspace" 2026-03-12 20:19:28 +00:00
Oleg Isonen 9cd4531ad2 feat(workspaces): default workspace provisioning (Stage 3)
- Create default "Personal" workspace at user signup in genericCreateAccount
- Add data migration to backfill existing users with default workspaces
- Assign unassigned projects to their owner's default workspace
- Add Workspace type export from @webstudio-is/project
- Regenerate PostgREST types with Workspace/WorkspaceMember tables
- Add workspaceId to storybook/test mock data
- Add @webstudio-is/postgrest dependency to project package
2026-03-12 20:15:11 +00:00
Oleg Isonen 00bc43680e feat(workspaces): add database schema and migration (Stage 2)\n\n- Add Workspace model (id, name, isDefault, createdAt, userId)\n- Add WorkspaceMember model (workspaceId, userId, relation) with CASCADE delete\n- Add optional workspaceId FK on Project (ON DELETE SET NULL)\n- Drop unused Team model and User.teamId column\n- Recreate DashboardProject view with workspaceId column\n- Recreate latestBuildVirtual wrapper using LATERAL join\n- Remove teamId from dashboard storybook mock\n- Partial unique index enforces one default workspace per user 2026-03-12 19:50:39 +00:00
Oleg Isonen 4438b76b26 feat: add workspaces feature flag (Stage 1) 2026-03-12 19:40:53 +00:00
Oleg Isonen 994a4f787a feat: Add delete unused assets command and dialog as well as button in assets panel (#5635)
- Add brush-cleaning icon and regenerate icons package
- Add delete unused assets command to command panel
- Add DeleteUnusedAssetsDialog with scrollable asset list
- Add icon button to assets panel header for quick access
- Export calculateUsagesByAssetId from asset-info
- Add autoFocus to Delete button in all delete-unused dialogs"

## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-03-10 12:49:39 +01:00
Oleg Isonen 04188dbbf4 feat: CSS Grid UI (#5614)
## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-03-08 10:52:21 +01:00
Oleg Isonen cc4c9c6565 fix: remove unusable filter from allowedArrayMethods in expressions (#5627)
filter requires a callback (arrow function) which is blocked by the
linter's blanket "Functions are not supported" rule, making it
effectively dead code. Remove it and update all related tests.

## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-02-26 20:39:46 +01:00
Oleg Isonen 348d049ed2 fix: add authorization checks (#5622)
closes https://github.com/webstudio-is/webstudio/issues/5621

to publishedBuilds and findManyByIds en…dpoints

- Add getProjectPermit check to publishedBuilds endpoint to verify user
has access
- Add userId filtering to findManyByIds to only return user's own
projects or approved marketplace templates
- Maintain belt-and-suspenders approach with both authType check and
permit verification

## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-02-21 03:18:56 +01:00
Oleg Isonen 9f497a3513 feat: Redirects improvements (#5619)
Show a warning banner when a redirect path matches the current page
path, indicating the redirect will override access to the page.

Changes:
- Add PanelBanner component with warning variant to page settings
- Implement findMatchingRedirect utility to detect redirect conflicts
- Show contextual warning with link to Redirects settings section
- Add comprehensive tests for redirect conflict detection

Code quality:
- Replace 'return undefined' with 'return' per style guide
- Use 'return null' for React components returning nothing
2026-02-19 11:26:07 +01:00
Bogdan Chadkin 942b81b8ff refactor: upgrade colorjs.io to v0.6 and adopt functional API (#5617)
## Summary

Upgrades colorjs.io from v0.5.x to v0.6.x and adopts the new functional
API to fix TypeScript compatibility issues and reduce bundle size.

## Breaking Changes in v0.6

This release includes two major changes from colorjs.io that required
code updates:

1. `null` instead of `NaN` for "none" values — Coordinates now use
`number | null` instead of the custom `Number` instance that previously
used `"none"` strings. This eliminates runtime casting and improves
TypeScript DX.

2. Plain numbers instead of `Number` objects — Coordinates are now plain
number primitives rather than `Number` objects with parsing metadata,
improving performance and bundle size.

## Changes Made

- Upgraded colorjs.io to v0.6.x
- Adopted functional API (`/fn` entry point) for tree-shakeable imports
and reduced bundle size
- Updated coordinate handling to use `number | null` directly instead of
custom `Number` instances with `"none"` values
- Removed runtime casting previously required for TypeScript
compatibility
- Aligned with engramma and hdr-color-input — both already use the
functional style, enabling code deduplication

## Migration Notes

See [colorjs.io v0.6.0 release
notes](https://github.com/color-js/color.js/releases/tag/v0.6.0) for
full details on the breaking changes.
2026-02-16 12:26:56 +03:00
Oleg Isonen 2a49a9f1fe feat: Add safe mode (#5612)
- Changed safe mode detection from .has() to strict === 'true' check
- Made safemode a required boolean parameter in builderPath/builderUrl
- Added 'Open in safe mode' option to dashboard project menu
- Added safe mode indicator button with shield icon in topbar
- Safe mode now prevents all script execution in HTML embeds
- Added isSafeMode to React SDK context
- Added test coverage for safe mode in HTML embed component

## Description

1. What is this PR about (link the issue and add a short description)

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
2026-02-10 23:13:43 +01:00
Oleg Isonen d339dc55cf feat: Add token conflict detection and resolution for marketplace templates (#5609)
- Add Token class and token() helper in template package for JSX token
support
- Refactor insertFragmentWithConflictResolution to
detectFragmentTokenConflicts
- Refactor insertPageWithConflictResolution to detectPageTokenConflicts
- Move dialog display to callers for better testability
- Add conflictResolution parameter to page-utils
- Add comprehensive tests for token functionality and conflict detection
- Fix bug: remove .values() call on arrays in breakpoint handling
2026-02-05 22:34:17 +01:00