if (!window.define) { const modules = {}; window.__modules = modules; const modulePromises = {}; const thisScriptSource = document.currentScript.getAttribute('src'); const srcDir = thisScriptSource.substring(0, thisScriptSource.lastIndexOf('/')); const load = (id) => { if (modules[id]) return modules[id]; if (modulePromises[id]) return modulePromises[id]; return modulePromises[id] = new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = srcDir + '/' + id + '.js'; script.onload = () => modules[id].then(resolve); script.onerror = err => reject(new Error('failed to load ' + id)); script.dataset.id = id; document.head.append(script); }); }; const require = (ids, callback) => { Promise.all(ids.map(load)).then(items => { if (items.length === 1) callback(items[0]); else callback(items); }); }; window.require = require; require.context = (dir, useSubdirs) => { if ((dir === "../../images/emoji" || dir === "../images/emoji") && !useSubdirs) { const data = {"chunks.png":"f59b84127fa7b6c48b6c.png","eggbug-classic.png":"41454e429d62b5cb7963.png","eggbug.png":"17aa2d48956926005de9.png","sixty.png":"9a6014af31fb1ca65a1f.png","unyeah.png":"5cf84d596a2c422967de.png","yeah.png":"014b0a8cc35206ef151d.png"}; const f = (n) => data[n]; f.keys = () => Object.keys(data); return f; } else if ((dir === "../../images/plus-emoji" || dir === "../images/plus-emoji") && !useSubdirs) { const data = {"eggbug-asleep.png":"ebbf360236a95b62bdfc.png","eggbug-devious.png":"c4f3f2c6b9ffb85934e7.png","eggbug-heart-sob.png":"b59709333449a01e3e0a.png","eggbug-nervous.png":"d2753b632211c395538e.png","eggbug-pensive.png":"ae53a8b5de7c919100e6.png","eggbug-pleading.png":"11c5493261064ffa82c0.png","eggbug-relieved.png":"3633c116f0941d94d237.png","eggbug-shocked.png":"b25a9fdf230219087003.png","eggbug-smile-hearts.png":"d7ec7f057e6fb15a94cc.png","eggbug-sob.png":"9559ff8058a895328d76.png","eggbug-tuesday.png":"90058099e741e483208a.png","eggbug-uwu.png":"228d3a13bd5f7796b434.png","eggbug-wink.png":"3bc3a1c5272e2ceb8712.png","host-aww.png":"9bb403f3822c6457baf6.png","host-cry.png":"530f8cf75eac87716702.png","host-evil.png":"cb9a5640d7ef7b361a1a.png","host-frown.png":"99c7fbf98de865cc9726.png","host-joy.png":"53635f5fe850274b1a7d.png","host-love.png":"c45b6d8f9de20f725b98.png","host-nervous.png":"e5d55348f39c65a20148.png","host-plead.png":"fa883e2377fea8945237.png","host-shock.png":"bfa6d6316fd95ae76803.png","host-stare.png":"a09d966cd188c9ebaa4c.png"}; const f = (n) => data[n]; f.keys = () => Object.keys(data); return f; } throw new Error('not supported: require.context for ' + dir); }; window.define = (imports, exec) => { if (typeof imports === 'function') { exec = imports; imports = []; } const id = document.currentScript.dataset.id ?? './' + document.currentScript.getAttribute('src').split('/').pop().replace(/\.js$/i, ''); if (modules[id]) return; const exports = {}; modules[id] = Promise.resolve().then(function() { const imported = []; for (const id of imports) { if (id === 'require') imported.push(Promise.resolve(require)); else if (id === 'exports') imported.push(Promise.resolve(exports)); else imported.push(load(id)); } return Promise.all(imported); }).then(function(imported) { const result = exec.apply(window, imported); if (!('default' in exports)) exports.default = result; return exports; }); }; window.process = { env: { NODE_ENV: 'production' } }; } define(['exports', './post-page', './artist-alley-listing-Dn2_eERZ'], (function (exports, postPage, artistAlleyListing) { 'use strict'; const useTransitionState = (...args) => { const [state, setState] = postPage.reactExports.useState(...args); const [isTransitioning, startTransition] = postPage.reactExports.useTransition(); const setStateWithTransition = (newState) => { startTransition(() => { setState(newState); }); }; return [state, setStateWithTransition]; }; const ArtistAlleyApprovalStatus = postPage.mod.enum([ "approved", "pending", "rejected", ]); const ArtistAlleyPaymentStatus = postPage.mod.enum(["paid", "unpaid", "refunded"]); postPage.mod.object({ altText: postPage.mod.string(), attachmentFilename: postPage.mod.string(), ip: postPage.mod.string(), }); const ArtistAlleyWireAttachment = postPage.mod.object({ altText: postPage.mod.string(), previewURL: postPage.mod.string().url(), fileURL: postPage.mod.string().url(), }); postPage.mod.enum(["hide", "include", "only"]); const WireArtistAlley = postPage.mod.object({ id: postPage.ArtistAlleyAdId, projectId: postPage.ProjectId, expiresAt: postPage.ISODateString, createdAt: postPage.ISODateString, body: postPage.mod.string(), cta: postPage.mod.object({ link: postPage.mod.string().url(), text: postPage.mod.string(), }), attachment: ArtistAlleyWireAttachment.nullable(), categories: postPage.mod.array(postPage.mod.string()), adultContent: postPage.mod.boolean(), }); WireArtistAlley.extend({ userId: postPage.UserId, status: ArtistAlleyApprovalStatus, paymentStatus: ArtistAlleyPaymentStatus, stripeCheckoutSessionId: postPage.mod.string().nullable(), stripePaymentIntentId: postPage.mod.string().nullable(), rejectReason: postPage.mod.string().nullable(), numWeeks: postPage.mod.number().int(), notes: postPage.mod.string().nullable(), }); WireArtistAlley.extend({ userId: postPage.UserId, status: ArtistAlleyApprovalStatus, paymentStatus: ArtistAlleyPaymentStatus, rejectReason: postPage.mod.string().nullable(), numWeeks: postPage.mod.number().int(), notes: postPage.mod.string().nullable(), receiptUrl: postPage.mod.string().url().nullable(), }); function useSet(values) { const setRef = postPage.reactExports.useRef(new Set(values)); const [, reRender] = postPage.reactExports.useReducer((x) => x + 1, 0); setRef.current.add = (...args) => { const res = Set.prototype.add.apply(setRef.current, args); reRender(); return res; }; setRef.current.clear = (...args) => { Set.prototype.clear.apply(setRef.current, args); reRender(); }; setRef.current.delete = (...args) => { const res = Set.prototype.delete.apply(setRef.current, args); reRender(); return res; }; return setRef.current; } // src/observe.ts var observerMap = /* @__PURE__ */ new Map(); var RootIds = /* @__PURE__ */ new WeakMap(); var rootId = 0; var unsupportedValue = void 0; function getRootId(root) { if (!root) return "0"; if (RootIds.has(root)) return RootIds.get(root); rootId += 1; RootIds.set(root, rootId.toString()); return RootIds.get(root); } function optionsToId(options) { return Object.keys(options).sort().filter( (key) => options[key] !== void 0 ).map((key) => { return `${key}_${key === "root" ? getRootId(options.root) : options[key]}`; }).toString(); } function createObserver(options) { const id = optionsToId(options); let instance = observerMap.get(id); if (!instance) { const elements = /* @__PURE__ */ new Map(); let thresholds; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { var _a; const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold); if (options.trackVisibility && typeof entry.isVisible === "undefined") { entry.isVisible = inView; } (_a = elements.get(entry.target)) == null ? void 0 : _a.forEach((callback) => { callback(inView, entry); }); }); }, options); thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]); instance = { id, observer, elements }; observerMap.set(id, instance); } return instance; } function observe(element, callback, options = {}, fallbackInView = unsupportedValue) { if (typeof window.IntersectionObserver === "undefined" && fallbackInView !== void 0) { const bounds = element.getBoundingClientRect(); callback(fallbackInView, { isIntersecting: fallbackInView, target: element, intersectionRatio: typeof options.threshold === "number" ? options.threshold : 0, time: 0, boundingClientRect: bounds, intersectionRect: bounds, rootBounds: bounds }); return () => { }; } const { id, observer, elements } = createObserver(options); const callbacks = elements.get(element) || []; if (!elements.has(element)) { elements.set(element, callbacks); } callbacks.push(callback); observer.observe(element); return function unobserve() { callbacks.splice(callbacks.indexOf(callback), 1); if (callbacks.length === 0) { elements.delete(element); observer.unobserve(element); } if (elements.size === 0) { observer.disconnect(); observerMap.delete(id); } }; } function useInView({ threshold, delay, trackVisibility, rootMargin, root, triggerOnce, skip, initialInView, fallbackInView, onChange } = {}) { var _a; const [ref, setRef] = postPage.reactExports.useState(null); const callback = postPage.reactExports.useRef(); const [state, setState] = postPage.reactExports.useState({ inView: !!initialInView, entry: void 0 }); callback.current = onChange; postPage.reactExports.useEffect( () => { if (skip || !ref) return; let unobserve; unobserve = observe( ref, (inView, entry) => { setState({ inView, entry }); if (callback.current) callback.current(inView, entry); if (entry.isIntersecting && triggerOnce && unobserve) { unobserve(); unobserve = void 0; } }, { root, rootMargin, threshold, // @ts-ignore trackVisibility, // @ts-ignore delay }, fallbackInView ); return () => { if (unobserve) { unobserve(); } }; }, // We break the rule here, because we aren't including the actual `threshold` variable // eslint-disable-next-line react-hooks/exhaustive-deps [ // If the threshold is an array, convert it to a string, so it won't change between renders. Array.isArray(threshold) ? threshold.toString() : threshold, ref, root, rootMargin, triggerOnce, skip, trackVisibility, fallbackInView, delay ] ); const entryTarget = (_a = state.entry) == null ? void 0 : _a.target; const previousEntryTarget = postPage.reactExports.useRef(); if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) { previousEntryTarget.current = entryTarget; setState({ inView: !!initialInView, entry: void 0 }); } const result = [setRef, state.inView, state.entry]; result.ref = result[0]; result.inView = result[1]; result.entry = result[2]; return result; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const defaultProps = { breakpointCols: undefined, // optional, number or object { default: number, [key: number]: number } className: undefined, // required, string columnClassName: undefined, // optional, string // Any React children. Typically an array of JSX items children: undefined, // Custom attributes, however it is advised against // using these to prevent unintended issues and future conflicts // ...any other attribute, will be added to the container columnAttrs: undefined, // object, added to the columns // Deprecated props // The column property is deprecated. // It is an alias of the `columnAttrs` property column: undefined }; const DEFAULT_COLUMNS = 2; class Masonry extends postPage.React.Component { constructor(props) { super(props); // Correct scope for when methods are accessed externally this.reCalculateColumnCount = this.reCalculateColumnCount.bind(this); this.reCalculateColumnCountDebounce = this.reCalculateColumnCountDebounce.bind(this); // default state let columnCount; if (this.props.breakpointCols && this.props.breakpointCols.default) { columnCount = this.props.breakpointCols.default; } else { columnCount = parseInt(this.props.breakpointCols) || DEFAULT_COLUMNS; } this.state = { columnCount }; } componentDidMount() { this.reCalculateColumnCount(); // window may not be available in some environments if (window) { window.addEventListener('resize', this.reCalculateColumnCountDebounce); } } componentDidUpdate() { this.reCalculateColumnCount(); } componentWillUnmount() { if (window) { window.removeEventListener('resize', this.reCalculateColumnCountDebounce); } } reCalculateColumnCountDebounce() { if (!window || !window.requestAnimationFrame) { // IE10+ this.reCalculateColumnCount(); return; } if (window.cancelAnimationFrame) { // IE10+ window.cancelAnimationFrame(this._lastRecalculateAnimationFrame); } this._lastRecalculateAnimationFrame = window.requestAnimationFrame(() => { this.reCalculateColumnCount(); }); } reCalculateColumnCount() { const windowWidth = window && window.innerWidth || Infinity; let breakpointColsObject = this.props.breakpointCols; // Allow passing a single number to `breakpointCols` instead of an object if (typeof breakpointColsObject !== 'object') { breakpointColsObject = { default: parseInt(breakpointColsObject) || DEFAULT_COLUMNS }; } let matchedBreakpoint = Infinity; let columns = breakpointColsObject.default || DEFAULT_COLUMNS; for (let breakpoint in breakpointColsObject) { const optBreakpoint = parseInt(breakpoint); const isCurrentBreakpoint = optBreakpoint > 0 && windowWidth <= optBreakpoint; if (isCurrentBreakpoint && optBreakpoint < matchedBreakpoint) { matchedBreakpoint = optBreakpoint; columns = breakpointColsObject[breakpoint]; } } columns = Math.max(1, parseInt(columns) || 1); if (this.state.columnCount !== columns) { this.setState({ columnCount: columns }); } } itemsInColumns() { const currentColumnCount = this.state.columnCount; const itemsInColumns = new Array(currentColumnCount); // Force children to be handled as an array const items = postPage.React.Children.toArray(this.props.children); for (let i = 0; i < items.length; i++) { const columnIndex = i % currentColumnCount; if (!itemsInColumns[columnIndex]) { itemsInColumns[columnIndex] = []; } itemsInColumns[columnIndex].push(items[i]); } return itemsInColumns; } renderColumns() { const { column, columnAttrs = {}, columnClassName } = this.props; const childrenInColumns = this.itemsInColumns(); const columnWidth = `${100 / childrenInColumns.length}%`; let className = columnClassName; if (className && typeof className !== 'string') { this.logDeprecated('The property "columnClassName" requires a string'); // This is a deprecated default and will be removed soon. if (typeof className === 'undefined') { className = 'my-masonry-grid_column'; } } const columnAttributes = _objectSpread(_objectSpread(_objectSpread({}, column), columnAttrs), {}, { style: _objectSpread(_objectSpread({}, columnAttrs.style), {}, { width: columnWidth }), className }); return childrenInColumns.map((items, i) => { return /*#__PURE__*/postPage.React.createElement("div", _extends({}, columnAttributes, { key: i }), items); }); } logDeprecated(message) { console.error('[Masonry]', message); } render() { const _this$props = this.props, { // ignored children, breakpointCols, columnClassName, columnAttrs, column, // used className } = _this$props, rest = _objectWithoutProperties(_this$props, ["children", "breakpointCols", "columnClassName", "columnAttrs", "column", "className"]); let classNameOutput = className; if (typeof className !== 'string') { this.logDeprecated('The property "className" requires a string'); // This is a deprecated default and will be removed soon. if (typeof className === 'undefined') { classNameOutput = 'my-masonry-grid'; } } return /*#__PURE__*/postPage.React.createElement("div", _extends({}, rest, { className: classNameOutput }), this.renderColumns()); } } Masonry.defaultProps = defaultProps; const MultiSwitchButton = ({ tabs }) => { return ( postPage.React.createElement('ul', { className: "co-multi-button mx-auto my-2 flex w-auto max-w-fit flex-row items-center justify-evenly overflow-y-auto whitespace-nowrap rounded-lg" ,} , tabs.map((tab) => ( postPage.React.createElement('li', { key: `${tab.label}`, className: `co-multi-button px-3 py-2 text-center text-sm first-of-type:rounded-l-lg last-of-type:rounded-r-lg ${ tab.active ? "co-active rounded-lg rounded-b-lg font-bold first-of-type:rounded-bl-none last-of-type:rounded-br-none" : "" }`,} , postPage.React.createElement('button', { onClick: tab.onClick,}, tab.label) ) )) ) ); }; const ArtistAlleyFilters = ({ className }) => { const postBoxTheme = postPage.useDynamicTheme(); const isDesktop = postPage.useMedia("(min-width: 1200px)", true); const [allCategories] = postPage.trpc.artistAlley.getCategoriesInUse.useSuspenseQuery(undefined, { refetchInterval: Infinity, keepPreviousData: true, }); const { loggedIn } = postPage.useUserInfo(); const { data: hasPurchasedListing } = postPage.trpc.artistAlley.hasPurchasedListing.useQuery(undefined, { enabled: loggedIn, suspense: true, }); const { adultFilterMode, setAdultFilterMode, categories, isAdult, categoryMatch, setCategoryMatch, sortOrder, setSortOrder, } = artistAlleyListing.useArtistAlleyFilters(); return ( postPage.React.createElement(postPage.React.Fragment, null , postPage.React.createElement(postPage.ve, { as: "div", 'data-theme': postBoxTheme.current, className: postPage.tw`co-themed-box co-artist-alley-filters cohost-shadow-light dark:cohost-shadow-dark col-span-1 flex h-fit max-h-max min-h-0 w-full flex-col rounded-lg border ${ className ?? "" }`, defaultOpen: isDesktop,} , postPage.React.createElement(postPage.ve.Button, { as: "header", className: "flex flex-row items-center justify-between rounded-t-lg p-3 ui-not-open:rounded-b-lg" ,} , postPage.React.createElement(postPage.ForwardRef$2, { className: "h-5 w-5 ui-open:rotate-90 motion-safe:transition-transform" ,} ) , postPage.React.createElement('span', { className: "font-league text-xs uppercase" ,}, "filters" ) ) , postPage.React.createElement(postPage.ve.Panel, { as: "div",} , postPage.React.createElement('div', { className: "flex flex-row flex-wrap gap-2 px-3 py-2" ,} , allCategories.map((category) => ( postPage.React.createElement('div', { key: `selected-token-${category}`, className: "group h-max cursor-pointer select-none" ,} /* this weird nested div thing is to prevent a bug caused by having the default click handler and our removal handler on the same element */ , postPage.React.createElement('button', { className: postPage.tw`co-token flex items-center justify-start gap-1 rounded-lg px-2 py-1 leading-none ${ categories.has(category) ? "co-active" : "" }`, onClick: (e) => { e.stopPropagation(); categories.has(category) ? categories.delete(category) : categories.add(category); }, type: "button",} , postPage.React.createElement(postPage.ForwardRef$3, { className: "inline-block h-3.5" ,} ) , postPage.React.createElement('span', { className: "block",}, category) ) ) )) ) , postPage.React.createElement(MultiSwitchButton, { tabs: [ { label: "any", onClick: () => setCategoryMatch("any"), active: categoryMatch === "any", }, { label: "all", onClick: () => setCategoryMatch("all"), active: categoryMatch === "all", }, ],} ) , isAdult && ( postPage.React.createElement(postPage.React.Fragment, null , postPage.React.createElement('hr', { className: "border-notWhite",} ) , postPage.React.createElement(MultiSwitchButton, { tabs: [ { label: "hide 18+", onClick: () => { setAdultFilterMode("hide"); }, active: adultFilterMode === "hide", }, { label: "show 18+", onClick: () => { setAdultFilterMode("include"); }, active: adultFilterMode === "include", }, { label: "only 18+", onClick: () => { setAdultFilterMode("only"); }, active: adultFilterMode === "only", }, ],} ) ) ) , postPage.React.createElement('hr', { className: "border-notWhite",} ) , postPage.React.createElement(MultiSwitchButton, { tabs: [ { label: "random", onClick: () => { setSortOrder("random"); }, active: sortOrder === "random", }, { label: "newest first", onClick: () => { setSortOrder("newest"); }, active: sortOrder === "newest", }, { label: "oldest first", onClick: () => { setSortOrder("oldest"); }, active: sortOrder === "oldest", }, ],} ) ) ) , postPage.React.createElement(postPage.ve, { as: "div", 'data-theme': postBoxTheme.current, className: postPage.tw`co-themed-box co-artist-alley-filters cohost-shadow-light dark:cohost-shadow-dark col-span-1 mt-4 flex h-fit max-h-max min-h-0 w-full flex-col rounded-lg border ${ className ?? "" }`, defaultOpen: isDesktop,} , postPage.React.createElement(postPage.ve.Button, { as: "header", className: "flex flex-row items-center justify-between rounded-t-lg p-3 ui-not-open:rounded-b-lg" ,} , postPage.React.createElement(postPage.ForwardRef$2, { className: "h-5 w-5 ui-open:rotate-90 motion-safe:transition-transform" ,} ) , postPage.React.createElement('span', { className: "font-league text-xs uppercase" ,}, "your listing here!" ) ) , postPage.React.createElement(postPage.ve.Panel, { as: "div", className: "p-3",} , postPage.React.createElement('div', { className: "co-prose prose mb-3" ,} , postPage.React.createElement('p', null, "are you an artist, musician, game developer, or other creative? got something you want cohost users to know about? get an artist alley listing! only $10 per week!" ) ) , postPage.React.createElement(postPage.BasicButton, { buttonSize: "regular", buttonColor: "post-box-filled", as: "a", href: postPage.sitemap.public.artistAlley.create().toString(), extraClasses: "mt-2",} , "buy a listing" ) , hasPurchasedListing && ( postPage.React.createElement(postPage.BasicButton, { buttonSize: "regular", buttonColor: "post-box-filled", as: "a", href: postPage.sitemap.public.artistAlley .ownerManage() .toString(), extraClasses: "mt-2",} , "manage your listings" ) ) ) ) ) ); }; function generateMasonryBreakpoints( maxCols ) { const breakpoints = { default: 1, }; // breakpoints are based on a max-width, so we need to set the breakpoint // based on the maximum number of columns below that width. columns are max // 300px, so 2 columns requires a min-width of 600px, meaning 1 column has a // max-width of 600px. i swear this makes sense. - jkap, 4/23/24 for (let i = 1; i <= maxCols; i++) { breakpoints[300 * (i + 1)] = i; } // since it's based on max-width, we set a fallback breakpoint that's // impossible to hit so that we don't snap back to 1 column on larger // screens. breakpoints[Number.MAX_SAFE_INTEGER] = maxCols + 1; return breakpoints; } const ArtistAlleyPage = () => { const { isAdult, explicitlyCollapseAdultContent } = postPage.useDisplayPrefs(); const [adultState, setAdultFilterMode] = useTransitionState( // if the user is an adult, use their display setting. otherwise, // default to hiding adult content isAdult ? explicitlyCollapseAdultContent ? "hide" : "include" : "hide" ); const [categoryMatch, setCategoryMatch] = useTransitionState("any"); const categories = useSet(); const artistAlleyLive = postPage.index_browserExports.useFlag(postPage.FeatureFlag.Enum["artist-alley-listings"]); const [sortOrder, setSortOrder] = useTransitionState("random"); return ( postPage.React.createElement(artistAlleyListing.ArtistAlleyFilterProvider.Provider, { value: { adultFilterMode: adultState, isAdult, categories, setAdultFilterMode, categoryMatch, setCategoryMatch, sortOrder, setSortOrder, },} , postPage.React.createElement('div', { className: "styled-scrollbars-light dark:styled-scrollbars-dark styled-scrollbars-light dark:styled-scrollbars-dark container mx-auto flex w-full max-w-full flex-row [height:calc(100vh-4rem)]" ,} , postPage.React.createElement(postPage.Helmet, { title: "artist alley" ,} ) , postPage.React.createElement(postPage.SidebarMenu, { narrowMode: true,} ) , artistAlleyLive ? ( postPage.React.createElement(postPage.reactExports.Suspense, { fallback: postPage.React.createElement('div', null, "aaaaaaa"),} , postPage.React.createElement(ArtistAlleyInner, null ) ) ) : ( postPage.React.createElement(ArtistAlleyClosed, null ) ) ) ) ); }; const ArtistAlleyClosed = () => { const theme = postPage.useDynamicTheme(); return ( postPage.React.createElement('div', { className: "mt-12",} , postPage.React.createElement('div', { 'data-theme': theme.current, className: "co-themed-box co-static" ,} , postPage.React.createElement('div', { className: "co-prose prose" ,} , postPage.React.createElement('h1', null, "artist alley is currently closed" ) , postPage.React.createElement('p', null, "we're still working on getting everything set up! if you're interested in buying a listing, you can do so on the" , " " , postPage.React.createElement('a', { href: postPage.sitemap.public.artistAlley .create() .toString(),} , "sign up page!" ) ) , postPage.React.createElement('p', null, "artist alley should be live soon. check out" , " " , postPage.React.createElement('a', { href: "https://cohost.org/staff",}, "@staff"), " for the most recent info!" ) ) ) ) ); }; // doing this with zod because i was having trouble getting typescript to handle // the discriminated union correctly otherwise postPage.mod.discriminatedUnion("type", [ postPage.mod.object({ type: postPage.mod.literal("LISTING"), id: postPage.ArtistAlleyAdId, listing: WireArtistAlley, project: postPage.WireProjectModel, }), postPage.mod.object({ type: postPage.mod.literal("FILTER"), id: postPage.mod.literal("FILTER") }), ]); const ArtistAlleyInner = () => { const toastId = postPage.reactExports.useRef(undefined); const { operatingPrime } = postPage.useSiteConfig(); const { adultFilterMode, categories, categoryMatch, sortOrder } = artistAlleyListing.useArtistAlleyFilters(); const [{ pages }, { fetchNextPage, fetchStatus }] = postPage.trpc.artistAlley.getListingsForDisplay.useSuspenseInfiniteQuery( { adultDisplayMode: adultFilterMode, categories: Array.from(categories), sortModulus: operatingPrime, categoryMatch, sortOrder, }, { getNextPageParam: (lastPage) => lastPage.nextCursor, keepPreviousData: true, // never refetch, each page load should be fully deterministic refetchInterval: Infinity, refetchOnMount: false, refetchOnReconnect: false, refetchOnWindowFocus: false, refetchIntervalInBackground: false, // toast management onError: (err) => { postPage.n.error(err.message, { id: toastId.current, }); }, onSuccess: () => { postPage.n.dismiss(toastId.current); }, } ); postPage.reactExports.useEffect(() => { if (fetchStatus === "fetching") { toastId.current = postPage.n.loading("loading listings...", { id: toastId.current, }); } }, [fetchStatus]); const flattenedListings = postPage.reactExports.useMemo(() => { return pages.flatMap((page) => page.listings) ?? []; }, [pages]); const flattenedProjects = postPage.reactExports.useMemo(() => { const projects = new Map(); pages.forEach((page) => { Object.values(page.relevantProjects).forEach((project) => { projects.set(project.projectId, project); }); }); return projects; }, [pages]); const masonicListings = postPage.reactExports.useMemo(() => { const val = flattenedListings .map((listing) => { const project = flattenedProjects.get(listing.projectId); if (!project) return undefined; return { type: "LISTING", id: listing.id, listing, project, }; }) .filter(postPage.isDefined); // inject the filter sentinel item at the beginning so it's rendered in the right place val.unshift({ type: "FILTER", id: "FILTER" }); return val; }, [flattenedListings, flattenedProjects]); const { ref, inView } = useInView(); postPage.reactExports.useEffect(() => { if (inView) { postPage.reactExports.startTransition(() => { void fetchNextPage(); }); } }, [inView, fetchNextPage]); const masonryBreakpoints = postPage.reactExports.useMemo(() => { return generateMasonryBreakpoints(20); }, []); return ( postPage.React.createElement('div', { className: "flex w-full flex-col gap-4" ,} , postPage.React.createElement(Masonry, { breakpointCols: masonryBreakpoints, className: "artist-alley-grid w-full" , columnClassName: "artist-alley-grid_column",} , masonicListings.map((listing) => ( postPage.React.createElement(ListingMasonryWrapper, { key: listing.id, data: listing,} ) )) ) /* marker so we can load the next page */ , postPage.React.createElement('div', { className: "h-[1px] w-[1px] flex-shrink-0" , ref: ref,}) ) ); }; const ListingMasonryWrapper = ({ data }) => { if (data.type === "LISTING") return ( postPage.React.createElement('div', { key: data.listing.id, className: "mt-4 inline-block w-full max-w-[300px]" ,} , postPage.React.createElement(artistAlleyListing.ArtistAlleyListing, { listing: data.listing, project: data.project,} ) ) ); return ( postPage.React.createElement('div', { key: data.id, className: "mt-4 inline-block w-full max-w-[300px]" ,} , postPage.React.createElement(ArtistAlleyFilters, null ) ) ); }; exports.ArtistAlleyPage = ArtistAlleyPage; exports.default = ArtistAlleyPage; }));