1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 20:04:24 +02:00

Bundled output for commit 3537f76eab

Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
This commit is contained in:
flarum-bot
2021-05-12 23:29:46 +00:00
parent 3537f76eab
commit c3a684c7ed
213 changed files with 6462 additions and 30 deletions

View File

@@ -0,0 +1,18 @@
/**
* The `AffixedSidebar` component uses Bootstrap's "affix" plugin to keep a
* sidebar navigation at the top of the viewport when scrolling.
*
* ### Children
*
* The component must wrap an element that itself wraps an <ul> element, which
* will be "affixed".
*
* @see https://getbootstrap.com/docs/3.4/javascript/#affix
*/
export default class AffixedSidebar extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
boundOnresize: (() => void) | undefined;
onresize(): void;
bottom: number | undefined;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,88 @@
/**
* The `AvatarEditor` component displays a user's avatar along with a dropdown
* menu which allows the user to upload/remove the avatar.
*
* ### Attrs
*
* - `className`
* - `user`
*/
export default class AvatarEditor extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Whether or not an avatar upload is in progress.
*
* @type {Boolean}
*/
loading: boolean | undefined;
/**
* Whether or not an image has been dragged over the dropzone.
*
* @type {Boolean}
*/
isDraggedOver: boolean | undefined;
/**
* Get the items in the edit avatar dropdown menu.
*
* @return {ItemList}
*/
controlItems(): ItemList;
/**
* Enable dragover style
*
* @param {Event} e
*/
enableDragover(e: Event): void;
/**
* Disable dragover style
*
* @param {Event} e
*/
disableDragover(e: Event): void;
/**
* Upload avatar when file is dropped into dropzone.
*
* @param {Event} e
*/
dropUpload(e: Event): void;
/**
* If the user doesn't have an avatar, there's no point in showing the
* controls dropdown, because only one option would be viable: uploading.
* Thus, when the avatar editor's dropdown toggle button is clicked, we prompt
* the user to upload an avatar immediately.
*
* @param {Event} e
*/
quickUpload(e: Event): void;
/**
* Upload avatar using file picker
*/
openPicker(): void;
/**
* Upload avatar
*
* @param {File} file
*/
upload(file: File): void;
/**
* Remove the user's avatar.
*/
remove(): void;
/**
* After a successful upload/removal, push the updated user data into the
* store, and force a recomputation of the user's avatar color.
*
* @param {Object} response
* @protected
*/
protected success(response: Object): void;
/**
* If avatar upload/removal fails, stop loading.
*
* @param {Object} response
* @protected
*/
protected failure(response: Object): void;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,25 @@
/**
* The `ChangeEmailModal` component shows a modal dialog which allows the user
* to change their email address.
*/
export default class ChangeEmailModal extends Modal {
/**
* Whether or not the email has been changed successfully.
*
* @type {Boolean}
*/
success: boolean | undefined;
/**
* The value of the email input.
*
* @type {function}
*/
email: Function | undefined;
/**
* The value of the password input.
*
* @type {function}
*/
password: Function | undefined;
}
import Modal from "../../common/components/Modal";

View File

@@ -0,0 +1,7 @@
/**
* The `ChangePasswordModal` component shows a modal dialog which allows the
* user to send themself a password reset email.
*/
export default class ChangePasswordModal extends Modal {
}
import Modal from "../../common/components/Modal";

View File

