···11-// Generated with claude code, sonnet 4.5
22-/**
33- * Scrolls an element into view within a scrolling container using Intersection Observer
44- * and the scrollTo API, instead of the native scrollIntoView.
55- *
66- * @param elementId - The ID of the element to scroll into view
77- * @param scrollContainerId - The ID of the scrolling container (defaults to "pages")
88- * @param threshold - Intersection observer threshold (0-1, defaults to 0.2 for 20%)
99- */
11+import { scrollIntoViewIfNeeded } from "./scrollIntoViewIfNeeded";
22+103export function scrollIntoView(
114 elementId: string,
125 scrollContainerId: string = "pages",
136 threshold: number = 0.9,
147) {
158 const element = document.getElementById(elementId);
1616- const scrollContainer = document.getElementById(scrollContainerId);
1717-1818- if (!element || !scrollContainer) {
1919- console.warn(`scrollIntoView: element or container not found`, {
2020- elementId,
2121- scrollContainerId,
2222- element,
2323- scrollContainer,
2424- });
2525- return;
2626- }
2727-2828- // Create an intersection observer to check if element is visible
2929- const observer = new IntersectionObserver(
3030- (entries) => {
3131- const entry = entries[0];
3232-3333- // If element is not sufficiently visible, scroll to it
3434- if (!entry.isIntersecting || entry.intersectionRatio < threshold) {
3535- const elementRect = element.getBoundingClientRect();
3636- const containerRect = scrollContainer.getBoundingClientRect();
3737-3838- // Calculate the target scroll position
3939- // We want to center the element horizontally in the container
4040- const targetScrollLeft =
4141- scrollContainer.scrollLeft +
4242- elementRect.left -
4343- containerRect.left -
4444- (containerRect.width - elementRect.width) / 2;
4545-4646- scrollContainer.scrollTo({
4747- left: targetScrollLeft,
4848- behavior: "smooth",
4949- });
5050- }
5151-5252- // Disconnect after checking once
5353- observer.disconnect();
5454- },
5555- {
5656- root: scrollContainer,
5757- threshold: threshold,
5858- },
5959- );
6060-6161- observer.observe(element);
99+ scrollIntoViewIfNeeded(element, false, "smooth");
6210}
···11+create table "public"."atp_poll_votes" (
22+ "uri" text not null,
33+ "record" jsonb not null,
44+ "voter_did" text not null,
55+ "poll_uri" text not null,
66+ "poll_cid" text not null,
77+ "option" text not null,
88+ "indexed_at" timestamp with time zone not null default now()
99+);
1010+1111+alter table "public"."atp_poll_votes" enable row level security;
1212+1313+CREATE UNIQUE INDEX atp_poll_votes_pkey ON public.atp_poll_votes USING btree (uri);
1414+1515+alter table "public"."atp_poll_votes" add constraint "atp_poll_votes_pkey" PRIMARY KEY using index "atp_poll_votes_pkey";
1616+1717+CREATE INDEX atp_poll_votes_poll_uri_idx ON public.atp_poll_votes USING btree (poll_uri);
1818+1919+CREATE INDEX atp_poll_votes_voter_did_idx ON public.atp_poll_votes USING btree (voter_did);
2020+2121+grant delete on table "public"."atp_poll_votes" to "anon";
2222+2323+grant insert on table "public"."atp_poll_votes" to "anon";
2424+2525+grant references on table "public"."atp_poll_votes" to "anon";
2626+2727+grant select on table "public"."atp_poll_votes" to "anon";
2828+2929+grant trigger on table "public"."atp_poll_votes" to "anon";
3030+3131+grant truncate on table "public"."atp_poll_votes" to "anon";
3232+3333+grant update on table "public"."atp_poll_votes" to "anon";
3434+3535+grant delete on table "public"."atp_poll_votes" to "authenticated";
3636+3737+grant insert on table "public"."atp_poll_votes" to "authenticated";
3838+3939+grant references on table "public"."atp_poll_votes" to "authenticated";
4040+4141+grant select on table "public"."atp_poll_votes" to "authenticated";
4242+4343+grant trigger on table "public"."atp_poll_votes" to "authenticated";
4444+4545+grant truncate on table "public"."atp_poll_votes" to "authenticated";
4646+4747+grant update on table "public"."atp_poll_votes" to "authenticated";
4848+4949+grant delete on table "public"."atp_poll_votes" to "service_role";
5050+5151+grant insert on table "public"."atp_poll_votes" to "service_role";
5252+5353+grant references on table "public"."atp_poll_votes" to "service_role";
5454+5555+grant select on table "public"."atp_poll_votes" to "service_role";
5656+5757+grant trigger on table "public"."atp_poll_votes" to "service_role";
5858+5959+grant truncate on table "public"."atp_poll_votes" to "service_role";
6060+6161+grant update on table "public"."atp_poll_votes" to "service_role";
6262+6363+create table "public"."atp_poll_records" (
6464+ "uri" text not null,
6565+ "cid" text not null,
6666+ "record" jsonb not null,
6767+ "created_at" timestamp with time zone not null default now()
6868+);
6969+7070+7171+alter table "public"."atp_poll_records" enable row level security;
7272+7373+alter table "public"."bsky_follows" alter column "identity" set default ''::text;
7474+7575+CREATE UNIQUE INDEX atp_poll_records_pkey ON public.atp_poll_records USING btree (uri);
7676+7777+alter table "public"."atp_poll_records" add constraint "atp_poll_records_pkey" PRIMARY KEY using index "atp_poll_records_pkey";
7878+7979+alter table "public"."atp_poll_votes" add constraint "atp_poll_votes_poll_uri_fkey" FOREIGN KEY (poll_uri) REFERENCES atp_poll_records(uri) ON UPDATE CASCADE ON DELETE CASCADE not valid;
8080+8181+alter table "public"."atp_poll_votes" validate constraint "atp_poll_votes_poll_uri_fkey";
8282+8383+grant delete on table "public"."atp_poll_records" to "anon";
8484+8585+grant insert on table "public"."atp_poll_records" to "anon";
8686+8787+grant references on table "public"."atp_poll_records" to "anon";
8888+8989+grant select on table "public"."atp_poll_records" to "anon";
9090+9191+grant trigger on table "public"."atp_poll_records" to "anon";
9292+9393+grant truncate on table "public"."atp_poll_records" to "anon";
9494+9595+grant update on table "public"."atp_poll_records" to "anon";
9696+9797+grant delete on table "public"."atp_poll_records" to "authenticated";
9898+9999+grant insert on table "public"."atp_poll_records" to "authenticated";
100100+101101+grant references on table "public"."atp_poll_records" to "authenticated";
102102+103103+grant select on table "public"."atp_poll_records" to "authenticated";
104104+105105+grant trigger on table "public"."atp_poll_records" to "authenticated";
106106+107107+grant truncate on table "public"."atp_poll_records" to "authenticated";
108108+109109+grant update on table "public"."atp_poll_records" to "authenticated";
110110+111111+grant delete on table "public"."atp_poll_records" to "service_role";
112112+113113+grant insert on table "public"."atp_poll_records" to "service_role";
114114+115115+grant references on table "public"."atp_poll_records" to "service_role";
116116+117117+grant select on table "public"."atp_poll_records" to "service_role";
118118+119119+grant trigger on table "public"."atp_poll_records" to "service_role";
120120+121121+grant truncate on table "public"."atp_poll_records" to "service_role";
122122+123123+grant update on table "public"."atp_poll_records" to "service_role";