From c7d57c60cbc330997ef277e0c951aaa8f1ae725e Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 16 Apr 2026 03:50:22 +0900 Subject: [PATCH 1/7] chore(editor): apply oxlint --fix for no-map-spread Replace `.map((x) => ({ a, ...x }))` with `Object.assign({ a }, x)` in 3 files to satisfy oxc(no-map-spread). Functionally equivalent; avoids the spread allocation pattern flagged as inefficient. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../(data)/table/[tablename]/definition/page.tsx | 10 +++++----- .../uxhost-settings-keyboardshortcuts.tsx | 7 +++---- editor/scaffolds/options/options-edit.tsx | 14 ++++++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/editor/app/(workbench)/[org]/[proj]/[id]/data/(data)/table/[tablename]/definition/page.tsx b/editor/app/(workbench)/[org]/[proj]/[id]/data/(data)/table/[tablename]/definition/page.tsx index 660fc8f86a..37cc0ad286 100644 --- a/editor/app/(workbench)/[org]/[proj]/[id]/data/(data)/table/[tablename]/definition/page.tsx +++ b/editor/app/(workbench)/[org]/[proj]/[id]/data/(data)/table/[tablename]/definition/page.tsx @@ -45,12 +45,12 @@ export default function TableDefinitionPage(props: { (name) => name !== tb.name ); return schema_other_table_names.map((name) => { - return { - name, - ...SupabasePostgRESTOpenApi.parse_supabase_postgrest_schema_definition( + return Object.assign( + { name }, + SupabasePostgRESTOpenApi.parse_supabase_postgrest_schema_definition( schema_definitions[name] - ), - }; + ) + ); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [tb]); diff --git a/editor/grida-canvas-hosted/playground/uxhost-settings-keyboardshortcuts.tsx b/editor/grida-canvas-hosted/playground/uxhost-settings-keyboardshortcuts.tsx index 91aaef571c..0d966b1758 100644 --- a/editor/grida-canvas-hosted/playground/uxhost-settings-keyboardshortcuts.tsx +++ b/editor/grida-canvas-hosted/playground/uxhost-settings-keyboardshortcuts.tsx @@ -123,10 +123,9 @@ export function KeyboardShortcuts() { const [searchQuery, setSearchQuery] = useState(""); const filteredActions = useMemo(() => { - const actionsWithId = Object.entries(actions).map(([id, action]) => ({ - id, - ...action, - })); + const actionsWithId = Object.entries(actions).map(([id, action]) => + Object.assign({ id }, action) + ); if (!searchQuery.trim()) { return actionsWithId; diff --git a/editor/scaffolds/options/options-edit.tsx b/editor/scaffolds/options/options-edit.tsx index 72b0fd418e..aae20ae1fd 100644 --- a/editor/scaffolds/options/options-edit.tsx +++ b/editor/scaffolds/options/options-edit.tsx @@ -87,8 +87,10 @@ export function initialOptionsEditState(init: { (a, b) => (a.index || -1) - (b.index || -1) ); const allitems = [ - ...sorted_options.map((_) => ({ type: "option" as const, ..._ })), - ...sorted_optgroups.map((_) => ({ type: "optgroup" as const, ..._ })), + ...sorted_options.map((_) => Object.assign({ type: "option" as const }, _)), + ...sorted_optgroups.map((_) => + Object.assign({ type: "optgroup" as const }, _) + ), ].map((_, i) => ({ ..._, index: i })); const indexed_options: Option[] = allitems.filter( (_) => _.type === "option" @@ -297,8 +299,12 @@ export function OptionsEdit({ const items: RowItem[] = useMemo( () => [ - ...(optgroups || []).map((o) => ({ type: "optgroup" as const, ...o })), - ...(options || []).map((o) => ({ type: "option" as const, ...o })), + ...(optgroups || []).map((o) => + Object.assign({ type: "optgroup" as const }, o) + ), + ...(options || []).map((o) => + Object.assign({ type: "option" as const }, o) + ), ].sort((a, b) => (a.index || 0) - (b.index || 0)), [options, optgroups] ); From 0bbdb8e77976d67334af8cf50dc8775f84485b0b Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 16 Apr 2026 04:06:52 +0900 Subject: [PATCH 2/7] chore(oxlint): typescript/no-import-type-side-effects --- .oxlintrc.jsonc | 5 +++++ .../[campaign_id]/participants/import/route.ts | 2 +- .../(canvas)/canvas/tools/ai/_components/canvas.tsx | 4 ++-- editor/app/(canvas)/canvas/tools/ai/page.tsx | 4 ++-- editor/app/(library)/library/[t]/page.tsx | 2 +- editor/app/(tenant)/~/[tenant]/(e)/d/e/[id]/layout.tsx | 2 +- .../(tools)/(playground)/playground/image/layout.tsx | 2 +- .../_enterprise/west-referral-duo-001-editor.tsx | 2 +- editor/app/(www)/(ai)/ai/models/page.tsx | 2 +- editor/app/(www)/(database)/database/page.tsx | 2 +- editor/app/(www)/(database)/database/supabase/page.tsx | 2 +- editor/app/(www)/(forms)/forms/page.tsx | 2 +- editor/app/(www)/(home)/_home/content-1.tsx | 2 +- editor/app/(www)/(sdk)/sdk/page.tsx | 2 +- editor/app/(www)/(slides)/slides/page.tsx | 2 +- .../components/formfield/phone-field/phone-field.tsx | 2 +- editor/components/tag/tag-input.tsx | 2 +- editor/components/ui-forms/toggle-group.tsx | 2 +- editor/grida-canvas/reducers/document.reducer.ts | 2 +- .../reducers/event-target.cem-bitmap.reducer.ts | 2 +- .../reducers/event-target.cem-vector.reducer.ts | 2 +- .../reducers/event-target.cem-width.reducer.ts | 2 +- editor/grida-canvas/reducers/event-target.reducer.ts | 2 +- editor/grida-canvas/reducers/methods/transform.ts | 2 +- editor/grida-canvas/reducers/surface.reducer.ts | 2 +- editor/grida-forms-hosted/json2db.ts | 2 +- .../grida-react-program-context/data-context/array.tsx | 2 +- .../data-context/context.tsx | 2 +- editor/host/auth/use-continue-with-auth.tsx | 2 +- editor/kits/minimal-tiptap/minimal-tiptap-headless.tsx | 2 +- editor/lib/supabase/use-session.ts | 2 +- editor/scaffolds/editor/feed.tsx | 10 +++++----- editor/scaffolds/grid/columns/select-column.tsx | 2 +- editor/scaffolds/sidecontrol/controls/font-family.tsx | 2 +- .../scaffolds/sidecontrol/sidecontrol-doctype-form.tsx | 2 +- editor/scaffolds/workspace/sidebar.tsx | 2 +- 36 files changed, 46 insertions(+), 41 deletions(-) diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index b8a9eeac4a..a2c35ae799 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -13,12 +13,17 @@ "categories": { "correctness": "error", "perf": "warn", + // "restriction": "error", }, "rules": { "typescript/no-explicit-any": "error", // ====================================== // grida-specific overrides: "typescript/no-namespace": "off", + + // restriction + "no-import-type-side-effects": "error", + // "default-case": "error", }, "env": { "builtin": true, diff --git a/editor/app/(api)/private/west/campaigns/[campaign_id]/participants/import/route.ts b/editor/app/(api)/private/west/campaigns/[campaign_id]/participants/import/route.ts index 6847c16754..6bf7c34e2e 100644 --- a/editor/app/(api)/private/west/campaigns/[campaign_id]/participants/import/route.ts +++ b/editor/app/(api)/private/west/campaigns/[campaign_id]/participants/import/route.ts @@ -1,4 +1,4 @@ -import { type Platform } from "@/lib/platform"; +import type { Platform } from "@/lib/platform"; import { createWestReferralClient } from "@/lib/supabase/server"; import { NextRequest, NextResponse } from "next/server"; diff --git a/editor/app/(canvas)/canvas/tools/ai/_components/canvas.tsx b/editor/app/(canvas)/canvas/tools/ai/_components/canvas.tsx index e44d440b4b..a447d9c65d 100644 --- a/editor/app/(canvas)/canvas/tools/ai/_components/canvas.tsx +++ b/editor/app/(canvas)/canvas/tools/ai/_components/canvas.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from "react"; import { cn } from "@/components/lib/utils"; -import { type DeepPartial } from "ai"; -import { type PortableNode } from "../schema"; +import type { DeepPartial } from "ai"; +import type { PortableNode } from "../schema"; const DEFAULT_IFRAME_HTML = ` diff --git a/editor/app/(canvas)/canvas/tools/ai/page.tsx b/editor/app/(canvas)/canvas/tools/ai/page.tsx index ea4fafec5c..25db087d81 100644 --- a/editor/app/(canvas)/canvas/tools/ai/page.tsx +++ b/editor/app/(canvas)/canvas/tools/ai/page.tsx @@ -14,8 +14,8 @@ import { MinimalChatBox } from "@/components/chat"; import { readStreamableValue } from "@ai-sdk/rsc"; import { Canvas } from "./_components/canvas"; import { generate, type UserAttachment } from "./generate"; -import { type DeepPartial } from "ai"; -import { type StreamingResponse } from "./schema"; +import type { DeepPartial } from "ai"; +import type { StreamingResponse } from "./schema"; import { Toggle } from "@/components/ui/toggle"; import { CodeIcon } from "@radix-ui/react-icons"; import { ThemedMonacoEditor } from "@/components/monaco"; diff --git a/editor/app/(library)/library/[t]/page.tsx b/editor/app/(library)/library/[t]/page.tsx index 9f2a25be2d..5125e7c454 100644 --- a/editor/app/(library)/library/[t]/page.tsx +++ b/editor/app/(library)/library/[t]/page.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { type Metadata } from "next"; +import type { Metadata } from "next"; import { getCategory, search } from "../actions"; import { notFound } from "next/navigation"; import Categories from "../_components/categories"; diff --git a/editor/app/(tenant)/~/[tenant]/(e)/d/e/[id]/layout.tsx b/editor/app/(tenant)/~/[tenant]/(e)/d/e/[id]/layout.tsx index 3c2aed8530..5cbc77f7c7 100644 --- a/editor/app/(tenant)/~/[tenant]/(e)/d/e/[id]/layout.tsx +++ b/editor/app/(tenant)/~/[tenant]/(e)/d/e/[id]/layout.tsx @@ -1,6 +1,6 @@ import { notFound } from "next/navigation"; import { service_role } from "@/lib/supabase/server"; -import { type Metadata, type Viewport } from "next"; +import type { Metadata, Viewport } from "next"; import { Inconsolata, Inter, Lora } from "next/font/google"; import type { FormDocument } from "@/grida-forms-hosted/types"; import { ThemeProvider } from "@/components/theme-provider"; diff --git a/editor/app/(tools)/(playground)/playground/image/layout.tsx b/editor/app/(tools)/(playground)/playground/image/layout.tsx index ff403b58a8..8cc642e928 100644 --- a/editor/app/(tools)/(playground)/playground/image/layout.tsx +++ b/editor/app/(tools)/(playground)/playground/image/layout.tsx @@ -1,4 +1,4 @@ -import { type Metadata } from "next"; +import type { Metadata } from "next"; export const metadata: Metadata = { title: "Image Playground", diff --git a/editor/app/(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx b/editor/app/(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx index 429e420256..beb3a39831 100644 --- a/editor/app/(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx +++ b/editor/app/(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx @@ -16,7 +16,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import type { TemplateData } from "@/theme/templates/enterprise/west-referral/templates"; import { OpenInNewWindowIcon } from "@radix-ui/react-icons"; import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"; -import { type WWWTemplateEditorInstance } from "@/scaffolds/platform/www"; +import type { WWWTemplateEditorInstance } from "@/scaffolds/platform/www"; import assert from "assert"; import { toast } from "sonner"; import { CampaignTemplateDuo001Viewer } from "./template-duo-001-viewer"; diff --git a/editor/app/(www)/(ai)/ai/models/page.tsx b/editor/app/(www)/(ai)/ai/models/page.tsx index af62b6a441..6bc6193d23 100644 --- a/editor/app/(www)/(ai)/ai/models/page.tsx +++ b/editor/app/(www)/(ai)/ai/models/page.tsx @@ -1,5 +1,5 @@ import type { FC } from "react"; -import { type Metadata } from "next"; +import type { Metadata } from "next"; import ai from "@/lib/ai"; import { Card, diff --git a/editor/app/(www)/(database)/database/page.tsx b/editor/app/(www)/(database)/database/page.tsx index 3e4be911ca..4e5e7e2a73 100644 --- a/editor/app/(www)/(database)/database/page.tsx +++ b/editor/app/(www)/(database)/database/page.tsx @@ -1,6 +1,6 @@ import React from "react"; import Page from "./_page"; -import { type Metadata } from "next"; +import type { Metadata } from "next"; export const metadata: Metadata = { title: "Grida Database | Your visual Data backend", diff --git a/editor/app/(www)/(database)/database/supabase/page.tsx b/editor/app/(www)/(database)/database/supabase/page.tsx index 649bf03496..e5e432603e 100644 --- a/editor/app/(www)/(database)/database/supabase/page.tsx +++ b/editor/app/(www)/(database)/database/supabase/page.tsx @@ -1,6 +1,6 @@ import React from "react"; import Page from "./_page"; -import { type Metadata } from "next"; +import type { Metadata } from "next"; export const metadata: Metadata = { title: "Supabase Admin Panel | Visual Database Interface for Supabase", diff --git a/editor/app/(www)/(forms)/forms/page.tsx b/editor/app/(www)/(forms)/forms/page.tsx index ea0c924a72..1542423909 100644 --- a/editor/app/(www)/(forms)/forms/page.tsx +++ b/editor/app/(www)/(forms)/forms/page.tsx @@ -1,4 +1,4 @@ -import { type Metadata } from "next"; +import type { Metadata } from "next"; import { GridaLogo } from "@/components/grida-logo"; import { Button } from "@/components/ui/button"; import { Section } from "@/www/ui/section"; diff --git a/editor/app/(www)/(home)/_home/content-1.tsx b/editor/app/(www)/(home)/_home/content-1.tsx index 61c61d9b26..e97c13405e 100644 --- a/editor/app/(www)/(home)/_home/content-1.tsx +++ b/editor/app/(www)/(home)/_home/content-1.tsx @@ -2,7 +2,7 @@ import React from "react"; import Image from "next/image"; import { Carousel, CarouselContent, CarouselItem } from "@/www/ui/carousel"; -import { type CarouselApi } from "@/www/ui/carousel"; +import type { CarouselApi } from "@/www/ui/carousel"; import Autoplay from "embla-carousel-autoplay"; import { cn } from "@/components/lib/utils"; import { motion } from "motion/react"; diff --git a/editor/app/(www)/(sdk)/sdk/page.tsx b/editor/app/(www)/(sdk)/sdk/page.tsx index cb9e165eb7..46c1c600b6 100644 --- a/editor/app/(www)/(sdk)/sdk/page.tsx +++ b/editor/app/(www)/(sdk)/sdk/page.tsx @@ -6,7 +6,7 @@ import Hero from "./_sections/hero"; import Features from "./_sections/features"; import SectionMainDemo from "./_sections/demo"; import FAQ from "./_sections/faq"; -import { type Metadata } from "next"; +import type { Metadata } from "next"; export const metadata: Metadata = { title: "Grida Canvas SDK - Build Your Own Canvas Framework | Open Source", diff --git a/editor/app/(www)/(slides)/slides/page.tsx b/editor/app/(www)/(slides)/slides/page.tsx index 293adaf6e4..40a4a83e5b 100644 --- a/editor/app/(www)/(slides)/slides/page.tsx +++ b/editor/app/(www)/(slides)/slides/page.tsx @@ -1,4 +1,4 @@ -import { type Metadata } from "next"; +import type { Metadata } from "next"; import { Section } from "@/www/ui/section"; import Header from "@/www/header"; import FooterWithCTA from "@/www/footer-with-cta"; diff --git a/editor/components/formfield/phone-field/phone-field.tsx b/editor/components/formfield/phone-field/phone-field.tsx index 2cfe66bb0f..c8950172ba 100644 --- a/editor/components/formfield/phone-field/phone-field.tsx +++ b/editor/components/formfield/phone-field/phone-field.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useState } from "react"; import { PhoneInput } from "@/components/extension/phone-input"; -import { type CountryCode } from "libphonenumber-js/core"; +import type { CountryCode } from "libphonenumber-js/core"; const PhoneFieldDefaultCountryContext = React.createContext< CountryCode | undefined diff --git a/editor/components/tag/tag-input.tsx b/editor/components/tag/tag-input.tsx index 914762a24a..b2ff6c5c37 100644 --- a/editor/components/tag/tag-input.tsx +++ b/editor/components/tag/tag-input.tsx @@ -3,7 +3,7 @@ import React, { useMemo } from "react"; import { Input } from "../ui/input"; import { Button } from "../ui/button"; -import { type VariantProps } from "class-variance-authority"; +import type { VariantProps } from "class-variance-authority"; import { TagPopover } from "./tag-popover"; import { TagList } from "./tag-list"; import { tagVariants } from "./tag"; diff --git a/editor/components/ui-forms/toggle-group.tsx b/editor/components/ui-forms/toggle-group.tsx index 83d4c3b1dc..f7c109fbdd 100644 --- a/editor/components/ui-forms/toggle-group.tsx +++ b/editor/components/ui-forms/toggle-group.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"; -import { type VariantProps } from "class-variance-authority"; +import type { VariantProps } from "class-variance-authority"; import { cn } from "@/components/lib/utils"; import { toggleVariants } from "@/components/ui/toggle"; diff --git a/editor/grida-canvas/reducers/document.reducer.ts b/editor/grida-canvas/reducers/document.reducer.ts index 6c251b522d..5981d8ad73 100644 --- a/editor/grida-canvas/reducers/document.reducer.ts +++ b/editor/grida-canvas/reducers/document.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import { updateState } from "./utils/immer"; import type { DocumentAction, diff --git a/editor/grida-canvas/reducers/event-target.cem-bitmap.reducer.ts b/editor/grida-canvas/reducers/event-target.cem-bitmap.reducer.ts index 898a6f2356..525e95339c 100644 --- a/editor/grida-canvas/reducers/event-target.cem-bitmap.reducer.ts +++ b/editor/grida-canvas/reducers/event-target.cem-bitmap.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import kolor from "@grida/color"; import { editor } from "@/grida-canvas"; import { dq } from "@/grida-canvas/query"; diff --git a/editor/grida-canvas/reducers/event-target.cem-vector.reducer.ts b/editor/grida-canvas/reducers/event-target.cem-vector.reducer.ts index 8459104199..70d276d23c 100644 --- a/editor/grida-canvas/reducers/event-target.cem-vector.reducer.ts +++ b/editor/grida-canvas/reducers/event-target.cem-vector.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import type { EditorEventTarget_PointerDown, diff --git a/editor/grida-canvas/reducers/event-target.cem-width.reducer.ts b/editor/grida-canvas/reducers/event-target.cem-width.reducer.ts index efb24a0b59..6b792b1168 100644 --- a/editor/grida-canvas/reducers/event-target.cem-width.reducer.ts +++ b/editor/grida-canvas/reducers/event-target.cem-width.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import type { EditorEventTarget_PointerDown, diff --git a/editor/grida-canvas/reducers/event-target.reducer.ts b/editor/grida-canvas/reducers/event-target.reducer.ts index 137a02e7fb..3055e75c8f 100644 --- a/editor/grida-canvas/reducers/event-target.reducer.ts +++ b/editor/grida-canvas/reducers/event-target.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import { safeOriginal } from "./utils/immer"; import { updateState } from "./utils/immer"; diff --git a/editor/grida-canvas/reducers/methods/transform.ts b/editor/grida-canvas/reducers/methods/transform.ts index 43030f857a..c5bde1e8a3 100644 --- a/editor/grida-canvas/reducers/methods/transform.ts +++ b/editor/grida-canvas/reducers/methods/transform.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import { safeOriginal } from "../utils/immer"; import { editor } from "@/grida-canvas"; import { self_insertSubDocument } from "./insert"; diff --git a/editor/grida-canvas/reducers/surface.reducer.ts b/editor/grida-canvas/reducers/surface.reducer.ts index a8bcbe9bf6..497cf55dd5 100644 --- a/editor/grida-canvas/reducers/surface.reducer.ts +++ b/editor/grida-canvas/reducers/surface.reducer.ts @@ -1,4 +1,4 @@ -import { type Draft } from "immer"; +import type { Draft } from "immer"; import { updateState } from "./utils/immer"; import type { SurfaceAction, EditorSurface_StartGesture } from "../action"; diff --git a/editor/grida-forms-hosted/json2db.ts b/editor/grida-forms-hosted/json2db.ts index 25a8fee170..3599e50308 100644 --- a/editor/grida-forms-hosted/json2db.ts +++ b/editor/grida-forms-hosted/json2db.ts @@ -1,5 +1,5 @@ import { FormRenderTree } from "@/grida-forms/lib"; -import { type JSONForm } from "@/types"; +import type { JSONForm } from "@/types"; import type { Database } from "@app/database"; import { toArrayOf } from "@/types/utility"; import { SupabaseClient } from "@supabase/supabase-js"; diff --git a/editor/grida-react-program-context/data-context/array.tsx b/editor/grida-react-program-context/data-context/array.tsx index 11564d10b2..6a2d785ccb 100644 --- a/editor/grida-react-program-context/data-context/array.tsx +++ b/editor/grida-react-program-context/data-context/array.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { type access } from "@grida/tokens"; +import type { access } from "@grida/tokens"; import { useValue } from "./use"; import { ScopedVariableBoundary } from "./context"; diff --git a/editor/grida-react-program-context/data-context/context.tsx b/editor/grida-react-program-context/data-context/context.tsx index 5a548e41f7..176d1be183 100644 --- a/editor/grida-react-program-context/data-context/context.tsx +++ b/editor/grida-react-program-context/data-context/context.tsx @@ -6,7 +6,7 @@ import React, { FC, useMemo, } from "react"; -import { type access } from "@grida/tokens"; +import type { access } from "@grida/tokens"; interface RootDataContextProps { rootData: Record; diff --git a/editor/host/auth/use-continue-with-auth.tsx b/editor/host/auth/use-continue-with-auth.tsx index 9650ff10bf..df4dc90e3e 100644 --- a/editor/host/auth/use-continue-with-auth.tsx +++ b/editor/host/auth/use-continue-with-auth.tsx @@ -3,7 +3,7 @@ import { createPortal } from "react-dom"; import { createContext, useContext, useEffect, useRef, useState } from "react"; import { ContinueWithAuthDialog } from "./continue-with-auth-dialog"; -import { type Session } from "@supabase/supabase-js"; +import type { Session } from "@supabase/supabase-js"; import useSession from "@/lib/supabase/use-session"; import usePendingCallback from "@/hooks/use-pending-callback"; diff --git a/editor/kits/minimal-tiptap/minimal-tiptap-headless.tsx b/editor/kits/minimal-tiptap/minimal-tiptap-headless.tsx index d04c5e3f86..befefecafb 100644 --- a/editor/kits/minimal-tiptap/minimal-tiptap-headless.tsx +++ b/editor/kits/minimal-tiptap/minimal-tiptap-headless.tsx @@ -18,7 +18,7 @@ import { ResetMarksOnEnter, } from "./extensions"; import { cn } from "@/components/lib/utils"; -import { type MinimalTiptapProps } from "./minimal-tiptap"; +import type { MinimalTiptapProps } from "./minimal-tiptap"; const createHeadlessExtensions = ({ placeholder }: { placeholder: string }) => [ StarterKit.configure({ diff --git a/editor/lib/supabase/use-session.ts b/editor/lib/supabase/use-session.ts index 4105571a38..4ad54e772f 100644 --- a/editor/lib/supabase/use-session.ts +++ b/editor/lib/supabase/use-session.ts @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import { createBrowserClient } from "@/lib/supabase/client"; -import { type Session } from "@supabase/supabase-js"; +import type { Session } from "@supabase/supabase-js"; export default function useSession() { const client = useMemo(() => createBrowserClient(), []); diff --git a/editor/scaffolds/editor/feed.tsx b/editor/scaffolds/editor/feed.tsx index 9cbd9e3d66..0481600320 100644 --- a/editor/scaffolds/editor/feed.tsx +++ b/editor/scaffolds/editor/feed.tsx @@ -16,11 +16,11 @@ import { XPostgrestQuery } from "@/lib/supabase-postgrest/builder"; import equal from "deep-equal"; import { PrivateEditorApi } from "@/lib/private"; import { EditorSymbols } from "./symbols"; -import { - type GDocSchemaTableProviderGrida, - type TablespaceSchemaTableStreamType, - type TablespaceTransaction, - type TVirtualRow, +import type { + GDocSchemaTableProviderGrida, + TablespaceSchemaTableStreamType, + TablespaceTransaction, + TVirtualRow, } from "./state"; import PQueue from "p-queue"; import assert from "assert"; diff --git a/editor/scaffolds/grid/columns/select-column.tsx b/editor/scaffolds/grid/columns/select-column.tsx index 3835ca9f24..6c9babec28 100644 --- a/editor/scaffolds/grid/columns/select-column.tsx +++ b/editor/scaffolds/grid/columns/select-column.tsx @@ -7,7 +7,7 @@ import { RenderHeaderCellProps, useRowSelection, } from "react-data-grid"; -import { type DGResponseRow } from "../types"; +import type { DGResponseRow } from "../types"; import { CellRoot } from "../cells"; import { useCellRootProps } from "../providers"; import { SelectColumnHeaderCell } from "../cells/column-select-header-cell"; diff --git a/editor/scaffolds/sidecontrol/controls/font-family.tsx b/editor/scaffolds/sidecontrol/controls/font-family.tsx index 28362456f8..953e4512cc 100644 --- a/editor/scaffolds/sidecontrol/controls/font-family.tsx +++ b/editor/scaffolds/sidecontrol/controls/font-family.tsx @@ -22,7 +22,7 @@ import { useVirtualizer } from "@tanstack/react-virtual"; import { useGridaFontsSearch } from "@/hooks/use-grida-fonts-search"; import { cn } from "@/components/lib/utils"; import grida from "@grida/schema"; -import { type GoogleWebFontListItem } from "@grida/fonts/google"; +import type { GoogleWebFontListItem } from "@grida/fonts/google"; import * as google from "@grida/fonts/google"; import { useCurrentEditor, diff --git a/editor/scaffolds/sidecontrol/sidecontrol-doctype-form.tsx b/editor/scaffolds/sidecontrol/sidecontrol-doctype-form.tsx index 4e181a4326..ccc1741149 100644 --- a/editor/scaffolds/sidecontrol/sidecontrol-doctype-form.tsx +++ b/editor/scaffolds/sidecontrol/sidecontrol-doctype-form.tsx @@ -15,7 +15,7 @@ import { } from "@/components/ui/popover"; import { useEditorState, useFormFields } from "@/scaffolds/editor"; import { MixIcon } from "@radix-ui/react-icons"; -import { type tokens } from "@grida/tokens"; +import type { tokens } from "@grida/tokens"; import { toast } from "sonner"; import { FormExpression } from "@/grida-forms/lib/expression"; import { PropertyLine, PropertyLineLabel } from "./ui"; diff --git a/editor/scaffolds/workspace/sidebar.tsx b/editor/scaffolds/workspace/sidebar.tsx index db4f17f7d0..e26450a84b 100644 --- a/editor/scaffolds/workspace/sidebar.tsx +++ b/editor/scaffolds/workspace/sidebar.tsx @@ -29,7 +29,7 @@ import { ChevronDown, Trash2Icon, } from "lucide-react"; -import { type LucideIcon } from "lucide-react"; +import type { LucideIcon } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, From ab892638775e64e3e1d8776e3e4262e11676baf1 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 16 Apr 2026 04:13:49 +0900 Subject: [PATCH 3/7] chore(oxlint): typescript/no-var --- .oxlintrc.jsonc | 5 +++-- editor/grida-canvas/libs/treefy/index.js | 16 ++++++++-------- packages/grida-cmath/index.ts | 23 ++++++++++++----------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index a2c35ae799..9ba3f903cf 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -16,13 +16,14 @@ // "restriction": "error", }, "rules": { - "typescript/no-explicit-any": "error", // ====================================== // grida-specific overrides: - "typescript/no-namespace": "off", + "no-namespace": "off", // restriction + "no-explicit-any": "error", "no-import-type-side-effects": "error", + "no-var": "error", // "default-case": "error", }, "env": { diff --git a/editor/grida-canvas/libs/treefy/index.js b/editor/grida-canvas/libs/treefy/index.js index 44f9a20132..6f2c64f6e5 100644 --- a/editor/grida-canvas/libs/treefy/index.js +++ b/editor/grida-canvas/libs/treefy/index.js @@ -13,7 +13,7 @@ } })(this, function () { function makePrefix(key, last) { - var str = last ? "└" : "├"; + let str = last ? "└" : "├"; if (key) { str += "─ "; } else { @@ -23,8 +23,8 @@ } function filterKeys(obj, hideFunctions) { - var keys = []; - for (var branch in obj) { + const keys = []; + for (let branch in obj) { // always exclude anything in the object's prototype if (!obj.hasOwnProperty(branch)) { continue; @@ -47,7 +47,7 @@ hideFunctions, callback ) { - var line = "", + let line = "", index = 0, lastKey, circular, @@ -82,7 +82,7 @@ // can we descend into the next item? if (!circular && typeof root === "object") { - var keys = filterKeys(root, hideFunctions); + const keys = filterKeys(root, hideFunctions); keys.forEach(function (branch) { // the last key is always printed with a different prefix, so we'll need to know if we have it lastKey = ++index === keys.length; @@ -103,7 +103,7 @@ // -------------------- - var Treeify = {}; + const Treeify = {}; // Treeify.asLines // -------------------- @@ -111,7 +111,7 @@ Treeify.asLines = function (obj, showValues, hideFunctions, lineCallback) { /* hideFunctions and lineCallback are curried, which means we don't break apps using the older form */ - var hideFunctionsArg = + const hideFunctionsArg = typeof hideFunctions !== "function" ? hideFunctions : false; growBranch( ".", @@ -129,7 +129,7 @@ // Outputs the entire tree, returning it as a string with line breaks. Treeify.asTree = function (obj, showValues, hideFunctions) { - var tree = ""; + let tree = ""; growBranch(".", obj, false, [], showValues, hideFunctions, function (line) { tree += line + "\n"; }); diff --git a/packages/grida-cmath/index.ts b/packages/grida-cmath/index.ts index 7f4aeae419..6ab3740425 100644 --- a/packages/grida-cmath/index.ts +++ b/packages/grida-cmath/index.ts @@ -3825,15 +3825,15 @@ namespace cmath { ): number[] { // for more information of where this math came from visit: // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes - var _120 = (cmath.PI * 120) / 180, + const _120 = (cmath.PI * 120) / 180, rad = (cmath.PI / 180) * (+angle || 0); - var res: number[] = []; + let res: number[] = []; - var xy: { x: number; y: number }; + let xy: { x: number; y: number }; const rotate = function (x: number, y: number, rad: number) { - var X = x * cmath.cos(rad) - y * cmath.sin(rad), + const X = x * cmath.cos(rad) - y * cmath.sin(rad), Y = x * cmath.sin(rad) + y * cmath.cos(rad); return { x: X, y: Y }; }; @@ -3848,14 +3848,15 @@ namespace cmath { xy = rotate(x2, y2, -rad); x2 = xy.x; y2 = xy.y; - var x = (x1 - x2) / 2, + const x = (x1 - x2) / 2, y = (y1 - y2) / 2; - var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); + let h = (x * x) / (rx * rx) + (y * y) / (ry * ry); if (h > 1) { h = cmath.sqrt(h); rx = h * rx; ry = h * ry; } + // oxlint-disable-next-line no-var var rx2 = rx * rx, ry2 = ry * ry, k = @@ -3891,9 +3892,9 @@ namespace cmath { cx = recursive[2]; cy = recursive[3]; } - var df = f2 - f1; + let df = f2 - f1; if (cmath.abs(df) > _120) { - var f2old = f2, + const f2old = f2, x2old = x2, y2old = y2; f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); @@ -3907,7 +3908,7 @@ namespace cmath { ]); } df = f2 - f1; - var c1 = cmath.cos(f1), + const c1 = cmath.cos(f1), s1 = cmath.sin(f1), c2 = cmath.cos(f2), s2 = cmath.sin(f2), @@ -3926,8 +3927,8 @@ namespace cmath { } else { // @ts-ignore res = [m2, m3, m4].concat(res).join().split(","); - var newres = []; - for (var i = 0, ii = res.length; i < ii; i++) { + const newres = []; + for (let i = 0, ii = res.length; i < ii; i++) { newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y From d68796b6a329ee8f7aa7348b5acee6a44b25ff10 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 16 Apr 2026 04:42:10 +0900 Subject: [PATCH 4/7] chore(oxlint): import --- .oxlintrc.jsonc | 11 ++++++++++- .../template-builder/widgets/icon.tsx | 1 + editor/instrumentation-client.ts | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index 9ba3f903cf..55b5bb2185 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -6,13 +6,15 @@ "oxc", "react", "react-perf", + "import", + // TODO: // "vitest", // "jsdoc", ], "categories": { "correctness": "error", - "perf": "warn", + // "perf": "warn", // "restriction": "error", }, "rules": { @@ -20,11 +22,18 @@ // grida-specific overrides: "no-namespace": "off", + // ====================================== // restriction "no-explicit-any": "error", "no-import-type-side-effects": "error", "no-var": "error", + // + // "no-invalid-void-type": "error", + // "no-empty-function": "error", + // "no-optional-chaining": "error", + // "no-alert": "error", // "default-case": "error", + // }, "env": { "builtin": true, diff --git a/editor/grida-canvas-react-renderer-dom/template-builder/widgets/icon.tsx b/editor/grida-canvas-react-renderer-dom/template-builder/widgets/icon.tsx index d863a34569..d7fe46b85c 100644 --- a/editor/grida-canvas-react-renderer-dom/template-builder/widgets/icon.tsx +++ b/editor/grida-canvas-react-renderer-dom/template-builder/widgets/icon.tsx @@ -27,6 +27,7 @@ export function IconWidget({ repository, name }: IconWidgetProps) { } function RadixIconWidget({ name }: { name: keyof typeof RadixIcons }) { + // eslint-disable-next-line import/namespace const Component = RadixIcons[name]; if (Component) return ; return <>; diff --git a/editor/instrumentation-client.ts b/editor/instrumentation-client.ts index 802e9d18d2..f4681a65fb 100644 --- a/editor/instrumentation-client.ts +++ b/editor/instrumentation-client.ts @@ -9,6 +9,7 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, // Add optional integrations for additional features + // eslint-disable-next-line import/namespace integrations: [Sentry.replayIntegration()], // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. @@ -26,4 +27,5 @@ Sentry.init({ debug: false, }); +// eslint-disable-next-line import/namespace export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; From 6a6a9d0f97a0e267d61d4dc1f78d8ca08d4d4c79 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 16 Apr 2026 04:56:12 +0900 Subject: [PATCH 5/7] chore(oxlint): jsx-a11y --- .oxlintrc.jsonc | 4 +++- apps/viewer/app/v1/pdf/[[...file]]/viewer.tsx | 1 + .../(canvas)/canvas/tools/ai/_components/canvas.tsx | 1 + editor/app/(www)/(figma)/figma/vscode/page.tsx | 1 + editor/app/(www)/(home)/_home/index.tsx | 6 +++++- editor/app/(www)/(sdk)/sdk/_sections/demo.tsx | 6 +++++- .../(www)/(slides)/slides/_sections/editor-preview.tsx | 1 + editor/app/(www)/(west)/west/_page.tsx | 1 + editor/app/global-error.tsx | 2 +- editor/components/mediaviewer/index.tsx | 1 + .../grida-canvas-react-renderer-dom/nodes/iframe.tsx | 1 + editor/grida-canvas-react/components/image.tsx | 2 +- editor/scaffolds/playground-forms/preview/index.tsx | 10 +++++++++- .../storage/dialog-create-sharable-link/index.tsx | 10 +++++++++- editor/theme/templates/formcomplete/preview.tsx | 2 ++ editor/www/footer-with-cta.tsx | 1 + 16 files changed, 43 insertions(+), 7 deletions(-) diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index 55b5bb2185..df2e89eb03 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -9,13 +9,15 @@ "import", // TODO: + // "jsx-a11y", // "vitest", // "jsdoc", ], "categories": { "correctness": "error", - // "perf": "warn", + // "suspicious": "error", // "restriction": "error", + // "perf": "warn", }, "rules": { // ====================================== diff --git a/apps/viewer/app/v1/pdf/[[...file]]/viewer.tsx b/apps/viewer/app/v1/pdf/[[...file]]/viewer.tsx index 3fa22bc083..e17688c720 100644 --- a/apps/viewer/app/v1/pdf/[[...file]]/viewer.tsx +++ b/apps/viewer/app/v1/pdf/[[...file]]/viewer.tsx @@ -29,6 +29,7 @@ export default function PDFViewer({ return (