@@ -0,0 +1,40 @@
/**
* The `CommentPost` component displays a standard `comment`-typed post. This
* includes a number of item lists (controls, header, and footer) surrounding
* the post's HTML content.
*
* ### Attrs
*
* - `post`
*/
export default class CommentPost extends Post {
/**
* If the post has been hidden, then this flag determines whether or not its
* content has been expanded.
*
* @type {Boolean}
*/
revealContent: boolean | undefined;
/**
* Whether or not the user hover card inside of PostUser is visible.
* The property must be managed in CommentPost to be able to use it in the subtree check
*
* @type {Boolean}
*/
cardVisible: boolean | undefined;
refreshContent(): void;
contentHtml: any;
isEditing(): any;
/**
* Toggle the visibility of a hidden post's content.
*/
toggleContent(): void;
/**
* Build an item list for the post's header.
*
* @return {ItemList}
*/
headerItems(): ItemList;
}
import Post from "./Post";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,112 @@
/**
* The `Composer` component displays the composer. It can be loaded with a
* content component with `load` and then its position/state can be altered with
* `show`, `hide`, `close`, `minimize`, `fullScreen`, and `exitFullScreen`.
*/
export default class Composer extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* The composer's "state".
*
* @type {ComposerState}
*/
state: ComposerState | undefined;
/**
* Whether or not the composer currently has focus.
*
* @type {Boolean}
*/
active: boolean | undefined;
prevPosition: any;
handlers: {} | undefined;
/**
* Add the necessary event handlers to the composer's handle so that it can
* be used to resize the composer.
*/
configHandle(vnode: any): void;
/**
* Resize the composer according to mouse movement.
*
* @param {Event} e
*/
onmousemove(e: Event): void;
/**
* Finish resizing the composer when the mouse is released.
*/
onmouseup(): void;
handle: any;
/**
* Draw focus to the first focusable content element (the text editor).
*/
focus(): void;
/**
* Update the DOM to reflect the composer's current height. This involves
* setting the height of the composer's root element, and adjusting the height
* of any flexible elements inside the composer's body.
*/
updateHeight(): void;
/**
* Update the amount of padding-bottom on the body so that the page's
* content will still be visible above the composer when the page is
* scrolled right to the bottom.
*/
updateBodyPadding(): void;
/**
* Trigger the right animation depending on the desired new position.
*/
animatePositionChange(): void;
/**
* Animate the Composer into the new position by changing the height.
*/
animateHeightChange(): JQuery.Promise<JQuery<HTMLElement>, any, any>;
/**
* Show the Composer backdrop.
*/
showBackdrop(): void;
$backdrop: JQuery<HTMLElement> | undefined;
/**
* Hide the Composer backdrop.
*/
hideBackdrop(): void;
/**
* Animate the composer sliding up from the bottom to take its normal height.
*
* @private
*/
private show;
/**
* Animate closing the composer.
*
* @private
*/
private hide;
/**
* Shrink the composer until only its title is visible.
*
* @private
*/
private minimize;
/**
* Build an item list for the composer's controls.
*
* @return {ItemList}
*/
controlItems(): ItemList;
/**
* Initialize default Composer height.
*/
initializeHeight(): void;
/**
* Default height of the Composer in case none is saved.
* @returns {Integer}
*/
defaultHeight(): any;
/**
* Save a new Composer height and update the DOM.
* @param {Integer} height
*/
changeHeight(height: any): void;
}
import Component from "../../common/Component";
import ComposerState from "../states/ComposerState";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,51 @@
/**
* The `ComposerBody` component handles the body, or the content, of the
* composer. Subclasses should implement the `onsubmit` method and override
* `headerTimes`.
*
* ### Attrs
*
* - `composer`
* - `originalContent`
* - `submitLabel`
* - `placeholder`
* - `user`
* - `confirmExit`
* - `disabled`
*
* @abstract
*/
export default class ComposerBody extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
composer: any;
/**
* Whether or not the component is loading.
*
* @type {Boolean}
*/
loading: boolean | undefined;
/**
* Check if there is any unsaved data.
*
* @return {String}
*/
hasChanges(): string;
/**
* Build an item list for the composer's header.
*
* @return {ItemList}
*/
headerItems(): ItemList;
/**
* Handle the submit event of the text editor.
*
* @abstract
*/
onsubmit(): void;
/**
* Stop loading.
*/
loaded(): void;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,8 @@
/**
* The `ComposerButton` component displays a button suitable for the composer
* controls.
*/
export default class ComposerButton extends Button {
static initAttrs(attrs: any): void;
}
import Button from "../../common/components/Button";

View File

