From 5cd98880ca41b3ac50487af3ac61f533c58a34f4 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 17 Feb 2025 12:22:45 -0500 Subject: [PATCH 1/9] reorganize panels --- .../src/repl/components/panel/PatternsTab.jsx | 179 ++++++++++-------- website/src/repl/useExamplePatterns.jsx | 8 +- website/src/user_pattern_utils.mjs | 19 +- 3 files changed, 108 insertions(+), 98 deletions(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index df6075eb..fd9ddb15 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -84,82 +84,72 @@ function ActionButton({ children, onClick, label, labelIsHidden }) { ); } -export function PatternsTab({ context }) { +const updateCodeWindow = (context, patternData, reset = false) => { + context.handleUpdate(patternData, reset); +}; + +const autoResetPatternOnChange = !isUdels(); + +function UserPatterns({ context }) { const activePattern = useActivePattern(); const viewingPatternStore = useViewingPatternData(); const viewingPatternData = parseJSON(viewingPatternStore); - const { userPatterns, patternFilter } = useSettings(); - - const examplePatterns = useExamplePatterns(); - const collections = examplePatterns.collections; - - const updateCodeWindow = (patternData, reset = false) => { - context.handleUpdate(patternData, reset); - }; const viewingPatternID = viewingPatternData?.id; - - const autoResetPatternOnChange = !isUdels(); - return ( -
- settingsMap.setKey('patternFilter', value)} - items={patternFilterName} - > - {patternFilter === patternFilterName.user && ( -
-
- { - const { data } = userPattern.createAndAddToDB(); - updateCodeWindow(data); - }} - /> - { - const { data } = userPattern.duplicate(viewingPatternData); - updateCodeWindow(data); - }} - /> - { - const { data } = userPattern.delete(viewingPatternID); - updateCodeWindow({ ...data, collection: userPattern.collection }); - }} - /> - - +
+
+ { + const { data } = userPattern.createAndAddToDB(); + updateCodeWindow(context, data); + }} + /> + { + const { data } = userPattern.duplicate(viewingPatternData); + updateCodeWindow(context, data); + }} + /> + { + const { data } = userPattern.delete(viewingPatternID); + updateCodeWindow(context, { ...data, collection: userPattern.collection }); + }} + /> + + - { - const { data } = userPattern.clearAll(); - updateCodeWindow(data); - }} - /> -
-
- )} + { + const { data } = userPattern.clearAll(); + updateCodeWindow(context, data); + }} + /> +
-
+
{patternFilter === patternFilterName.user && ( - updateCodeWindow({ ...userPatterns[id], collection: userPattern.collection }, autoResetPatternOnChange) + updateCodeWindow( + context, + { ...userPatterns[id], collection: userPattern.collection }, + autoResetPatternOnChange, + ) } patterns={userPatterns} started={context.started} @@ -167,24 +157,47 @@ export function PatternsTab({ context }) { viewingPatternID={viewingPatternID} /> )} - {patternFilter !== patternFilterName.user && - Array.from(collections.keys()).map((collection) => { - const patterns = collections.get(collection); - return ( -
-

{collection}

-
- updateCodeWindow({ ...patterns[id], collection }, autoResetPatternOnChange)} - started={context.started} - patterns={patterns} - activePattern={activePattern} - /> -
-
- ); - })} -
+
+
+ ); +} + +function PublicPatterns({ context }) { + const activePattern = useActivePattern(); + const examplePatterns = useExamplePatterns(); + const collections = examplePatterns.collections; + const { patternFilter } = useSettings(); + const patterns = collections.get(patternFilter) ?? collections.get(patternFilterName.public); + return ( +
+ + updateCodeWindow(context, { ...patterns[id], collection: patternFilter }, autoResetPatternOnChange) + } + started={context.started} + patterns={patterns} + activePattern={activePattern} + /> +
+ ); +} + +export function PatternsTab({ context }) { + const { patternFilter } = useSettings(); + + return ( +
+ settingsMap.setKey('patternFilter', value)} + items={patternFilterName} + > + + {patternFilter === patternFilterName.user ? ( + + ) : ( + + )}
); } diff --git a/website/src/repl/useExamplePatterns.jsx b/website/src/repl/useExamplePatterns.jsx index 08629d44..2e11fcae 100644 --- a/website/src/repl/useExamplePatterns.jsx +++ b/website/src/repl/useExamplePatterns.jsx @@ -1,4 +1,4 @@ -import { $featuredPatterns, $publicPatterns, collectionName } from '../user_pattern_utils.mjs'; +import { $featuredPatterns, $publicPatterns, patternFilterName } from '../user_pattern_utils.mjs'; import { useStore } from '@nanostores/react'; import { useMemo } from 'react'; import * as tunes from '../repl/tunes.mjs'; @@ -12,9 +12,9 @@ export const useExamplePatterns = () => { const publicPatterns = useStore($publicPatterns); const collections = useMemo(() => { const pats = new Map(); - pats.set(collectionName.featured, featuredPatterns); - pats.set(collectionName.public, publicPatterns); - // pats.set(collectionName.stock, stockPatterns); + pats.set(patternFilterName.featured, featuredPatterns); + pats.set(patternFilterName.public, publicPatterns); + // pats.set(patternFilterName.stock, stockPatterns); return pats; }, [featuredPatterns, publicPatterns]); diff --git a/website/src/user_pattern_utils.mjs b/website/src/user_pattern_utils.mjs index 866491d0..d87fbff4 100644 --- a/website/src/user_pattern_utils.mjs +++ b/website/src/user_pattern_utils.mjs @@ -8,16 +8,13 @@ import { confirmDialog, parseJSON, supabase } from './repl/util.mjs'; export let $publicPatterns = atom([]); export let $featuredPatterns = atom([]); -export const collectionName = { - user: 'user', - public: 'Last Creations', - stock: 'Stock Examples', - featured: 'Featured', -}; + export const patternFilterName = { - community: 'community', + public: 'latest', + featured: 'featured', user: 'user', + // stock: 'stock examples', }; const sessionAtom = (name, initial = undefined) => { @@ -36,7 +33,7 @@ const sessionAtom = (name, initial = undefined) => { export let $viewingPatternData = sessionAtom('viewingPatternData', { id: '', code: '', - collection: collectionName.user, + collection: patternFilterName.user, created_at: Date.now(), }); @@ -52,11 +49,11 @@ export const setViewingPatternData = (data) => { }; export function loadPublicPatterns() { - return supabase.from('code_v1').select().eq('public', true).limit(20).order('id', { ascending: false }); + return supabase.from('code_v1').select().eq('public', true).limit(40).order('id', { ascending: false }); } export function loadFeaturedPatterns() { - return supabase.from('code_v1').select().eq('featured', true).limit(20).order('id', { ascending: false }); + return supabase.from('code_v1').select().eq('featured', true).limit(40).order('id', { ascending: false }); } export async function loadDBPatterns() { @@ -92,7 +89,7 @@ export const setLatestCode = (code) => settingsMap.setKey('latestCode', code); const defaultCode = ''; export const userPattern = { - collection: collectionName.user, + collection: patternFilterName.user, getAll() { const patterns = parseJSON(settingsMap.get().userPatterns); return patterns ?? {}; From 50f076084f56be3bc1cfaf20c7174200d3ace34d Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 01:48:17 -0500 Subject: [PATCH 2/9] working --- .../components/incrementor/Incrementor.jsx | 52 +++++++++ .../repl/components/pagination/Pagination.jsx | 7 ++ .../src/repl/components/panel/PatternsTab.jsx | 109 ++++++++++++++---- .../src/repl/components/panel/Reference.jsx | 8 +- .../src/repl/components/panel/SoundsTab.jsx | 6 +- .../src/repl/components/textbox/Textbox.jsx | 15 +++ website/src/repl/components/usedebounce.jsx | 30 +++++ website/src/repl/util.mjs | 1 + website/src/settings.mjs | 2 + website/src/user_pattern_utils.mjs | 44 ++++--- website/tailwind.config.cjs | 2 + website/tailwind_utils.mjs | 4 + 12 files changed, 237 insertions(+), 43 deletions(-) create mode 100644 website/src/repl/components/incrementor/Incrementor.jsx create mode 100644 website/src/repl/components/pagination/Pagination.jsx create mode 100644 website/src/repl/components/textbox/Textbox.jsx create mode 100644 website/src/repl/components/usedebounce.jsx create mode 100644 website/tailwind_utils.mjs diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx new file mode 100644 index 00000000..1bad0a8d --- /dev/null +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -0,0 +1,52 @@ +import { cn } from 'tailwind_utils.mjs'; +import { Textbox } from '../textbox/Textbox'; + +function IncButton({ children, label, className, ...buttonProps }) { + return ( + + ); +} +export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, className }) { + value = parseInt(value); + value = isNaN(value) ? '' : value; + return ( +
rounded-md', className)}> + { + if (v.length && v < min) { + return; + } + onChange(v); + }} + type="number" + placeholder="" + value={value} + className="w-32 my-0 border-none rounded-r-none bg-transparent appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" + /> +
+ onChange(value - 1)}> + + + + + = max} onClick={() => onChange(value + 1)}> + + + + +
+
+ ); +} diff --git a/website/src/repl/components/pagination/Pagination.jsx b/website/src/repl/components/pagination/Pagination.jsx new file mode 100644 index 00000000..e9953136 --- /dev/null +++ b/website/src/repl/components/pagination/Pagination.jsx @@ -0,0 +1,7 @@ + +import { Incrementor } from '../incrementor/Incrementor'; + +export function Pagination({ currPage, onPageChange, className }) { + return ; +} + diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index fd9ddb15..e809d654 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -1,6 +1,8 @@ import { exportPatterns, importPatterns, + loadAndSetFeaturedPatterns, + loadAndSetPublicPatterns, patternFilterName, useActivePattern, useViewingPatternData, @@ -12,6 +14,9 @@ import { useExamplePatterns } from '../../useExamplePatterns.jsx'; import { parseJSON, isUdels } from '../../util.mjs'; import { ButtonGroup } from './Forms.jsx'; import { settingsMap, useSettings } from '../../../settings.mjs'; +import { Pagination } from '../pagination/Pagination.jsx'; +import { useState } from 'react'; +import { useDebounce } from '../usedebounce.jsx'; function classNames(...classes) { return classes.filter(Boolean).join(' '); @@ -33,7 +38,9 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { if (title == null) { title = 'unnamed'; } - return <>{`${pattern.id}: ${title} by ${Array.isArray(meta.by) ? meta.by.join(',') : 'Anonymous'}`}; + + const author = Array.isArray(meta.by) ? meta.by.join(',') : 'Anonymous'; + return <>{`${pattern.id}: ${title} by ${author.slice(0, 100)}`.slice(0, 60)}; } function PatternButton({ showOutline, onClick, pattern, showHiglight }) { @@ -57,7 +64,7 @@ function PatternButtons({ patterns, activePattern, onClick, started }) { const viewingPatternID = viewingPatternData.id; return (
- {Object.values(patterns) + {Object.values(patterns ?? {}) .reverse() .map((pattern) => { const id = pattern.id; @@ -97,8 +104,8 @@ function UserPatterns({ context }) { const { userPatterns, patternFilter } = useSettings(); const viewingPatternID = viewingPatternData?.id; return ( -
-
+
+
{ @@ -141,7 +148,7 @@ function UserPatterns({ context }) { />
-
+
{patternFilter === patternFilterName.user && ( @@ -162,31 +169,93 @@ function UserPatterns({ context }) { ); } -function PublicPatterns({ context }) { +function PatternPageWithPagination({ patterns, patternOnClick, context, paginationOnChange }) { + const [page, setPage] = useState(1); + const debouncedPageChange = useDebounce(() => { + paginationOnChange(page); + }); + + const onPageChange = (pageNum) => { + setPage(pageNum); + debouncedPageChange(); + }; + const activePattern = useActivePattern(); - const examplePatterns = useExamplePatterns(); - const collections = examplePatterns.collections; - const { patternFilter } = useSettings(); - const patterns = collections.get(patternFilter) ?? collections.get(patternFilterName.public); return ( -
- - updateCodeWindow(context, { ...patterns[id], collection: patternFilter }, autoResetPatternOnChange) - } - started={context.started} - patterns={patterns} - activePattern={activePattern} - /> +
+
+ patternOnClick(id)} + started={context.started} + patterns={patterns} + activePattern={activePattern} + /> +
+
+ {' '} + +
); } +function FeaturedPatterns({ context }) { + const examplePatterns = useExamplePatterns(); + const collections = examplePatterns.collections; + const patterns = collections.get(patternFilterName.featured); + return ( + { + updateCodeWindow( + context, + { ...patterns[id], collection: patternFilterName.featured }, + autoResetPatternOnChange, + ); + }} + paginationOnChange={async (pageNum) => { + await loadAndSetFeaturedPatterns(pageNum); + }} + /> + ); +} + +function LatestPatterns({ context }) { + const examplePatterns = useExamplePatterns(); + const collections = examplePatterns.collections; + const patterns = collections.get(patternFilterName.public); + return ( + { + updateCodeWindow( + context, + { ...patterns[id], collection: patternFilterName.public }, + autoResetPatternOnChange, + ); + }} + paginationOnChange={async (pageNum) => { + await loadAndSetPublicPatterns(pageNum); + }} + /> + ); +} + +function PublicPatterns({ context }) { + const { patternFilter } = useSettings(); + if (patternFilter === patternFilterName.featured) { + return ; + } + return ; +} + export function PatternsTab({ context }) { const { patternFilter } = useSettings(); return ( -
+
settingsMap.setKey('patternFilter', value)} diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx index fbbf0a08..a8b8a301 100644 --- a/website/src/repl/components/panel/Reference.jsx +++ b/website/src/repl/components/panel/Reference.jsx @@ -1,6 +1,7 @@ import { useMemo, useState } from 'react'; import jsdocJson from '../../../../../doc.json'; +import { Textbox } from '../textbox/Textbox'; const availableFunctions = jsdocJson.docs .filter(({ name, description }) => name && !name.startsWith('_') && !!description) .sort((a, b) => /* a.meta.filename.localeCompare(b.meta.filename) + */ a.name.localeCompare(b.name)); @@ -28,12 +29,7 @@ export function Reference() {
- setSearch(event.target.value)} - /> +
{visibleFunctions.map((entry, i) => ( diff --git a/website/src/repl/components/panel/SoundsTab.jsx b/website/src/repl/components/panel/SoundsTab.jsx index b968466f..3d5e2d2c 100644 --- a/website/src/repl/components/panel/SoundsTab.jsx +++ b/website/src/repl/components/panel/SoundsTab.jsx @@ -5,6 +5,7 @@ import { useMemo, useRef, useState } from 'react'; import { settingsMap, useSettings } from '../../../settings.mjs'; import { ButtonGroup } from './Forms.jsx'; import ImportSoundsButton from './ImportSoundsButton.jsx'; +import { Textbox } from '../textbox/Textbox.jsx'; const getSamples = (samples) => Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1; @@ -53,11 +54,10 @@ export function SoundsTab() { return (
- setSearch(e.target.value)} + onChange={(v) => setSearch(v)} />
diff --git a/website/src/repl/components/textbox/Textbox.jsx b/website/src/repl/components/textbox/Textbox.jsx new file mode 100644 index 00000000..da99b17b --- /dev/null +++ b/website/src/repl/components/textbox/Textbox.jsx @@ -0,0 +1,15 @@ +import { cn } from 'tailwind_utils.mjs'; +// type TextboxProps = { +// onChange: (val: string | number) => void; +// ...inputProps +// } +export function Textbox(props) { + const {onChange, className, ...inputProps} = props + return ( + props.onChange(e.target.value)} + {...inputProps} + /> + ); +} diff --git a/website/src/repl/components/usedebounce.jsx b/website/src/repl/components/usedebounce.jsx new file mode 100644 index 00000000..a0fb1ea7 --- /dev/null +++ b/website/src/repl/components/usedebounce.jsx @@ -0,0 +1,30 @@ +import { useMemo } from 'react'; +import { useEffect } from 'react'; +import { useRef } from 'react'; + +function debounce(fn, wait) { + let timer; + return function (...args) { + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(() => fn(...args), wait); + }; +} + +export function useDebounce(callback) { + const ref = useRef; + useEffect(() => { + ref.current = callback; + }, [callback]); + + const debouncedCallback = useMemo(() => { + const func = () => { + ref.current?.(); + }; + + return debounce(func, 1000); + }, []); + + return debouncedCallback; +} diff --git a/website/src/repl/util.mjs b/website/src/repl/util.mjs index f623e468..ddd91453 100644 --- a/website/src/repl/util.mjs +++ b/website/src/repl/util.mjs @@ -199,3 +199,4 @@ export function setVersionDefaultsFrom(code) { console.error(err); } } + diff --git a/website/src/settings.mjs b/website/src/settings.mjs index cd3d8936..8c35e996 100644 --- a/website/src/settings.mjs +++ b/website/src/settings.mjs @@ -40,6 +40,8 @@ export const defaultSettings = { audioEngineTarget: audioEngineTargets.webaudio, isButtonRowHidden: false, isCSSAnimationDisabled: false, + publicPatternPage: 1, + featuredPatternPage: 1, }; let search = null; diff --git a/website/src/user_pattern_utils.mjs b/website/src/user_pattern_utils.mjs index d87fbff4..a1a344db 100644 --- a/website/src/user_pattern_utils.mjs +++ b/website/src/user_pattern_utils.mjs @@ -9,7 +9,7 @@ export let $publicPatterns = atom([]); export let $featuredPatterns = atom([]); - +const patternQueryLimit = 20 export const patternFilterName = { public: 'latest', featured: 'featured', @@ -48,25 +48,41 @@ export const setViewingPatternData = (data) => { $viewingPatternData.set(JSON.stringify(data)); }; -export function loadPublicPatterns() { - return supabase.from('code_v1').select().eq('public', true).limit(40).order('id', { ascending: false }); +function parsePageNum(page) { + return isNaN(page) ? 0 : page +} +export function loadPublicPatterns(page) { + page = parsePageNum(page) + const offset = page * patternQueryLimit + return supabase.from('code_v1').select().eq('public', true).range(offset, offset + patternQueryLimit ).order('id', { ascending: false }); } -export function loadFeaturedPatterns() { - return supabase.from('code_v1').select().eq('featured', true).limit(40).order('id', { ascending: false }); +export function loadFeaturedPatterns(page = 0) { + page = parsePageNum(page) + const offset = page * patternQueryLimit + return supabase.from('code_v1').select().eq('featured', true).range(offset, offset + patternQueryLimit).order('id', { ascending: false }); +} + +export async function loadAndSetPublicPatterns(page) { + const p = await loadPublicPatterns(page); + const data = p?.data + const pats = {} + data?.forEach((data, key) => (pats[data.id ?? key] = data)); + $publicPatterns.set(pats) +} +export async function loadAndSetFeaturedPatterns(page) { + + const p = await loadFeaturedPatterns(page); + const data = p?.data + const pats = {} + data?.forEach((data, key) => (pats[data.id ?? key] = data)); + $featuredPatterns.set(pats) } export async function loadDBPatterns() { try { - const { data: publicPatterns } = await loadPublicPatterns(); - const { data: featuredPatterns } = await loadFeaturedPatterns(); - const featured = {}; - const pub = {}; - - publicPatterns?.forEach((data, key) => (pub[data.id ?? key] = data)); - featuredPatterns?.forEach((data, key) => (featured[data.id ?? key] = data)); - $publicPatterns.set(pub); - $featuredPatterns.set(featured); + await loadAndSetPublicPatterns() + await loadAndSetFeaturedPatterns() } catch (err) { console.error('error loading patterns', err); } diff --git a/website/tailwind.config.cjs b/website/tailwind.config.cjs index 23ae96c3..83793161 100644 --- a/website/tailwind.config.cjs +++ b/website/tailwind.config.cjs @@ -2,6 +2,8 @@ const defaultTheme = require('tailwindcss/defaultTheme'); + + module.exports = { darkMode: 'class', content: [ diff --git a/website/tailwind_utils.mjs b/website/tailwind_utils.mjs new file mode 100644 index 00000000..21ed33d7 --- /dev/null +++ b/website/tailwind_utils.mjs @@ -0,0 +1,4 @@ +// utility for combining class names +export function cn(...classNameStrings) { + return classNameStrings.join(' ') + } \ No newline at end of file From c210ea3f8932d7586327109cc10944984fbd8e64 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 10:41:16 -0500 Subject: [PATCH 3/9] fix paginator --- .../components/incrementor/Incrementor.jsx | 6 ++--- .../repl/components/pagination/Pagination.jsx | 2 -- .../src/repl/components/panel/PatternsTab.jsx | 25 +++++++++---------- .../src/repl/components/textbox/Textbox.jsx | 12 +++------ website/tailwind_utils.mjs | 6 ++--- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx index 1bad0a8d..43e69865 100644 --- a/website/src/repl/components/incrementor/Incrementor.jsx +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -6,7 +6,7 @@ function IncButton({ children, label, className, ...buttonProps }) {
); } +let featuredPageNum = 1 function FeaturedPatterns({ context }) { const examplePatterns = useExamplePatterns(); const collections = examplePatterns.collections; @@ -207,6 +205,7 @@ function FeaturedPatterns({ context }) { { updateCodeWindow( context, @@ -216,11 +215,13 @@ function FeaturedPatterns({ context }) { }} paginationOnChange={async (pageNum) => { await loadAndSetFeaturedPatterns(pageNum); + featuredPageNum = pageNum }} /> ); } +let latestPageNum = 1 function LatestPatterns({ context }) { const examplePatterns = useExamplePatterns(); const collections = examplePatterns.collections; @@ -229,15 +230,13 @@ function LatestPatterns({ context }) { { - updateCodeWindow( - context, - { ...patterns[id], collection: patternFilterName.public }, - autoResetPatternOnChange, - ); + updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, autoResetPatternOnChange); }} paginationOnChange={async (pageNum) => { await loadAndSetPublicPatterns(pageNum); + latestPageNum = pageNum }} /> ); diff --git a/website/src/repl/components/textbox/Textbox.jsx b/website/src/repl/components/textbox/Textbox.jsx index da99b17b..7b97afed 100644 --- a/website/src/repl/components/textbox/Textbox.jsx +++ b/website/src/repl/components/textbox/Textbox.jsx @@ -1,14 +1,10 @@ import { cn } from 'tailwind_utils.mjs'; -// type TextboxProps = { -// onChange: (val: string | number) => void; -// ...inputProps -// } -export function Textbox(props) { - const {onChange, className, ...inputProps} = props + +export function Textbox({ onChange, className, ...inputProps }) { return ( props.onChange(e.target.value)} + className={cn('p-1 bg-background rounded-md my-2 border-foreground', className)} + onChange={(e) => onChange(e.target.value)} {...inputProps} /> ); diff --git a/website/tailwind_utils.mjs b/website/tailwind_utils.mjs index 21ed33d7..c8934e95 100644 --- a/website/tailwind_utils.mjs +++ b/website/tailwind_utils.mjs @@ -1,4 +1,4 @@ // utility for combining class names -export function cn(...classNameStrings) { - return classNameStrings.join(' ') - } \ No newline at end of file +export function cn(...classes) { + return classes.filter(Boolean).join(' '); +} \ No newline at end of file From 47f65da621e52f54813ed527fd0ba4f673646068 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 10:47:48 -0500 Subject: [PATCH 4/9] remove unesseccary code --- website/src/settings.mjs | 2 -- 1 file changed, 2 deletions(-) diff --git a/website/src/settings.mjs b/website/src/settings.mjs index 8c35e996..cd3d8936 100644 --- a/website/src/settings.mjs +++ b/website/src/settings.mjs @@ -40,8 +40,6 @@ export const defaultSettings = { audioEngineTarget: audioEngineTargets.webaudio, isButtonRowHidden: false, isCSSAnimationDisabled: false, - publicPatternPage: 1, - featuredPatternPage: 1, }; let search = null; From f47f5c1344a6fcaf8b78fbd88ed3d60eec4b4847 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 10:52:48 -0500 Subject: [PATCH 5/9] prettier --- .../components/incrementor/Incrementor.jsx | 9 +++- .../src/repl/components/panel/PatternsTab.jsx | 8 ++-- .../src/repl/components/panel/Reference.jsx | 2 +- .../src/repl/components/panel/SoundsTab.jsx | 6 +-- website/src/repl/useExamplePatterns.jsx | 2 +- website/src/repl/util.mjs | 1 - website/src/user_pattern_utils.mjs | 44 +++++++++++-------- website/tailwind.config.cjs | 2 - website/tailwind_utils.mjs | 2 +- 9 files changed, 41 insertions(+), 35 deletions(-) diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx index 43e69865..2c631cc5 100644 --- a/website/src/repl/components/incrementor/Incrementor.jsx +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -36,12 +36,17 @@ export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, className="w-32 my-0 border-none rounded-r-none bg-transparent appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" />
- onChange(value - 1)}> + onChange(value - 1)}> - = max} onClick={() => onChange(value + 1)}> + = max} + onClick={() => onChange(value + 1)} + > diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 032e7593..46d6ccc0 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -196,7 +196,7 @@ function PatternPageWithPagination({ patterns, patternOnClick, context, paginati ); } -let featuredPageNum = 1 +let featuredPageNum = 1; function FeaturedPatterns({ context }) { const examplePatterns = useExamplePatterns(); const collections = examplePatterns.collections; @@ -215,13 +215,13 @@ function FeaturedPatterns({ context }) { }} paginationOnChange={async (pageNum) => { await loadAndSetFeaturedPatterns(pageNum); - featuredPageNum = pageNum + featuredPageNum = pageNum; }} /> ); } -let latestPageNum = 1 +let latestPageNum = 1; function LatestPatterns({ context }) { const examplePatterns = useExamplePatterns(); const collections = examplePatterns.collections; @@ -236,7 +236,7 @@ function LatestPatterns({ context }) { }} paginationOnChange={async (pageNum) => { await loadAndSetPublicPatterns(pageNum); - latestPageNum = pageNum + latestPageNum = pageNum; }} /> ); diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx index a8b8a301..6fdc9659 100644 --- a/website/src/repl/components/panel/Reference.jsx +++ b/website/src/repl/components/panel/Reference.jsx @@ -29,7 +29,7 @@ export function Reference() {
- +
{visibleFunctions.map((entry, i) => ( diff --git a/website/src/repl/components/panel/SoundsTab.jsx b/website/src/repl/components/panel/SoundsTab.jsx index 3d5e2d2c..8ca2d39d 100644 --- a/website/src/repl/components/panel/SoundsTab.jsx +++ b/website/src/repl/components/panel/SoundsTab.jsx @@ -54,11 +54,7 @@ export function SoundsTab() { return (
- setSearch(v)} - /> + setSearch(v)} />
{ }; function parsePageNum(page) { - return isNaN(page) ? 0 : page + return isNaN(page) ? 0 : page; } export function loadPublicPatterns(page) { - page = parsePageNum(page) - const offset = page * patternQueryLimit - return supabase.from('code_v1').select().eq('public', true).range(offset, offset + patternQueryLimit ).order('id', { ascending: false }); + page = parsePageNum(page); + const offset = page * patternQueryLimit; + return supabase + .from('code_v1') + .select() + .eq('public', true) + .range(offset, offset + patternQueryLimit) + .order('id', { ascending: false }); } export function loadFeaturedPatterns(page = 0) { - page = parsePageNum(page) - const offset = page * patternQueryLimit - return supabase.from('code_v1').select().eq('featured', true).range(offset, offset + patternQueryLimit).order('id', { ascending: false }); + page = parsePageNum(page); + const offset = page * patternQueryLimit; + return supabase + .from('code_v1') + .select() + .eq('featured', true) + .range(offset, offset + patternQueryLimit) + .order('id', { ascending: false }); } export async function loadAndSetPublicPatterns(page) { const p = await loadPublicPatterns(page); - const data = p?.data - const pats = {} + const data = p?.data; + const pats = {}; data?.forEach((data, key) => (pats[data.id ?? key] = data)); - $publicPatterns.set(pats) + $publicPatterns.set(pats); } export async function loadAndSetFeaturedPatterns(page) { - const p = await loadFeaturedPatterns(page); - const data = p?.data - const pats = {} + const data = p?.data; + const pats = {}; data?.forEach((data, key) => (pats[data.id ?? key] = data)); - $featuredPatterns.set(pats) + $featuredPatterns.set(pats); } export async function loadDBPatterns() { try { - await loadAndSetPublicPatterns() - await loadAndSetFeaturedPatterns() + await loadAndSetPublicPatterns(); + await loadAndSetFeaturedPatterns(); } catch (err) { console.error('error loading patterns', err); } diff --git a/website/tailwind.config.cjs b/website/tailwind.config.cjs index 83793161..23ae96c3 100644 --- a/website/tailwind.config.cjs +++ b/website/tailwind.config.cjs @@ -2,8 +2,6 @@ const defaultTheme = require('tailwindcss/defaultTheme'); - - module.exports = { darkMode: 'class', content: [ diff --git a/website/tailwind_utils.mjs b/website/tailwind_utils.mjs index c8934e95..4ec963f4 100644 --- a/website/tailwind_utils.mjs +++ b/website/tailwind_utils.mjs @@ -1,4 +1,4 @@ // utility for combining class names export function cn(...classes) { return classes.filter(Boolean).join(' '); -} \ No newline at end of file +} From 3e6a45cf8b2d95913079cebda955f5ec278b4211 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 11:10:15 -0500 Subject: [PATCH 6/9] fix offset --- website/src/repl/components/incrementor/Incrementor.jsx | 2 +- website/src/repl/components/panel/PatternsTab.jsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx index 2c631cc5..9103894d 100644 --- a/website/src/repl/components/incrementor/Incrementor.jsx +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -33,7 +33,7 @@ export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, type="number" placeholder="" value={value} - className="w-32 my-0 border-none rounded-r-none bg-transparent appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" + className="w-32 mb-0 mt-0 border-none rounded-r-none bg-transparent appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" />
onChange(value - 1)}> diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 46d6ccc0..16d85495 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -214,7 +214,7 @@ function FeaturedPatterns({ context }) { ); }} paginationOnChange={async (pageNum) => { - await loadAndSetFeaturedPatterns(pageNum); + await loadAndSetFeaturedPatterns(pageNum -1); featuredPageNum = pageNum; }} /> @@ -235,7 +235,7 @@ function LatestPatterns({ context }) { updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, autoResetPatternOnChange); }} paginationOnChange={async (pageNum) => { - await loadAndSetPublicPatterns(pageNum); + await loadAndSetPublicPatterns(pageNum -1); latestPageNum = pageNum; }} /> From dfb7d7bb7f4cab746cabd046d0d09ae84c788569 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 18 Feb 2025 11:13:33 -0500 Subject: [PATCH 7/9] prettier --- website/src/repl/components/panel/PatternsTab.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 16d85495..3fc247b8 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -214,7 +214,7 @@ function FeaturedPatterns({ context }) { ); }} paginationOnChange={async (pageNum) => { - await loadAndSetFeaturedPatterns(pageNum -1); + await loadAndSetFeaturedPatterns(pageNum - 1); featuredPageNum = pageNum; }} /> @@ -235,7 +235,7 @@ function LatestPatterns({ context }) { updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, autoResetPatternOnChange); }} paginationOnChange={async (pageNum) => { - await loadAndSetPublicPatterns(pageNum -1); + await loadAndSetPublicPatterns(pageNum - 1); latestPageNum = pageNum; }} /> From bbb88a2302e41942042af690b92b97a908afec70 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 21 Feb 2025 20:03:17 -0500 Subject: [PATCH 8/9] accessibility --- .../components/incrementor/Incrementor.jsx | 26 ++++++++----------- .../repl/components/pagination/Pagination.jsx | 4 +-- .../src/repl/components/panel/PatternsTab.jsx | 4 +-- .../src/repl/components/panel/Reference.jsx | 2 +- .../src/repl/components/textbox/Textbox.jsx | 4 +-- website/tailwind_utils.mjs | 4 --- 6 files changed, 18 insertions(+), 26 deletions(-) delete mode 100644 website/tailwind_utils.mjs diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx index 9103894d..f03a98da 100644 --- a/website/src/repl/components/incrementor/Incrementor.jsx +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -1,26 +1,26 @@ -import { cn } from 'tailwind_utils.mjs'; import { Textbox } from '../textbox/Textbox'; +import cx from '@src/cx.mjs'; -function IncButton({ children, label, className, ...buttonProps }) { +function IncButton({ children, className, ...buttonProps }) { return ( ); } -export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, className }) { +export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, className, ...incrementorProps }) { value = parseInt(value); value = isNaN(value) ? '' : value; return ( -
rounded-md', className)}> +
rounded-md', className)}>
- onChange(value - 1)}> + onChange(value - 1)}> - = max} - onClick={() => onChange(value + 1)} - > + = max} onClick={() => onChange(value + 1)}> diff --git a/website/src/repl/components/pagination/Pagination.jsx b/website/src/repl/components/pagination/Pagination.jsx index 8df761dc..c3ea6dd4 100644 --- a/website/src/repl/components/pagination/Pagination.jsx +++ b/website/src/repl/components/pagination/Pagination.jsx @@ -1,5 +1,5 @@ import { Incrementor } from '../incrementor/Incrementor'; -export function Pagination({ currPage, onPageChange, className }) { - return ; +export function Pagination({ currPage, onPageChange, className, ...incrementorProps }) { + return ; } diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 3fc247b8..21449444 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -17,7 +17,7 @@ import { settingsMap, useSettings } from '../../../settings.mjs'; import { Pagination } from '../pagination/Pagination.jsx'; import { useState } from 'react'; import { useDebounce } from '../usedebounce.jsx'; -import { cn } from 'tailwind_utils.mjs'; +import cx from '@src/cx.mjs'; export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { const meta = useMemo(() => getMetadata(pattern.code), [pattern]); @@ -43,7 +43,7 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { function PatternButton({ showOutline, onClick, pattern, showHiglight }) { return (
- +
{visibleFunctions.map((entry, i) => ( diff --git a/website/src/repl/components/textbox/Textbox.jsx b/website/src/repl/components/textbox/Textbox.jsx index 7b97afed..f391dd6d 100644 --- a/website/src/repl/components/textbox/Textbox.jsx +++ b/website/src/repl/components/textbox/Textbox.jsx @@ -1,9 +1,9 @@ -import { cn } from 'tailwind_utils.mjs'; +import cx from '@src/cx.mjs'; export function Textbox({ onChange, className, ...inputProps }) { return ( onChange(e.target.value)} {...inputProps} /> diff --git a/website/tailwind_utils.mjs b/website/tailwind_utils.mjs deleted file mode 100644 index 4ec963f4..00000000 --- a/website/tailwind_utils.mjs +++ /dev/null @@ -1,4 +0,0 @@ -// utility for combining class names -export function cn(...classes) { - return classes.filter(Boolean).join(' '); -} From 5c5d41158893d5bbc5fab8837b54e3ee1b7643bb Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 21 Feb 2025 20:11:39 -0500 Subject: [PATCH 9/9] lint --- .../components/incrementor/Incrementor.jsx | 20 ++++++++++++++++--- .../src/repl/components/panel/Reference.jsx | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/website/src/repl/components/incrementor/Incrementor.jsx b/website/src/repl/components/incrementor/Incrementor.jsx index f03a98da..5f722fb7 100644 --- a/website/src/repl/components/incrementor/Incrementor.jsx +++ b/website/src/repl/components/incrementor/Incrementor.jsx @@ -16,7 +16,16 @@ function IncButton({ children, className, ...buttonProps }) { ); } -export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, className, ...incrementorProps }) { +export function Incrementor({ + onChange, + value, + min = -Infinity, + max = Infinity, + className, + incrementLabel = 'next page', + decrementLabel = 'prev page', + ...incrementorProps +}) { value = parseInt(value); value = isNaN(value) ? '' : value; return ( @@ -37,12 +46,17 @@ export function Incrementor({ onChange, value, min = -Infinity, max = Infinity, {...incrementorProps} />
- onChange(value - 1)}> + onChange(value - 1)} aria-label={decrementLabel}> - = max} onClick={() => onChange(value + 1)}> + = max} + onClick={() => onChange(value + 1)} + aria-label={incrementLabel} + > diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx index 452889de..b2bdd543 100644 --- a/website/src/repl/components/panel/Reference.jsx +++ b/website/src/repl/components/panel/Reference.jsx @@ -29,7 +29,7 @@ export function Reference() {
- +
{visibleFunctions.map((entry, i) => (