@@ -0,0 +1,18 @@
/**
* The `ComposerPostPreview` component renders Markdown as HTML using the
* TextFormatter library, polling a data source for changes every 50ms. This is
* done to prevent expensive redraws on e.g. every single keystroke, while
* still retaining the perception of live updates for the user.
*
* ### Attrs
*
* - `composer` The state of the composer controlling this preview.
* - `className` A CSS class for the element surrounding the preview.
* - `surround` A callback that can execute code before and after re-render, e.g. for scroll anchoring.
*/
export default class ComposerPostPreview extends Component<import("../../common/Component").ComponentAttrs> {
static initAttrs(attrs: any): void;
constructor();
updateInterval: number | undefined;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,34 @@
/**
* The `DiscussionComposer` component displays the composer content for starting
* a new discussion. It adds a text field as a header control so the user can
* enter the title of their discussion. It also overrides the `submit` and
* `willExit` actions to account for the title.
*
* ### Attrs
*
* - All of the attrs for ComposerBody
* - `titlePlaceholder`
*/
export default class DiscussionComposer extends ComposerBody {
static initAttrs(attrs: any): void;
/**
* The value of the title input.
*
* @type {Function}
*/
title: Function | undefined;
/**
* Handle the title input's keydown event. When the return key is pressed,
* move the focus to the start of the text editor.
*
* @param {Event} e
*/
onkeydown(e: Event): void;
/**
* Get the data to submit to the server when the discussion is saved.
*
* @return {Object}
*/
data(): Object;
}
import ComposerBody from "./ComposerBody";

View File

@@ -0,0 +1,18 @@
/**
* The `DiscussionHero` component displays the hero on a discussion page.
*
* ### attrs
*
* - `discussion`
*/
export default class DiscussionHero extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Build an item list for the contents of the discussion hero.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,11 @@
/**
* The `DiscussionList` component displays a list of discussions.
*
* ### Attrs
*
* - `state` A DiscussionListState object that represents the discussion lists's state.
*/
export default class DiscussionList extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,58 @@
/**
* The `DiscussionListItem` component shows a single discussion in the
* discussion list.
*
* ### Attrs
*
* - `discussion`
* - `params`
*/
export default class DiscussionListItem extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Set up a subtree retainer so that the discussion will not be redrawn
* unless new data comes in.
*
* @type {SubtreeRetainer}
*/
subtree: SubtreeRetainer | undefined;
elementAttrs(): {
className: string;
};
highlightRegExp: RegExp | undefined;
/**
* Determine whether or not the discussion is currently being viewed.
*
* @return {Boolean}
*/
active(): boolean;
/**
* Determine whether or not information about who started the discussion
* should be displayed instead of information about the most recent reply to
* the discussion.
*
* @return {Boolean}
*/
showFirstPost(): boolean;
/**
* Determine whether or not the number of replies should be shown instead of
* the number of unread posts.
*
* @return {Boolean}
*/
showRepliesCount(): boolean;
/**
* Mark the discussion as read.
*/
markAsRead(): void;
/**
* Build an item list of info for a discussion listing. By default this is
* just the first/last post indicator.
*
* @return {ItemList}
*/
infoItems(): ItemList;
}
import Component from "../../common/Component";
import SubtreeRetainer from "../../common/utils/SubtreeRetainer";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,19 @@
/**
* The `DiscussionListPane` component displays the list of previously viewed
* discussions in a panel that can be displayed by moving the mouse to the left
* edge of the screen, where it can also be pinned in place.
*
* ### Attrs
*
* - `state` A DiscussionListState object that represents the discussion lists's state.
*/
export default class DiscussionListPane extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Are we on a device that's larger than we consider "mobile"?
*
* @returns {boolean}
*/
enoughSpace(): boolean;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,53 @@
/**
* The `DiscussionPage` component displays a whole discussion page, including
* the discussion list pane, the hero, the posts, and the sidebar.
*/
export default class DiscussionPage extends Page {
/**
* The discussion that is being viewed.
*
* @type {Discussion}
*/
discussion: any;
/**
* The number of the first post that is currently visible in the viewport.
*
* @type {number}
*/
near: number | undefined;
/**
* Load the discussion from the API or use the preloaded one.
*/
load(): void;
/**
* Get the parameters that should be passed in the API request to get the
* discussion.
*
* @return {Object}
*/
requestParams(): Object;
/**
* Initialize the component to display the given discussion.
*
* @param {Discussion} discussion
*/
show(discussion: any): void;
stream: PostStreamState | undefined;
/**
* Build an item list for the contents of the sidebar.
*
* @return {ItemList}
*/
sidebarItems(): ItemList;
/**
* When the posts that are visible in the post stream change (i.e. the user
* scrolls up or down), then we update the URL and mark the posts as read.
*
* @param {Integer} startNumber
* @param {Integer} endNumber
*/
positionChanged(startNumber: any, endNumber: any): void;
}
import Page from "../../common/components/Page";
import PostStreamState from "../states/PostStreamState";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,11 @@
/**
* The `DiscussionRenamedNotification` component displays a notification which
* indicates that a discussion has had its title changed.
*
* ### Attrs
*
* - All of the attrs for Notification
*/
export default class DiscussionRenamedNotification extends Notification {
}
import Notification from "./Notification";

View File

@@ -0,0 +1,11 @@
/**
* The `DiscussionRenamedPost` component displays a discussion event post
* indicating that the discussion has been renamed.
*
* ### Attrs
*
* - All of the attrs for EventPost
*/
export default class DiscussionRenamedPost extends EventPost {
}
import EventPost from "./EventPost";

View File

@@ -0,0 +1,11 @@
import { SearchSource } from './Search';
import Mithril from 'mithril';
/**
* The `DiscussionsSearchSource` finds and displays discussion search results in
* the search dropdown.
*/
export default class DiscussionsSearchSource implements SearchSource {
protected results: Map<string, unknown[]>;
search(query: string): Promise<Map<string, unknown[]>>;
view(query: string): Array<Mithril.Vnode>;
}

View File

@@ -0,0 +1,9 @@
/**
* The `DiscussionsUserPage` component shows a discussion list inside of a user
* page.
*/
export default class DiscussionsUserPage extends UserPage {
state: DiscussionListState | undefined;
}
import UserPage from "./UserPage";
import DiscussionListState from "../states/DiscussionListState";

View File

@@ -0,0 +1,24 @@
/**
* The `EditPostComposer` component displays the composer content for editing a
* post. It sets the initial content to the content of the post that is being
* edited, and adds a header control to indicate which post is being edited.
*
* ### Attrs
*
* - All of the attrs for ComposerBody
* - `post`
*/
export default class EditPostComposer extends ComposerBody {
static initAttrs(attrs: any): void;
/**
* Jump to the preview when triggered by the text editor.
*/
jumpToPreview(e: any): void;
/**
* Get the data to submit to the server when the post is saved.
*
* @return {Object}
*/
data(): Object;
}
import ComposerBody from "./ComposerBody";

View File

@@ -0,0 +1,39 @@
/**
* The `EventPost` component displays a post which indicating a discussion
* event, like a discussion being renamed or stickied. Subclasses must implement
* the `icon` and `description` methods.
*
* ### Attrs
*
* - All of the attrs for `Post`
*
* @abstract
*/
export default class EventPost extends Post {
/**
* Get the name of the event icon.
*
* @return {String}
*/
icon(): string;
/**
* Get the description text for the event.
*
* @param {Object} data
* @return {String|Object} The description to render in the DOM
*/
description(data: Object): string | Object;
/**
* Get the translation key for the description of the event.
*
* @return {String}
*/
descriptionKey(): string;
/**
* Get the translation data for the description of the event.
*
* @return {Object}
*/
descriptionData(): Object;
}
import Post from "./Post";

View File

@@ -0,0 +1,24 @@
/**
* The `ForgotPasswordModal` component displays a modal which allows the user to
* enter their email address and request a link to reset their password.
*
* ### Attrs
*
* - `email`
*/
export default class ForgotPasswordModal extends Modal {
/**
* The value of the email input.
*
* @type {Function}
*/
email: Function | undefined;
/**
* Whether or not the password reset email was sent successfully.
*
* @type {Boolean}
*/
success: boolean | undefined;
alert: any;
}
import Modal from "../../common/components/Modal";

View File

@@ -0,0 +1,15 @@
/**
* The `HeaderPrimary` component displays primary header controls. On the
* default skin, these are shown just to the right of the forum title.
*/
export default class HeaderPrimary extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,16 @@
/**
* The `HeaderSecondary` component displays secondary header controls, such as
* the search box and the user menu. On the default skin, these are shown on the
* right side of the header.
*/
export default class HeaderSecondary extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,59 @@
/**
* The `IndexPage` component displays the index page, including the welcome
* hero, the sidebar, and the discussion list.
*/
export default class IndexPage extends Page {
static providesInitialSearch: boolean;
lastDiscussion: any;
setTitle(): void;
/**
* Get the component to display as the hero.
*
* @return {MithrilComponent}
*/
hero(): any;
/**
* Build an item list for the sidebar of the index page. By default this is a
* "New Discussion" button, and then a DropdownSelect component containing a
* list of navigation items.
*
* @return {ItemList}
*/
sidebarItems(): ItemList;
/**
* Build an item list for the navigation in the sidebar of the index page. By
* default this is just the 'All Discussions' link.
*
* @return {ItemList}
*/
navItems(): ItemList;
/**
* Build an item list for the part of the toolbar which is concerned with how
* the results are displayed. By default this is just a select box to change
* the way discussions are sorted.
*
* @return {ItemList}
*/
viewItems(): ItemList;
/**
* Build an item list for the part of the toolbar which is about taking action
* on the results. By default this is just a "mark all as read" button.
*
* @return {ItemList}
*/
actionItems(): ItemList;
/**
* Open the composer for a new discussion or prompt the user to login.
*
* @return {Promise}
*/
newDiscussionAction(): Promise<any>;
/**
* Mark all discussions as read.
*
* @return void
*/
markAllAsRead(): void;
}
import Page from "../../common/components/Page";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,8 @@
/**
* The `LoadingPost` component shows a placeholder that looks like a post,
* indicating that the post is loading.
*/
export default class LoadingPost extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,12 @@
/**
* The `LogInButton` component displays a social login button which will open
* a popup window containing the specified path.
*
* ### Attrs
*
* - `path`
*/
export default class LogInButton extends Button {
static initAttrs(attrs: any): void;
}
import Button from "../../common/components/Button";

View File

@@ -0,0 +1,15 @@
/**
* The `LogInButtons` component displays a collection of social login buttons.
*/
export default class LogInButtons extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Build a list of LogInButton components.
*
* @return {ItemList}
* @public
*/
public items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,47 @@
/**
* The `LogInModal` component displays a modal dialog with a login form.
*
* ### Attrs
*
* - `identification`
* - `password`
*/
export default class LogInModal extends Modal {
/**
* The value of the identification input.
*
* @type {Function}
*/
identification: Function | undefined;
/**
* The value of the password input.
*
* @type {Function}
*/
password: Function | undefined;
/**
* The value of the remember me input.
*
* @type {Function}
*/
remember: Function | undefined;
body(): JSX.Element[];
fields(): ItemList;
footer(): (string | JSX.Element)[];
/**
* Open the forgot password modal, prefilling it with an email if the user has
* entered one.
*
* @public
*/
public forgotPassword(): void;
/**
* Open the sign up modal, prefilling it with an email/username/password if
* the user has entered one.
*
* @public
*/
public signUp(): void;
}
import Modal from "../../common/components/Modal";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,46 @@
/**
* The `Notification` component abstract displays a single notification.
* Subclasses should implement the `icon`, `href`, and `content` methods.
*
* ### Attrs
*
* - `notification`
*
* @abstract
*/
export default class Notification extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Get the name of the icon that should be displayed in the notification.
*
* @return {String}
* @abstract
*/
icon(): string;
/**
* Get the URL that the notification should link to.
*
* @return {String}
* @abstract
*/
href(): string;
/**
* Get the content of the notification.
*
* @return {VirtualElement}
* @abstract
*/
content(): any;
/**
* Get the excerpt of the notification.
*
* @return {VirtualElement}
* @abstract
*/
excerpt(): any;
/**
* Mark the notification as read.
*/
markAsRead(): void;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,83 @@
/**
* The `NotificationGrid` component displays a table of notification types and
* methods, allowing the user to toggle each combination.
*
* ### Attrs
*
* - `user`
*/
export default class NotificationGrid extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Information about the available notification methods.
*
* @type {Array}
*/
methods: any[] | undefined;
/**
* A map of which notification checkboxes are loading.
*
* @type {Object}
*/
loading: Object | undefined;
/**
* Information about the available notification types.
*
* @type {Array}
*/
types: any[] | undefined;
/**
* Toggle the state of the given preferences, based on the value of the first
* one.
*
* @param {Array} keys
*/
toggle(keys: any[]): void;
/**
* Toggle all notification types for the given method.
*
* @param {String} method
*/
toggleMethod(method: string): void;
/**
* Toggle all notification methods for the given type.
*
* @param {String} type
*/
toggleType(type: string): void;
/**
* Get the name of the preference key for the given notification type-method
* combination.
*
* @param {String} type
* @param {String} method
* @return {String}
*/
preferenceKey(type: string, method: string): string;
/**
* Build an item list for the notification methods to display in the grid.
*
* Each notification method is an object which has the following properties:
*
* - `name` The name of the notification method.
* - `icon` The icon to display in the column header.
* - `label` The label to display in the column header.
*
* @return {ItemList}
*/
notificationMethods(): ItemList;
/**
* Build an item list for the notification types to display in the grid.
*
* Each notification type is an object which has the following properties:
*
* - `name` The name of the notification type.
* - `icon` The icon to display in the notification grid row.
* - `label` The label to display in the notification grid row.
*
* @return {ItemList}
*/
notificationTypes(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,17 @@
/**
* The `NotificationList` component displays a list of the logged-in user's
* notifications, grouped by discussion.
*/
export default class NotificationList extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
$notifications: JQuery<HTMLElement> | undefined;
$scrollParent: JQuery<HTMLElement> | JQuery<Window & typeof globalThis> | undefined;
boundScrollHandler: (() => void) | undefined;
scrollHandler(): void;
/**
* If the NotificationList component isn't in a panel (e.g. on NotificationPage when mobile),
* we need to listen to scroll events on the window, and get scroll state from the body.
*/
inPanel(): boolean;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,8 @@
export default class NotificationsDropdown extends Dropdown {
onclick(): void;
goToRoute(): void;
getUnreadCount(): any;
getNewCount(): any;
menuClick(e: any): void;
}
import Dropdown from "../../common/components/Dropdown";

View File

@@ -0,0 +1,7 @@
/**
* The `NotificationsPage` component shows the notifications list. It is only
* used on mobile devices where the notifications dropdown is within the drawer.
*/
export default class NotificationsPage extends Page {
}
import Page from "../../common/components/Page";

View File

@@ -0,0 +1,56 @@
/**
* The `Post` component displays a single post. The basic post template just
* includes a controls dropdown; subclasses must implement `content` and `attrs`
* methods.
*
* ### Attrs
*
* - `post`
*
* @abstract
*/
export default class Post extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
loading: boolean | undefined;
/**
* Set up a subtree retainer so that the post will not be redrawn
* unless new data comes in.
*
* @type {SubtreeRetainer}
*/
subtree: SubtreeRetainer | undefined;
/**
* Get attributes for the post element.
*
* @return {Object}
*/
elementAttrs(): Object;
/**
* Get the post's content.
*
* @return {Array}
*/
content(): any[];
/**
* Get the post's classes.
*
* @param string classes
* @returns {string[]}
*/
classes(existing: any): string[];
/**
* Build an item list for the post's actions.
*
* @return {ItemList}
*/
actionItems(): ItemList;
/**
* Build an item list for the post's footer.
*
* @return {ItemList}
*/
footerItems(): ItemList;
}
import Component from "../../common/Component";
import SubtreeRetainer from "../../common/utils/SubtreeRetainer";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,12 @@
/**
* The `PostEdited` component displays information about when and by whom a post
* was edited.
*
* ### Attrs
*
* - `post`
*/
export default class PostEdited extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,20 @@
/**
* The `PostMeta` component displays the time of a post, and when clicked, shows
* a dropdown containing more information about the post (number, full time,
* permalink).
*
* ### Attrs
*
* - `post`
*/
export default class PostMeta extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Get the permalink for the given post.
*
* @param {Post} post
* @returns {String}
*/
getPermalink(post: any): string;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,12 @@
/**
* The `PostPreview` component shows a link to a post containing the avatar and
* username of the author, and a short excerpt of the post's content.
*
* ### Attrs
*
* - `post`
*/
export default class PostPreview extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,83 @@
/**
* The `PostStream` component displays an infinitely-scrollable wall of posts in
* a discussion. Posts that have not loaded will be displayed as placeholders.
*
* ### Attrs
*
* - `discussion`
* - `stream`
* - `targetPost`
* - `onPositionChange`
*/
export default class PostStream extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
discussion: any;
stream: any;
scrollListener: ScrollListener | undefined;
/**
* Start scrolling, if appropriate, to a newly-targeted post.
*/
triggerScroll(): void;
/**
*
* @param {Integer} top
*/
onscroll(top?: any): void;
calculatePositionTimeout: number | undefined;
/**
* Check if either extreme of the post stream is in the viewport,
* and if so, trigger loading the next/previous page.
*
* @param {Integer} top
*/
loadPostsIfNeeded(top?: any): void;
updateScrubber(top?: number): void;
/**
* Work out which posts (by number) are currently visible in the viewport, and
* fire an event with the information.
*/
calculatePosition(top?: number): void;
/**
* Get the distance from the top of the viewport to the point at which we
* would consider a post to be the first one visible.
*
* @return {Integer}
*/
getMarginTop(): any;
/**
* Scroll down to a certain post by number and 'flash' it.
*
* @param {Integer} number
* @param {Boolean} animate
* @return {jQuery.Deferred}
*/
scrollToNumber(number: any, animate: boolean): any;
/**
* Scroll down to a certain post by index.
*
* @param {Integer} index
* @param {Boolean} animate
* @param {Boolean} reply Whether or not to scroll to the reply placeholder.
* @return {jQuery.Deferred}
*/
scrollToIndex(index: any, animate: boolean, reply: boolean): any;
/**
* Scroll down to the given post.
*
* @param {jQuery} $item
* @param {Boolean} animate
* @param {Boolean} force Whether or not to force scrolling to the item, even
* if it is already in the viewport.
* @param {Boolean} reply Whether or not to scroll to the reply placeholder.
* @return {jQuery.Deferred}
*/
scrollToItem($item: JQueryStatic, animate: boolean, force: boolean, reply: boolean): any;
/**
* 'Flash' the given post, drawing the user's attention to it.
*
* @param {jQuery} $item
*/
flashItem($item: JQueryStatic): void;
}
import Component from "../../common/Component";
import ScrollListener from "../../common/utils/ScrollListener";

View File

@@ -0,0 +1,52 @@
/**
* The `PostStreamScrubber` component displays a scrubber which can be used to
* navigate/scrub through a post stream.
*
* ### Attrs
*
* - `stream`
* - `className`
*/
export default class PostStreamScrubber extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
stream: any;
handlers: {} | undefined;
scrollListener: ScrollListener | undefined;
dragging: boolean | undefined;
mouseStart: any;
indexStart: any;
/**
* Update the scrollbar's position to reflect the current values of the
* index/visible properties.
*
* @param {Boolean} animate
*/
updateScrubberValues(options?: {}): void;
adjustingHeight: boolean | undefined;
/**
* Go to the first post in the discussion.
*/
goToFirst(): void;
/**
* Go to the last post in the discussion.
*/
goToLast(): void;
onresize(): void;
onmousedown(e: any): void;
onmousemove(e: any): void;
onmouseup(): void;
onclick(e: any): void;
/**
* Get the percentage of the height of the scrubber that should be allocated
* to each post.
*
* @return {Object}
* @property {Number} index The percent per post for posts on either side of
* the visible part of the scrubber.
* @property {Number} visible The percent per post for the visible part of the
* scrubber.
*/
percentPerPost(): Object;
}
import Component from "../../common/Component";
import ScrollListener from "../../common/utils/ScrollListener";

View File

@@ -0,0 +1,19 @@
/**
* The `PostUser` component shows the avatar and username of a post's author.
*
* ### Attrs
*
* - `post`
*/
export default class PostUser extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Show the user card.
*/
showCard(): void;
/**
* Hide the user card.
*/
hideCard(): void;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,58 @@
/**
* The `PostsUserPage` component shows a user's activity feed inside of their
* profile.
*/
export default class PostsUserPage extends UserPage {
/**
* Whether or not the activity feed is currently loading.
*
* @type {Boolean}
*/
loading: boolean | undefined;
/**
* Whether or not there are any more activity items that can be loaded.
*
* @type {Boolean}
*/
moreResults: boolean | undefined;
/**
* The Post models in the feed.
*
* @type {Post[]}
*/
posts: any[] | undefined;
/**
* The number of activity items to load per request.
*
* @type {Integer}
*/
loadLimit: any;
/**
* Clear and reload the user's activity feed.
*
* @public
*/
public refresh(): void;
/**
* Load a new page of the user's activity feed.
*
* @param {Integer} [offset] The position to start getting results from.
* @return {Promise}
* @protected
*/
protected loadResults(offset?: any): Promise<any>;
/**
* Load the next page of results.
*
* @public
*/
public loadMore(): void;
/**
* Parse results and append them to the activity feed.
*
* @param {Post[]} results
* @return {Post[]}
*/
parseResults(results: any[]): any[];
}
import UserPage from "./UserPage";

View File

@@ -0,0 +1,10 @@
/**
* The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion
*/
export default class RenameDiscussionModal extends Modal {
discussion: any;
currentTitle: any;
newTitle: Stream<any> | undefined;
}
import Modal from "../../common/components/Modal";
import Stream from "../../common/utils/Stream";

View File

@@ -0,0 +1,23 @@
/**
* The `ReplyComposer` component displays the composer content for replying to a
* discussion.
*
* ### Attrs
*
* - All of the attrs of ComposerBody
* - `discussion`
*/
export default class ReplyComposer extends ComposerBody {
static initAttrs(attrs: any): void;
/**
* Jump to the preview when triggered by the text editor.
*/
jumpToPreview(e: any): void;
/**
* Get the data to submit to the server when the reply is saved.
*
* @return {Object}
*/
data(): Object;
}
import ComposerBody from "./ComposerBody";

View File

@@ -0,0 +1,13 @@
/**
* The `ReplyPlaceholder` component displays a placeholder for a reply, which,
* when clicked, opens the reply composer.
*
* ### Attrs
*
* - `discussion`
*/
export default class ReplyPlaceholder extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
anchorPreview(preview: any): void;
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,103 @@
import Component, { ComponentAttrs } from '../../common/Component';
import ItemList from '../../common/utils/ItemList';
import KeyboardNavigatable from '../utils/KeyboardNavigatable';
import SearchState from '../states/SearchState';
import Mithril from 'mithril';
/**
* The `SearchSource` interface defines a section of search results in the
* search dropdown.
*
* Search sources should be registered with the `Search` component class
* by extending the `sourceItems` method. When the user types a
* query, each search source will be prompted to load search results via the
* `search` method. When the dropdown is redrawn, it will be constructed by
* putting together the output from the `view` method of each source.
*/
export interface SearchSource {
/**
* Make a request to get results for the given query.
*/
search(query: string): any;
/**
* Get an array of virtual <li>s that list the search results for the given
* query.
*/
view(query: string): Array<Mithril.Vnode>;
}
export interface SearchAttrs extends ComponentAttrs {
/** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */
state: SearchState;
}
/**
* The `Search` component displays a menu of as-you-type results from a variety
* of sources.
*
* The search box will be 'activated' if the app's search state's
* getInitialSearch() value is a truthy value. If this is the case, an 'x'
* button will be shown next to the search field, and clicking it will clear the search.
*
* ATTRS:
*
* - state: SearchState instance.
*/
export default class Search<T extends SearchAttrs = SearchAttrs> extends Component<T> {
static MIN_SEARCH_LEN: number;
protected state: SearchState;
/**
* Whether or not the search input has focus.
*/
protected hasFocus: boolean;
/**
* An array of SearchSources.
*/
protected sources: SearchSource[];
/**
* The number of sources that are still loading results.
*/
protected loadingSources: number;
/**
* The index of the currently-selected <li> in the results list. This can be
* a unique string (to account for the fact that an item's position may jump
* around as new results load), but otherwise it will be numeric (the
* sequential position within the list).
*/
protected index: number;
protected navigator: KeyboardNavigatable;
protected searchTimeout?: number;
private updateMaxHeightHandler?;
oninit(vnode: Mithril.Vnode<T, this>): void;
view(): JSX.Element;
updateMaxHeight(): void;
onupdate(vnode: any): void;
oncreate(vnode: any): void;
onremove(vnode: any): void;
/**
* Navigate to the currently selected search result and close the list.
*/
selectResult(): void;
/**
* Clear the search
*/
clear(): void;
/**
* Build an item list of SearchSources.
*/
sourceItems(): ItemList;
/**
* Get all of the search result items that are selectable.
*/
selectableItems(): JQuery;
/**
* Get the position of the currently selected search result item.
*/
getCurrentNumericIndex(): number;
/**
* Get the <li> in the search results with the given index (numeric or named).
*/
getItem(index: number): JQuery;
/**
* Set the currently-selected search result item to the one with the given
* index.
*/
setIndex(index: number, scrollToItem?: boolean): void;
}

View File

@@ -0,0 +1,14 @@
/**
* The `SessionDropdown` component shows a button with the current user's
* avatar/name, with a dropdown of session controls.
*/
export default class SessionDropdown extends Dropdown {
/**
* Build an item list for the contents of the dropdown menu.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Dropdown from "../../common/components/Dropdown";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,33 @@
/**
* The `SettingsPage` component displays the user's settings control panel, in
* the context of their user profile.
*/
export default class SettingsPage extends UserPage {
/**
* Build an item list for the user's settings controls.
*
* @return {ItemList}
*/
settingsItems(): ItemList;
/**
* Build an item list for the user's account settings.
*
* @return {ItemList}
*/
accountItems(): ItemList;
/**
* Build an item list for the user's notification settings.
*
* @return {ItemList}
*/
notificationsItems(): ItemList;
/**
* Build an item list for the user's privacy settings.
*
* @return {ItemList}
*/
privacyItems(): ItemList;
discloseOnlineLoading: boolean | undefined;
}
import UserPage from "./UserPage";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,50 @@
/**
* The `SignUpModal` component displays a modal dialog with a singup form.
*
* ### Attrs
*
* - `username`
* - `email`
* - `password`
* - `token` An email token to sign up with.
*/
export default class SignUpModal extends Modal {
/**
* The value of the username input.
*
* @type {Function}
*/
username: Function | undefined;
/**
* The value of the email input.
*
* @type {Function}
*/
email: Function | undefined;
/**
* The value of the password input.
*
* @type {Function}
*/
password: Function | undefined;
isProvided(field: any): any;
body(): (string | JSX.Element)[];
fields(): ItemList;
footer(): JSX.Element[];
/**
* Open the log in modal, prefilling it with an email/username/password if
* the user has entered one.
*
* @public
*/
public logIn(): void;
/**
* Get the data that should be submitted in the sign-up request.
*
* @return {Object}
* @protected
*/
protected submitData(): Object;
}
import Modal from "../../common/components/Modal";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,12 @@
/**
* Displays information about a the first or last post in a discussion.
*
* ### Attrs
*
* - `discussion`
* - `lastPost`
*/
export default class TerminalPost extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -0,0 +1,23 @@
/**
* The `UserCard` component displays a user's profile card. This is used both on
* the `UserPage` (in the hero) and in discussions, shown when hovering over a
* post author.
*
* ### Attrs
*
* - `user`
* - `className`
* - `editable`
* - `controlsButtonClassName`
*/
export default class UserCard extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
/**
* Build an item list of tidbits of info to show on this user's profile.
*
* @return {ItemList}
*/
infoItems(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,50 @@
/**
* The `UserPage` component shows a user's profile. It can be extended to show
* content inside of the content area. See `ActivityPage` and `SettingsPage` for
* examples.
*
* @abstract
*/
export default class UserPage extends Page {
/**
* The user this page is for.
*
* @type {User}
*/
user: any;
/**
* Get the content to display in the user page.
*
* @return {VirtualElement}
*/
content(): any;
/**
* Initialize the component with a user, and trigger the loading of their
* activity feed.
*
* @param {User} user
* @protected
*/
protected show(user: any): void;
/**
* Given a username, load the user's profile from the store, or make a request
* if we don't have it yet. Then initialize the profile page with that user.
*
* @param {String} username
*/
loadUser(username: string): void;
/**
* Build an item list for the content of the sidebar.
*
* @return {ItemList}
*/
sidebarItems(): ItemList;
/**
* Build an item list for the navigation in the sidebar.
*
* @return {ItemList}
*/
navItems(): ItemList;
}
import Page from "../../common/components/Page";
import ItemList from "../../common/utils/ItemList";

View File

@@ -0,0 +1,11 @@
import { SearchSource } from './Search';
import Mithril from 'mithril';
/**
* The `UsersSearchSource` finds and displays user search results in the search
* dropdown.
*/
export default class UsersSearchResults implements SearchSource {
protected results: Map<string, unknown[]>;
search(query: string): Promise<void>;
view(query: string): Array<Mithril.Vnode>;
}

View File

@@ -0,0 +1,13 @@
/**
* The `WelcomeHero` component displays a hero that welcomes the user to the
* forum.
*/
export default class WelcomeHero extends Component<import("../../common/Component").ComponentAttrs> {
constructor();
hidden: string | boolean | null | undefined;
/**
* Hide the welcome hero.
*/
hide(): void;
}
import Component from "../../common/Component";