Adding AlertBox

This commit is contained in:
Jean Ouina 2020-07-11 21:29:08 +02:00
parent 2ff7a5cea8
commit e4390f7a99
15 changed files with 1881 additions and 1126 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,260 +1,281 @@
// Good luck to read my code, Even me can't read it properly. // Good luck to read my code, Even me can't read it properly.
import { stat } from "fs" import { stat } from "fs"
import { uuidv4 } from "../modules/distant" import { uuidv4 } from "../modules/distant"
import webpackModules from "../modules/webpackModules" import webpackModules from "../modules/webpackModules"
import { remote } from "electron" import { remote } from "electron"
import MarginTop from "./margintop" import MarginTop from "./margintop"
const keys = { const keys = {
settingTitle: uuidv4() settingTitle: uuidv4()
} }
let formModule let formModule
export default class ApiPreview extends React.PureComponent { export default class ApiPreview extends React.PureComponent {
constructor(){ constructor(){
super(...arguments) super(...arguments)
this.state = { this.state = {
states: [] states: []
} }
} }
render(){ render(){
if(!formModule)formModule = webpackModules.find(e => e.FormSection) if(!formModule)formModule = webpackModules.find(e => e.FormSection)
/** /**
* @type {Function[]} * @type {Function[]}
*/ */
const allComponents = [...new Set(Object.keys(window.Lightcord.Api.Components).map(e => { const allComponents = [...new Set(Object.keys(window.Lightcord.Api.Components).map(e => {
return Object.keys(window.Lightcord.Api.Components[e]).map(k => window.Lightcord.Api.Components[e][k]) return Object.keys(window.Lightcord.Api.Components[e]).map(k => window.Lightcord.Api.Components[e][k])
}).flat())] }).flat())]
return [ return [
<formModule.FormSection tag="h2" title="Lightcord's Api Availlable components"> <formModule.FormSection tag="h2" title="Lightcord's Api Availlable components">
<formModule.FormText type="description" className="" selectable={false}> <formModule.FormText type="description" className="" selectable={false}>
These components are here for the plugin devs. They can quickly embed any component below with this panel. These components are here for the plugin devs. They can quickly embed any component below with this panel.
</formModule.FormText> </formModule.FormText>
<MarginTop></MarginTop> <MarginTop></MarginTop>
<Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => { <Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => {
remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/Apis") remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/Apis")
}} wrapper={false}> }} wrapper={false}>
Documentation Documentation
</Lightcord.Api.Components.inputs.Button> </Lightcord.Api.Components.inputs.Button>
</formModule.FormSection>, </formModule.FormSection>,
allComponents.map(comp => { allComponents.map(comp => {
let AllPreviews = [] let AllPreviews = []
if(comp.AllPreviews)AllPreviews = comp.AllPreviews if(comp.AllPreviews)AllPreviews = comp.AllPreviews
let onChange = (tab) => { let onChange = (tab) => {
setState({ setState({
tab tab
}) })
} }
let setState = (newState) => { let setState = (newState) => {
this.setState({ this.setState({
states: [Object.assign(state, newState)].concat(this.state.states.filter(e => e.elem !== comp)) states: [Object.assign(state, newState)].concat(this.state.states.filter(e => e.elem !== comp))
}) })
} }
let state = this.state.states.find(e => e.elem === comp) let state = this.state.states.find(e => e.elem === comp)
if(!state){ if(!state){
state = { state = {
tab: "preview", tab: "preview",
elem: comp, elem: comp,
options: {} options: {}
} }
this.state.states.push(state) this.state.states.push(state)
} }
let getProps = () => { let getProps = () => {
let final = {} let final = {}
AllPreviews.forEach(category => { AllPreviews.forEach(category => {
final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]] final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]
}) })
Object.keys(state.options).forEach(key => { Object.keys(state.options).forEach(key => {
final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key] final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]
}) })
return final return final
} }
let renderPreview = () => { let renderPreview = () => {
return <div style={{margin: "20px"}}> return <div style={{margin: "20px"}}>
<div style={{ <div style={{
backgroundColor: "var(--background-primary)", backgroundColor: "var(--background-primary)",
padding: "30px 30px", padding: "30px 30px",
borderRadius: "8px" borderRadius: "8px"
}} className="lc-tab-box-shadow"> }} className="lc-tab-box-shadow">
{React.createElement(comp, getProps())} {React.createElement(comp, getProps())}
</div> </div>
</div> </div>
} }
let renderCode = () => { let renderCode = () => {
return <div style={{margin: "20px"}}> return <div style={{margin: "20px"}}>
<div style={{ <div style={{
backgroundColor: "var(--background-primary)", backgroundColor: "var(--background-primary)",
padding: "30px 30px", padding: "30px 30px",
borderRadius: "8px" borderRadius: "8px"
}} className="lc-tab-box-shadow"> }} className="lc-tab-box-shadow">
<window.Lightcord.Api.Components.general.SettingSubTitle> <window.Lightcord.Api.Components.general.SettingSubTitle>
JSX JSX
</window.Lightcord.Api.Components.general.SettingSubTitle> </window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/> <window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/>
<window.Lightcord.Api.Components.general.SettingSubTitle> <window.Lightcord.Api.Components.general.SettingSubTitle>
React React
</window.Lightcord.Api.Components.general.SettingSubTitle> </window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/> <window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/>
</div> </div>
</div> </div>
} }
let getStrForProp = (value, compPath, lang) => { let getStrForProp = (value, compPath, lang) => {
if(typeof value === "string"){ if(typeof value === "string"){
return value return value
}else if(typeof value === "boolean"){ }else if(typeof value === "boolean"){
return String(value) return String(value)
}else if(typeof value === "function"){ }else if(typeof value === "function"){
return value.toString() return value.toString()
}else if(typeof value === "object"){ }else if(typeof value === "object"){
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){ if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
if(compPath === "Lightcord.Api.Components.general.Tabs"){ if(compPath === "Lightcord.Api.Components.general.Tabs"){
if(lang === "react"){ if(lang === "react"){
return `React.createElement("div", {style: { return `React.createElement("div", {style: {
marginTop: "20px", marginBottom: "20px" marginTop: "20px", marginBottom: "20px"
}}, }},
React.createElement("div", {style: { React.createElement("div", {style: {
backgroundColor: "var(--background-primary)", backgroundColor: "var(--background-primary)",
padding: "30px 30px", padding: "30px 30px",
borderRadius: "8px" borderRadius: "8px"
}, className: "lc-tab-box-shadow" }, }, className: "lc-tab-box-shadow" },
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs") React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
) )
)` )`
}else if(lang === "jsx"){ }else if(lang === "jsx"){
return `<div style={{ return `<div style={{
marginTop: "20px", marginBottom: "20px" marginTop: "20px", marginBottom: "20px"
}}> }}>
<div style={{ <div style={{
backgroundColor: "var(--background-primary)", backgroundColor: "var(--background-primary)",
padding: "30px 30px", padding: "30px 30px",
borderRadius: "8px" borderRadius: "8px"
}} className="lc-tab-box-shadow"> }} className="lc-tab-box-shadow">
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title> <Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
</div> </div>
</div>` </div>`
} }
} }
return "Your components here." return "Your components here."
} }
return JSON.stringify(value, null, " ") return JSON.stringify(value, null, " ")
}else if(typeof value === "number"){ }else if(typeof value === "number"){
return String(value) return String(value)
} }
return String(value) return String(value)
} }
let generateCode = function(lang){ // code formatting is hard let generateCode = function(lang){ // code formatting is hard
const compName = comp.displayName || comp.name const compName = comp.displayName || comp.name
let categories = Object.keys(window.Lightcord.Api.Components) let categories = Object.keys(window.Lightcord.Api.Components)
const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName]) const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])
const compPath = `Lightcord.Api.Components.${compCategory}.${compName}` const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`
const props = getProps() const props = getProps()
if(lang === "jsx"){ if(lang === "jsx"){
let propStrings = [] let propStrings = []
let childrenProp = null let childrenProp = null
Object.keys(props).forEach(key => { Object.keys(props).forEach(key => {
if(key == "children"){ if(key == "children"){
childrenProp = getStrForProp(props[key], compPath, lang) childrenProp = getStrForProp(props[key], compPath, lang)
}else{ }else{
let str = key+"=" let str = key+"="
if(typeof props[key] === "string"){ if(typeof props[key] === "string"){
str += JSON.stringify(props[key]) str += JSON.stringify(props[key])
}else{ }else{
str += `{${getStrForProp(props[key], compPath, lang)}}` str += `{${getStrForProp(props[key], compPath, lang)}}`
} }
propStrings.push(str) propStrings.push(str)
} }
}) })
let openTag let openTag
if(childrenProp){ if(childrenProp){
openTag = `<${compPath} ${propStrings.join(" ")}>` openTag = `<${compPath} ${propStrings.join(" ")}>`
let closeTag = `</${compPath}>` let closeTag = `</${compPath}>`
return `${openTag}\n ${childrenProp}\n${closeTag}` return `${openTag}\n ${childrenProp}\n${closeTag}`
}else{ }else{
openTag = `<${compPath} ${propStrings.join(" ")}/>` openTag = `<${compPath} ${propStrings.join(" ")}/>`
return openTag return openTag
} }
}else if(lang === "react"){ }else if(lang === "react"){
let children = props.children || null let children = props.children || null
delete props.children delete props.children
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){ if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
children = getStrForProp(children, compPath, lang) children = getStrForProp(children, compPath, lang)
} }
let propStrings = [] let propStrings = []
Object.keys(props).forEach(key => { Object.keys(props).forEach(key => {
let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key
let str = visibleKey+": " let str = visibleKey+": "
if(typeof props[key] === "string"){ if(typeof props[key] === "string"){
str += JSON.stringify(props[key]) str += JSON.stringify(props[key])
}else{ }else{
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => { str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
if(i === 0)return str if(i === 0)return str
return " " + str return " " + str
}).join("\n") }).join("\n")
} }
propStrings.push(str) propStrings.push(str)
}) })
let propObject = "{" let propObject = "{"
if(propStrings.length){ if(propStrings.length){
propStrings.forEach((str, i) => { propStrings.forEach((str, i) => {
let isLast = i === propStrings.length - 1 let isLast = i === propStrings.length - 1
let isFirst = i === 0 let isFirst = i === 0
if(!isFirst){ if(!isFirst){
propObject += "," propObject += ","
} }
propObject += "\n " propObject += "\n "
propObject += str propObject += str
if(isLast){ if(isLast){
propObject +="\n}" propObject +="\n}"
} }
}) })
}else{ }else{
propObject += "}" propObject += "}"
} }
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children) let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
return `React.createElement(${compPath}, ${propObject}, ${childrenData})` return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
} }
} }
return (<div> let help = comp.help || {}
<window.Lightcord.Api.Components.general.SettingsTitle> let info = help.info ? <window.Lightcord.Api.Components.general.AlertBox type="info">
{comp.displayName || comp.name} {help.info}
</window.Lightcord.Api.Components.general.SettingsTitle> </window.Lightcord.Api.Components.general.AlertBox> : null
{AllPreviews.map(category => { let warn = help.warn ? <window.Lightcord.Api.Components.general.AlertBox type="warn">
if(category[0].onClick)return null {help.warn}
if(category[0].text)return null </window.Lightcord.Api.Components.general.AlertBox> : null
if(category[0].children)return null let danger = help.danger ? <window.Lightcord.Api.Components.general.AlertBox type="danger">
if(category.length === 1)return null {help.danger}
</window.Lightcord.Api.Components.general.AlertBox> : null
let key = Object.keys(category[0])[0] let error = help.error ? <window.Lightcord.Api.Components.general.AlertBox type="error">
return [ {help.error}
<window.Lightcord.Api.Components.general.SettingSubTitle> </window.Lightcord.Api.Components.general.AlertBox> : null
{key} let success = help.success ? <window.Lightcord.Api.Components.general.AlertBox type="success">
</window.Lightcord.Api.Components.general.SettingSubTitle>, {help.success}
<window.Lightcord.Api.Components.inputs.Dropdown options={category.map((e, index) => { </window.Lightcord.Api.Components.general.AlertBox> : null
return { return (<div>
value: "opt-"+index, <window.Lightcord.Api.Components.general.SettingsTitle>
label: JSON.stringify(e[Object.keys(e)[0]]) {comp.displayName || comp.name}
} </window.Lightcord.Api.Components.general.SettingsTitle>
})} value={"opt-"+(state.options[key] || "0")} onChange={(value) => { {info}
setState({ {success}
options: Object.assign({}, state.options, { {warn}
[key]: (value.value || "0").replace("opt-", "") {error}
}) {danger}
}) {AllPreviews.map(category => {
}} searchable={true}/>, if(category[0].onClick)return null
<div style={{marginBottom: "8px"}}></div> if(category[0].text)return null
] if(category[0].children)return null
})} if(category.length === 1)return null
<window.Lightcord.Api.Components.general.Tabs tabs={[{label: "Preview", id: "preview"}, {label: "Code", id: "code"}]}
active={state.tab} children={state.tab === "preview" ? renderPreview() : renderCode()} onChange={onChange}/> let key = Object.keys(category[0])[0]
</div>) return [
}) <window.Lightcord.Api.Components.general.SettingSubTitle>
] {key}
} </window.Lightcord.Api.Components.general.SettingSubTitle>,
<window.Lightcord.Api.Components.inputs.Dropdown options={category.map((e, index) => {
get renders(){ return {
value: "opt-"+index,
} label: JSON.stringify(e[Object.keys(e)[0]])
}
})} value={"opt-"+(state.options[key] || "0")} onChange={(value) => {
setState({
options: Object.assign({}, state.options, {
[key]: (value.value || "0").replace("opt-", "")
})
})
}} searchable={true}/>,
<div style={{marginBottom: "8px"}}></div>
]
})}
<window.Lightcord.Api.Components.general.Tabs tabs={[{label: "Preview", id: "preview"}, {label: "Code", id: "code"}]}
active={state.tab} children={state.tab === "preview" ? renderPreview() : renderCode()} onChange={onChange}/>
</div>)
})
]
}
get renders(){
}
} }

File diff suppressed because one or more lines are too long

View File

@ -1,33 +1,37 @@
import DiscordButton from "./inputs/Button" import DiscordButton from "./inputs/Button"
import Switch from "./inputs/Switch" import Switch from "./inputs/Switch"
import RadioGroup from "./inputs/RadioGroup" import RadioGroup from "./inputs/RadioGroup"
import TextArea from "./inputs/TextArea" import TextArea from "./inputs/TextArea"
import TextInput from "./inputs/TextInput" import TextInput from "./inputs/TextInput"
import Dropdown from "./inputs/Dropdown" import Dropdown from "./inputs/Dropdown"
import Title from "./general/Title" import Title from "./general/Title"
import SettingsTitle from "./general/SettingsTitle" import SettingsTitle from "./general/SettingsTitle"
import Tabs, { Tab } from "./general/Tabs" import Tabs, { Tab } from "./general/Tabs"
import SettingSubTitle from "./general/SettingSubTitle" import SettingSubTitle from "./general/SettingSubTitle"
import CodeBlock from "./general/CodeBlock" import CodeBlock from "./general/CodeBlock"
import cloneNullProto from "../modules/cloneNullProto" import cloneNullProto from "../modules/cloneNullProto"
import Tooltip from "./general/Tooltip" import Tooltip from "./general/Tooltip"
import ColorPicker from "./inputs/ColorPicker"
export default cloneNullProto({ import AlertBox from "./general/AlertBox"
inputs: cloneNullProto({
Button: DiscordButton, export default cloneNullProto({
Switch: Switch, inputs: cloneNullProto({
Choices: RadioGroup, Button: DiscordButton,
RadioGroup: RadioGroup, Switch: Switch,
TextArea: TextArea, Choices: RadioGroup,
TextInput: TextInput, RadioGroup: RadioGroup,
Dropdown: Dropdown TextArea: TextArea,
}), TextInput: TextInput,
general: cloneNullProto({ Dropdown: Dropdown,
Title: Title, ColorPicker: ColorPicker
SettingsTitle: SettingsTitle, }),
SettingSubTitle: SettingSubTitle, general: cloneNullProto({
Tabs: Tabs, Title: Title,
CodeBlock: CodeBlock, SettingsTitle: SettingsTitle,
Tooltip: Tooltip SettingSubTitle: SettingSubTitle,
}) Tabs: Tabs,
CodeBlock: CodeBlock,
Tooltip: Tooltip,
AlertBox: AlertBox
})
}) })

View File

@ -0,0 +1,84 @@
import WebpackLoader from "../../modules/WebpackLoader"
import { ReactNode } from "react"
type AlertBoxProps = {
type: "warn"|"info"|"danger"|"error"|"success",
children: ReactNode|string
}
let AlertBoxModules
export default class AlertBox extends React.Component<AlertBoxProps> {
static defaultProps:AlertBoxProps = {
type: "info",
children: null
}
get modules(){
return AlertBoxModules || (AlertBoxModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "Markdown" && e.default.defaultProps.parser).default
])
}
render(){
const [
Markdown
] = this.modules
let wrap
let children
if(typeof this.props.children === "string"){
wrap = Markdown.prototype.render.call({
props: Object.assign({
className: "",
children: this.props.children
}, Markdown.defaultProps)
})
children = wrap.props.children
}else{
wrap = Markdown.prototype.render.call({
props: Object.assign({
className: "",
children: ""
}, Markdown.defaultProps)
})
children = this.props.children
}
wrap.props.children = <div className={"lc-alert-box lc-alert-box-"+this.props.type}>
<blockquote style={{color: "#dcddde"}} className="lc-blockquote">
{children}
</blockquote>
</div>
return wrap
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([
{
children: "***Discord's*** **Markdown** _is_ [supported](https://google.com) or you can just insert your own react childs."
}
], [
{
type: "warn"
},
{
type: "info"
},
{
type: "error"
},
{
type: "success"
}
])
return AllPreviews
})()
}
static help = {
info: "You can insert markdown (as string) or normal react childs",
warn: "All string will be interpreted as markdown. If you want raw string, pass an array with the string inside."
}
}
let AllPreviews

View File

@ -1,67 +1,71 @@
import WebpackLoader from "../../modules/WebpackLoader" /**
* TODO: Add margin component
type CodeBlockProps = { */
language?: string,
content: string import WebpackLoader from "../../modules/WebpackLoader"
}
type CodeBlockProps = {
let CodeBlockModules language?: string,
export default class CodeBlock extends React.Component<CodeBlockProps> { content: string
static defaultProps:CodeBlockProps = { }
language: "plaintext",
content: "" let CodeBlockModules
} export default class CodeBlock extends React.Component<CodeBlockProps> {
static defaultProps:CodeBlockProps = {
get modules(){ language: "plaintext",
return CodeBlockModules || (CodeBlockModules = [ content: ""
WebpackLoader.find(e => e.markup), }
WebpackLoader.find(e => e.messageContent),
WebpackLoader.find(e => e.scrollbarGhostHairline), get modules(){
WebpackLoader.find(e => e.highlight), return CodeBlockModules || (CodeBlockModules = [
WebpackLoader.find(e => e.marginBottom8) WebpackLoader.find(e => e.markup),
]) WebpackLoader.find(e => e.messageContent),
} WebpackLoader.find(e => e.scrollbarGhostHairline),
WebpackLoader.find(e => e.highlight),
render(){ WebpackLoader.find(e => e.marginBottom8)
let [ ])
messageModule1, }
messageModule2,
scrollbarModule1, render(){
hightlightJS, let [
marginModule1 messageModule1,
] = this.modules messageModule2,
scrollbarModule1,
const code = this.props.language === "plaintext" ? <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}> hightlightJS,
{this.props.content} marginModule1
</code> : <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`} ] = this.modules
dangerouslySetInnerHTML={{__html: hightlightJS.highlight(this.props.language, this.props.content).value}} />
return (<div className={`${messageModule1.markup} ${messageModule2.messageContent}`}> const code = this.props.language === "plaintext" ? <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}>
<pre> {this.props.content}
{code} </code> : <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}
</pre> dangerouslySetInnerHTML={{__html: hightlightJS.highlight(this.props.language, this.props.content).value}} />
<div className={marginModule1.marginBottom8}></div> return (<div className={`${messageModule1.markup} ${messageModule2.messageContent}`}>
</div>) <pre>
} {code}
</pre>
static get AllPreviews(){ <div className={marginModule1.marginBottom8}></div>
return AllPreviews || (() => { </div>)
AllPreviews = [] }
AllPreviews.push([
{ static get AllPreviews(){
content: "console.log(\"Exemple code\")" return AllPreviews || (() => {
} AllPreviews = []
]) AllPreviews.push([
AllPreviews.push([ {
{ content: "console.log(\"Exemple code\")"
language: "js" }
}, ])
{ AllPreviews.push([
language: "plaintext" {
}, language: "js"
...CodeBlock.prototype.modules[3].listLanguages().filter(e => e !== "js").map(e => ({language: e})) },
]) {
return AllPreviews language: "plaintext"
})() },
} ...CodeBlock.prototype.modules[3].listLanguages().filter(e => e !== "js").map(e => ({language: e}))
} ])
return AllPreviews
})()
}
}
let AllPreviews let AllPreviews

View File

@ -0,0 +1,132 @@
/**
* Replacement for color picker if original is not availlable
*
* - Don't work at the moment. Please use the other.
*/
import NOOP from "../../modules/noop"
import WebpackLoader from "../../modules/WebpackLoader"
import Tooltip from "../general/Tooltip"
type ColorPickerProps = {
inline?: boolean,
popout?: true
tooltip?: string|false,
defaultColor?: boolean,
customColor?: boolean,
baseColors?: boolean
} | {
inline?: boolean,
popout?: false,
tooltip?: false,
defaultColor?: boolean,
customColor?: boolean,
baseColors?: boolean
}
let ColorPickerModules
export default class ColorPicker extends React.Component<ColorPickerProps> {
constructor(props:ColorPickerProps){
super(props)
}
static defaultProps:ColorPickerProps = {
inline: false,
popout: false,
tooltip: false,
defaultColor: true,
customColor: true,
baseColors: true
}
get modules(){
return ColorPickerModules || (ColorPickerModules = [
{
colorPickerCustom: "lc-colorPickerCustom",
customColorPickerInput: "lc-customColorPickerInput",
input: "lc-colorPicker-input",
colorPickerRow: "lc-colorPickerRow",
colorPickerSwatch: "lc-colorPickerSwatch",
custom: "lc-colorPicker-custom",
default: "lc-colorPicker-default",
disabled: "lc-colorPicker-disabled",
colorPickerDropper: "lc-colorPickerDropper",
noColor: "lc-colorPicker-noColor",
colorPickerDropperFg: "lc-colorPickerDropperFg"
},
WebpackLoader.find(e => e.flexMarginReset),
WebpackLoader.find(e => e.justifyStart && !e.streamerModeEnabled),
WebpackLoader.find(e => e.marginTop60 && !e.title),
WebpackLoader.findByUniqueProperties(["Messages"]).default.Messages
])
}
renderColorPicker(){
let [
colorPickerClasses,
flexClasses,
positionClasses,
marginClasses,
TranslationModule
] = this.modules
let defaultColor = this.props.defaultColor ? <div className={marginClasses.marginReset}>
<Tooltip text={TranslationModule.DEFAULT} position="bottom" color="black">
<button type="button" className={`${colorPickerClasses.colorPickerSwatch} ${colorPickerClasses.default}`} style={{
marginLeft: "0px",
backgroundColor: Constants.defaultColor
}} onClick={this.setColor.bind(this, Constants.defaultColor)}>
<svg aria-hidden="false" width="32" height="24" viewBox="0 0 24 24">
<path fill="#ffffff" fill-rule="evenodd" clip-rule="evenodd" d="M8.99991 16.17L4.82991 12L3.40991 13.41L8.99991 19L20.9999 7.00003L19.5899 5.59003L8.99991 16.17Z"></path>
</svg>
</button>
</Tooltip>
</div> : null
let customColor = this.props.customColor ? <div className={marginClasses.marginReset}>
<Tooltip text={TranslationModule.CUSTOM_COLOR} position="bottom" color="black">
<button type="button" className={`${colorPickerClasses.colorPickerSwatch} ${colorPickerClasses.default}`} style={{
marginLeft: "0px",
backgroundColor: Constants.defaultColor
}} onClick={this.setColor.bind(this, Constants.defaultColor)}>
<svg aria-hidden="false" width="32" height="24" viewBox="0 0 24 24">
<path fill="#ffffff" fill-rule="evenodd" clip-rule="evenodd" d="M8.99991 16.17L4.82991 12L3.40991 13.41L8.99991 19L20.9999 7.00003L19.5899 5.59003L8.99991 16.17Z"></path>
</svg>
</button>
</Tooltip>
</div> : null
return <div className={`${flexClasses.flex} ${flexClasses._horizontal} ${positionClasses.justifyStart} ${positionClasses.alignStretch} ${positionClasses.noWrap}`}>
{defaultColor}
{customColor}
</div>
}
renderPopout(){
}
setColor(color){
console.log(color)
}
render(){
let props = this.props
let returnValue = null
if(props.popout){
returnValue = this.renderPopout()
}else{
returnValue = this.renderColorPicker()
}
return returnValue
}
static get AllPreviews(){
return []
}
}
let AllPreviews
const Constants = {
defaultColor: "#99aab5"
}

View File

@ -0,0 +1,166 @@
import NOOP from "../../modules/noop"
import WebpackLoader from "../../modules/WebpackLoader"
import Tooltip from "../general/Tooltip"
import Utils from "../../modules/Utils"
const Constants = {
defaultColor: 10070709,
baseColors: [
1752220,
3066993,
3447003,
10181046,
15277667,
15844367,
15105570,
15158332,
9807270,
6323595,
1146986,
2067276,
2123412,
7419530,
11342935,
12745742,
11027200,
10038562,
9936031,
5533306
]
}
type ColorPickerProps = {
defaultColor?: number,
customColor?: number,
baseColors?: number[],
value?: string,
disabled?: boolean,
onChange?: (color:number) => void
}
let ColorPickerModules
let isFetching = null
export default class ColorPicker extends React.PureComponent<ColorPickerProps, {value?:string,lastColor:any}> {
constructor(props:ColorPickerProps){
super(props)
this.state = {
value: props.value || null,
lastColor: this.props.value
}
this.onChange = this.onChange.bind(this)
}
onChange(val){
this.props.onChange(val)
this.setState({
value: val
})
this.forceUpdate()
}
static defaultProps:ColorPickerProps = {
defaultColor: Constants.defaultColor,
customColor: null,
baseColors: Constants.baseColors,
value: null,
disabled: false,
onChange: NOOP
}
get modules(){
return ColorPickerModules || (ColorPickerModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "ColorPicker")
])
}
renderColorPicker(){
let [
ColorPickerComponent
] = this.modules
if(!ColorPickerComponent){
if(isFetching)isFetching.then(e => this.forceUpdate()) // support for multiple color picker
ColorPickerModules = null
let resolve
isFetching = new Promise(res => (resolve = res))
const GuildSettingsRoles = new (WebpackLoader.find(e => e.default && e.default.displayName && e.default.displayName.includes("GuildSettingsRoles")).default)().render().type
const settings = GuildSettingsRoles.prototype.renderRoleSettings.call({
props: {
guild: {
roles: [],
id: null,
isOwner: () => false
},
currentUser: {
id: null
}
},
getSelectedRole(){
return {
id: null
}
}
})
const GuildRoleSettings = settings.props.children.type
let children = GuildRoleSettings.prototype.renderColorPicker.call({
props: {
role: {
id: null,
color: 0
},
locked: false,
everyone: false
}
}).props.children
children.type(children.props).props.children.type._ctor().then(c => {
this.forceUpdate()
resolve()
})
return null
}
return <ColorPickerComponent.default colors={this.props.baseColors} defaultColor={this.props.defaultColor} value={this.state.value}
disabled={this.props.disabled} onChange={this.onChange} customColor={this.props.customColor}>
</ColorPickerComponent.default>
}
render(){
if(this.state.lastColor !== this.props.value){
this.state = {
value: this.props.value,
lastColor: this.props.value
}
}
return this.renderColorPicker()
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([
{
disabled: false
},
{
disabled: true
}
], [
{
value: Utils.HexColorToDecimal("#7289DA")
}, {
value: null
}
], [
{
onChange: (color) => {}
}
])
return AllPreviews
})()
}
static help = {
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`"
}
}
let AllPreviews

View File

@ -1,148 +1,146 @@
import NOOP from "../../modules/noop" import NOOP from "../../modules/noop"
import WebpackLoader from "../../modules/WebpackLoader" import WebpackLoader from "../../modules/WebpackLoader"
import { ReactNode, CSSProperties } from "react" import { ReactNode, CSSProperties } from "react"
import Utils from "../../modules/Utils"
import unfreeze from "../../modules/Unfreeze" type DropdownProps = {
className?: string,
type DropdownProps = { error?: string,
className?: string, options?: {
error?: string, value: string,
options?: { label: string
value: string, }[],
label: string valueRenderer?: (data) => ReactNode,
}[], optionRenderer?: (data) => ReactNode,
valueRenderer?: (data) => ReactNode, multiValueRenderer?: (data) => ReactNode
optionRenderer?: (data) => ReactNode, onChange?: (value: string) => void,
multiValueRenderer?: (data) => ReactNode value?: string,
onChange?: (value: string) => void, disabled?: boolean,
value?: string, searchable?: boolean,
disabled?: boolean, clearable?: boolean,
searchable?: boolean, styleOverrides?: CSSProperties,
clearable?: boolean, lightThemeColorOverrides?: themeOverride,
styleOverrides?: CSSProperties, darkThemeColorOverrides?: themeOverride,
lightThemeColorOverrides?: themeOverride, isMulti?: boolean
darkThemeColorOverrides?: themeOverride, }
isMulti?: boolean
} type themeOverride = {
neutral0: string,
type themeOverride = { neutral5: string,
neutral0: string, neutral10: string,
neutral5: string, neutral20: string,
neutral10: string, neutral30: string,
neutral20: string, primary: string,
neutral30: string, primary25: string,
primary: string, primary50: string,
primary25: string, selectedOptionBackground: string,
primary50: string, text: string,
selectedOptionBackground: string, menuBackground: string,
text: string, menuBorder: string,
menuBackground: string, scrollBarThumb: string,
menuBorder: string, multiOptionBackground: string
scrollBarThumb: string, }
multiOptionBackground: string
} let DropdownModules
export default class Dropdown extends React.Component<DropdownProps, {value: string|null}> {
let DropdownModules constructor(props:DropdownProps){
export default class Dropdown extends React.Component<DropdownProps, {value: string|null}> { super(props)
constructor(props:DropdownProps){ this.onChange = this.onChange.bind(this)
super(props) this.state = {
this.onChange = this.onChange.bind(this) value: props.value || null
this.state = { }
value: props.value || null }
}
} static defaultProps:DropdownProps = {
className: null,
static defaultProps:DropdownProps = { error: null,
className: null, options: [{
error: null, value: "none",
options: [{ "label": "No options - No options was passed to Dropdown. If you meant to put an empty dropdown, input an empty array."
value: "none", }],
"label": "No options - No options was passed to Dropdown. If you meant to put an empty dropdown, input an empty array." valueRenderer: null,
}], multiValueRenderer: null,
valueRenderer: null, optionRenderer: null,
multiValueRenderer: null, onChange: NOOP,
optionRenderer: null, value: null,
onChange: NOOP, disabled: false,
value: null, searchable: false,
disabled: false, clearable: false,
searchable: false, styleOverrides: null,
clearable: false, lightThemeColorOverrides: null,
styleOverrides: null, darkThemeColorOverrides: null,
lightThemeColorOverrides: null, isMulti: false
darkThemeColorOverrides: null, }
isMulti: false
} onChange(value){
this.props.onChange(value)
onChange(value){ this.setState({
this.props.onChange(value) value: value
this.setState({ })
value: value }
})
} get modules(){
return DropdownModules || (DropdownModules = [
get modules(){ WebpackLoader.find(e => e.default && e.default.displayName === "SelectTempWrapper").default
return DropdownModules || (DropdownModules = [ ])
WebpackLoader.find(e => e.default && e.default.displayName === "SelectTempWrapper").default }
])
} render(){
let [
render(){ DropdownComponent
let [ ] = this.modules
DropdownComponent
] = this.modules let props = this.props
let returnValue = <DropdownComponent {...props} onChange={this.onChange} value={this.state.value}/>
let props = this.props return returnValue
let returnValue = <DropdownComponent {...props} onChange={this.onChange} value={this.state.value}/> }
return returnValue
} get value(){
return this.state.value
get value(){ }
return this.state.value
} static get AllPreviews(){
return AllPreviews || (() => {
static get AllPreviews(){ AllPreviews = []
return AllPreviews || (() => { AllPreviews.push([{
AllPreviews = [] error: null
AllPreviews.push([{ }, {
error: null error: "An error occured"
}, { }], [{
error: "An error occured" options: [
}], [{ {
options: [ value: "option1",
{ label: "Option 1"
value: "option1", },
label: "Option 1" {
}, value: "option2",
{ label: "Option 2"
value: "option2", },
label: "Option 2" {
}, value: "option3",
{ label: "Option 3"
value: "option3", }
label: "Option 3" ]
} }], [{
] value: "option1"
}], [{ }], [{
value: "option1" disabled: false
}], [{ }, {
disabled: false disabled: true
}, { }], [{
disabled: true searchable: true
}], [{ }, {
searchable: true searchable: false
}, { }], [{
searchable: false clearable: true
}], [{ }, {
clearable: true clearable: false
}, { }], [{
clearable: false isMulti: false
}], [{ }, {
isMulti: false isMulti: true
}, { }])
isMulti: true return AllPreviews
}]) })()
return AllPreviews }
})() }
}
}
let AllPreviews let AllPreviews

View File

@ -1,98 +1,102 @@
import WebpackLoader from "../../modules/WebpackLoader" import WebpackLoader from "../../modules/WebpackLoader"
import uuid from "../../modules/uuid" import uuid from "../../modules/uuid"
import NOOP from "../../modules/noop" import NOOP from "../../modules/noop"
import Utils from "../../modules/Utils" import Utils from "../../modules/Utils"
type SwitchProps = { type SwitchProps = {
id?: string, id?: string,
onChange?: (checked: boolean) => void, onChange?: (checked: boolean) => void,
value?: boolean, value?: boolean,
fill?: string, fill?: string,
theme?: "default"|"clear", theme?: "default"|"clear",
disabled?: boolean, disabled?: boolean,
className?: string, className?: string,
size?: "default"|"mini", size?: "default"|"mini",
style?: React.CSSProperties style?: React.CSSProperties
} }
let SwitchModules let SwitchModules
export default class Switch extends React.Component<SwitchProps, {value: boolean}> { export default class Switch extends React.Component<SwitchProps, {value: boolean}> {
constructor(props:SwitchProps){ constructor(props:SwitchProps){
super(props) super(props)
this.state = { this.state = {
value: props.value || false value: props.value || false
} }
this.onChange = this.onChange.bind(this) this.onChange = this.onChange.bind(this)
} }
get modules(){ get modules(){
return SwitchModules || (SwitchModules = [ return SwitchModules || (SwitchModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "Switch").default WebpackLoader.find(e => e.default && e.default.displayName === "Switch").default
]) ])
} }
render(){ render(){
let [ let [
SwitchComponent SwitchComponent
] = this.modules ] = this.modules
let props = this.props let props = this.props
return (<SwitchComponent id={props.id} onChange={this.onChange} value={this.state.value || false} fill={props.fill} return (<SwitchComponent id={props.id} onChange={this.onChange} value={this.state.value || false} fill={props.fill}
theme={SwitchComponent.Themes[props.theme.toUpperCase()]} disabled={props.disabled} className={props.className} theme={SwitchComponent.Themes[props.theme.toUpperCase()]} disabled={props.disabled} className={props.className}
size={SwitchComponent.Sizes[props.size.toUpperCase()]} style={props.style}/>) size={SwitchComponent.Sizes[props.size.toUpperCase()]} style={props.style}/>)
} }
onChange(value){ onChange(value){
this.props.onChange(!this.state.value) this.props.onChange(!this.state.value)
this.setState({ this.setState({
value: !this.state.value value: !this.state.value
}) })
} }
get value(){ get value(){
return this.state.value return this.state.value
} }
static defaultProps = { static defaultProps = {
id: null, id: null,
onChange: NOOP, onChange: NOOP,
value: false, value: false,
fill: null, fill: null,
theme: "default", theme: "default",
disabled: false, disabled: false,
className: null, className: null,
size: "default", size: "default",
style: {} style: {}
} }
static get AllPreviews(){ static get AllPreviews(){
return AllPreviews || (() => { return AllPreviews || (() => {
AllPreviews = [] AllPreviews = []
AllPreviews.push([{onChange: (value) => {}}]) AllPreviews.push([{onChange: (value) => {}}])
AllPreviews.push([{ AllPreviews.push([{
value: false value: false
}], [{ }], [{
theme: "default" theme: "default"
}, { }, {
theme: "clear" theme: "clear"
}], [{ }], [{
disabled: false disabled: false
}, { }, {
disabled: true disabled: true
}], [{ }], [{
id: "api-preview-switch" id: "api-preview-switch"
}], [{ }], [{
fill: null fill: null
}], [{ }], [{
size: "default" size: "default"
}, { }, {
size: "mini" size: "mini"
}], [{ }], [{
style: {} style: {}
}]) }])
return AllPreviews return AllPreviews
})() })()
} }
}
static help = {
error: "The `clear` option doesn't work well on light theme."
}
}
let AllPreviews let AllPreviews

View File

@ -1,163 +1,167 @@
import WebpackLoader from "../../modules/WebpackLoader" import WebpackLoader from "../../modules/WebpackLoader"
import NOOP from "../../modules/noop" import NOOP from "../../modules/noop"
import Utils from "../../modules/Utils" import Utils from "../../modules/Utils"
type TextAreaProps = { type TextAreaProps = {
name?: string, name?: string,
disabled?: boolean, disabled?: boolean,
placeholder?: string, placeholder?: string,
autoFocus?: boolean, autoFocus?: boolean,
resizeable?: boolean, resizeable?: boolean,
flex?: boolean, flex?: boolean,
autosize?: false, autosize?: false,
rows?: number, rows?: number,
value?: string, value?: string,
error?: string, error?: string,
maxLength?: number, maxLength?: number,
className?: string, className?: string,
id?: string, id?: string,
onChange?: (value: string, name: string) => void, onChange?: (value: string, name: string) => void,
onFocus?: (ev, name: string) => void, onFocus?: (ev, name: string) => void,
onBlur?: (ev, name: string) => void, onBlur?: (ev, name: string) => void,
onKeyDown?: (ev) => void onKeyDown?: (ev) => void
} }
let TextAreaModules let TextAreaModules
export default class TextArea extends React.Component<TextAreaProps, {value: string}> { export default class TextArea extends React.Component<TextAreaProps, {value: string}> {
constructor(props:TextAreaProps){ constructor(props:TextAreaProps){
super(props) super(props)
this.onChange = this.onChange.bind(this) this.onChange = this.onChange.bind(this)
this.onFocus = this.onFocus.bind(this) this.onFocus = this.onFocus.bind(this)
this.onBlur = this.onBlur.bind(this) this.onBlur = this.onBlur.bind(this)
this.onKeyDown = this.onKeyDown.bind(this) this.onKeyDown = this.onKeyDown.bind(this)
this.state = { this.state = {
value: props.value || "" value: props.value || ""
} }
} }
get modules(){ get modules(){
return TextAreaModules || (TextAreaModules = [ return TextAreaModules || (TextAreaModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "TextArea").default WebpackLoader.find(e => e.default && e.default.displayName === "TextArea").default
]) ])
} }
onChange(value, name){ onChange(value, name){
this.props.onChange(value, name) this.props.onChange(value, name)
this.setState({ this.setState({
value value
}) })
} }
onFocus(ev, name){ onFocus(ev, name){
this.props.onFocus(ev, name) this.props.onFocus(ev, name)
} }
onBlur(ev, name){ onBlur(ev, name){
this.props.onBlur(ev, name) this.props.onBlur(ev, name)
} }
onKeyDown(ev){ onKeyDown(ev){
this.props.onKeyDown(ev) this.props.onKeyDown(ev)
} }
render(){ render(){
let [ let [
TextAreaComponent TextAreaComponent
] = this.modules ] = this.modules
let props = this.props let props = this.props
return <TextAreaComponent {...props} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.onKeyDown} value={this.state.value}/> return <TextAreaComponent {...props} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.onKeyDown} value={this.state.value}/>
} }
get value(){ get value(){
return this.state.value || "" return this.state.value || ""
} }
static defaultProps:TextAreaProps = { static defaultProps:TextAreaProps = {
name: null, name: null,
disabled: false, disabled: false,
placeholder: null, placeholder: null,
autoFocus: false, autoFocus: false,
resizeable: false, resizeable: false,
flex: false, flex: false,
autosize: false, autosize: false,
rows: 3, rows: 3,
value: "", value: "",
error: null, error: null,
maxLength: null, maxLength: null,
className: null, className: null,
id: null, id: null,
onChange: NOOP, onChange: NOOP,
onFocus: NOOP, onFocus: NOOP,
onBlur: NOOP, onBlur: NOOP,
onKeyDown: NOOP onKeyDown: NOOP
} }
static get AllPreviews(){ static get AllPreviews(){
return AllPreviews || (() => { return AllPreviews || (() => {
AllPreviews = [] AllPreviews = []
AllPreviews.push([{ AllPreviews.push([{
name: "api-preview-textarea" name: "api-preview-textarea"
}]) }])
AllPreviews.push([{ AllPreviews.push([{
disabled: false disabled: false
}, { }, {
disabled: true disabled: true
}]) }])
AllPreviews.push([{ AllPreviews.push([{
placeholder: null placeholder: null
}]) }])
AllPreviews.push([{ AllPreviews.push([{
autoFocus: false autoFocus: false
}, { }, {
autoFocus: true autoFocus: true
}]) }])
AllPreviews.push([{ AllPreviews.push([{
resizeable: false resizeable: false
}, { }, {
resizeable: true resizeable: true
}]) }])
AllPreviews.push([{ AllPreviews.push([{
flex: false flex: false
}, { }, {
flex: true flex: true
}]) }])
AllPreviews.push([{ AllPreviews.push([{
autosize: false autosize: false
}, { }, {
autosize: true autosize: true
}]) }])
AllPreviews.push([{ AllPreviews.push([{
rows: 3 rows: 3
}, { }, {
rows: 2 rows: 2
}, { }, {
rows: 1 rows: 1
}]) }])
AllPreviews.push([{ AllPreviews.push([{
value: "" value: ""
}]) }])
AllPreviews.push([{ AllPreviews.push([{
error: null error: null
}, { }, {
error: "Example error" error: "Example error"
}]) }])
AllPreviews.push([{ AllPreviews.push([{
maxLength: 100 maxLength: 100
}]) }])
AllPreviews.push([{ AllPreviews.push([{
className: "" className: ""
}]) }])
AllPreviews.push([{ AllPreviews.push([{
inputClassName: "" inputClassName: ""
}]) }])
AllPreviews.push([{ AllPreviews.push([{
id: "api-preview-textarea" id: "api-preview-textarea"
}]) }])
return AllPreviews return AllPreviews
})() })()
} }
}
static help = {
warn: "This should be used for multi line inputs."
}
}
let AllPreviews let AllPreviews

View File

@ -1,133 +1,137 @@
import WebpackLoader from "../../modules/WebpackLoader" import WebpackLoader from "../../modules/WebpackLoader"
import NOOP from "../../modules/noop" import NOOP from "../../modules/noop"
import Utils from "../../modules/Utils" import Utils from "../../modules/Utils"
type TextInputProps = { type TextInputProps = {
name?: string, name?: string,
size?: "default"|"mini" size?: "default"|"mini"
disabled?: boolean, disabled?: boolean,
placeholder?: string, placeholder?: string,
value?: string, value?: string,
error?: string, error?: string,
maxLength?: number, maxLength?: number,
className?: string, className?: string,
inputClassName?: string inputClassName?: string
id?: string, id?: string,
onChange?: (value: string, name: string, input: TextInput) => void, onChange?: (value: string, name: string, input: TextInput) => void,
onFocus?: (ev, name: string, input: TextInput) => void, onFocus?: (ev, name: string, input: TextInput) => void,
onBlur?: (ev, name: string, input: TextInput) => void onBlur?: (ev, name: string, input: TextInput) => void
} }
let TextInputModules let TextInputModules
export default class TextInput extends React.PureComponent<TextInputProps, {value: string}> { export default class TextInput extends React.PureComponent<TextInputProps, {value: string}> {
hasSet: boolean hasSet: boolean
constructor(props: TextInputProps){ constructor(props: TextInputProps){
super(props) super(props)
this.onChange = this.onChange.bind(this) this.onChange = this.onChange.bind(this)
this.onFocus = this.onFocus.bind(this) this.onFocus = this.onFocus.bind(this)
this.onBlur = this.onBlur.bind(this) this.onBlur = this.onBlur.bind(this)
this.state = { this.state = {
value: props.value || "" value: props.value || ""
} }
} }
static defaultProps:TextInputProps = { static defaultProps:TextInputProps = {
name: "", name: "",
size: "default", size: "default",
disabled: false, disabled: false,
placeholder: "", placeholder: "",
value: "", value: "",
error: null, error: null,
maxLength: 999, maxLength: 999,
className: "", className: "",
inputClassName: "", inputClassName: "",
id: null, id: null,
onChange: NOOP, onChange: NOOP,
onFocus: NOOP, onFocus: NOOP,
onBlur: NOOP onBlur: NOOP
} }
get modules(){ get modules(){
return TextInputModules || (TextInputModules = [ return TextInputModules || (TextInputModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "TextInput").default WebpackLoader.find(e => e.default && e.default.displayName === "TextInput").default
]) ])
} }
onChange(value, name){ onChange(value, name){
this.hasSet = false this.hasSet = false
this.props.onChange(value, name, this) this.props.onChange(value, name, this)
if(this.hasSet)return // prevent event if the onChange has changed the value. if(this.hasSet)return // prevent event if the onChange has changed the value.
this.setState({ this.setState({
value value
}) })
this.forceUpdate() this.forceUpdate()
} }
onFocus(ev, name){ onFocus(ev, name){
this.props.onFocus(ev, name, this) this.props.onFocus(ev, name, this)
} }
onBlur(ev, name){ onBlur(ev, name){
this.props.onBlur(ev, name, this) this.props.onBlur(ev, name, this)
} }
render(){ render(){
let [ let [
TextAreaComponent TextAreaComponent
] = this.modules ] = this.modules
let props = this.props let props = this.props
return <TextAreaComponent {...props} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} value={this.state.value} /> return <TextAreaComponent {...props} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} value={this.state.value} />
} }
get value(){ get value(){
return this.state.value || "" return this.state.value || ""
} }
setValue(value:string){ setValue(value:string){
this.setState({ this.setState({
value: value value: value
}) })
this.forceUpdate() this.forceUpdate()
this.hasSet = true this.hasSet = true
} }
static get AllPreviews(){ static get AllPreviews(){
return AllPreviews || (() => { return AllPreviews || (() => {
AllPreviews = [] AllPreviews = []
AllPreviews.push([{ AllPreviews.push([{
name: "api-preview-textinput" name: "api-preview-textinput"
}], [{ }], [{
size: "default" size: "default"
}, { }, {
size: "mini" size: "mini"
}], [{ }], [{
disabled: false disabled: false
}, { }, {
disabled: true disabled: true
}], [{ }], [{
placeholder: "" placeholder: ""
}], [{ }], [{
value: "" value: ""
}], [{ }], [{
error: null error: null
}, { }, {
error: "Example error" error: "Example error"
}], [{ }], [{
maxLength: 999 maxLength: 999
}], [{ }], [{
className: "" className: ""
}], [{ }], [{
inputClassName: "" inputClassName: ""
}], [{ }], [{
id: "api-preview-textinput" id: "api-preview-textinput"
}], [{ }], [{
onChange: (value: string, name: string) => {} onChange: (value: string, name: string) => {}
}]) }])
return AllPreviews return AllPreviews
})() })()
} }
}
static help = {
warn: "This should be used for single line inputs."
}
}
let AllPreviews let AllPreviews

View File

@ -1,23 +1,34 @@
import { ReactElement } from "react"; import { ReactElement } from "react";
import ReactDOM = require("react-dom") import ReactDOM = require("react-dom")
import PluginUtilities from "./PluginUtilities"; import PluginUtilities from "./PluginUtilities";
export default new class Utils { export default new class Utils {
constructor(){} constructor(){}
ReactToHTMLElement(ReactElement: ReactElement){ ReactToHTMLElement(ReactElement: ReactElement){
const element = document.createElement("div") const element = document.createElement("div")
ReactDOM.render(ReactElement, element) ReactDOM.render(ReactElement, element)
return element return element
} }
get PluginUtils(){return PluginUtilities} get PluginUtils(){return PluginUtilities}
getNestedProps(obj:any, path: string){ getNestedProps(obj:any, path: string){
let segments = path.split(".") let segments = path.split(".")
for(let seg of segments){ for(let seg of segments){
obj = obj && (seg in obj) ? obj[seg] : undefined obj = obj && (seg in obj) ? obj[seg] : undefined
} }
return obj return obj
} }
DecimalColorToHex(color:number):string{
return "#"+color.toString(16)
}
HexColorToDecimal(color:string):number{
color = color.replace(/[#;]/g, "")
let res = parseInt(color, 16)
if(isNaN(res))throw new Error(`Invalid color: ${color}`)
return res
}
} }

View File

@ -1,45 +1,49 @@
const BDModules = window.BDModules const BDModules = window.BDModules
export default new class WebpackLoader { export default new class WebpackLoader {
constructor(){} constructor(){}
get(id: number):any{ get(id: number):any{
return BDModules.get(id) return BDModules.get(id)
} }
find(filter: (mod:any) => boolean):any{ find(filter: (mod:any) => boolean):any{
return BDModules.get(filter)[0] let result = BDModules.get(filter)[0]
} if(!result){
findByUniqueProperties(props:(string|number)[]):any{ console.warn(filter, "couldn't find the module.")
return BDModules.get((mod) => { }
if(mod.__esModule && ("default" in mod)){ return result
let doesMatch = true }
for(let prop of props){ findByUniqueProperties(props:(string|number)[]):any{
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false return BDModules.get((mod) => {
} if(mod.__esModule && ("default" in mod)){
if(doesMatch)return true let doesMatch = true
} for(let prop of props){
for(let prop of props){ if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false }
} if(doesMatch)return true
return true }
})[0] for(let prop of props){
} if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
filter(filter: (mod:any) => boolean):any[]{ }
return BDModules.get(filter) return true
} })[0]
filterByUniqueProperties(props:(string|number)[]):any{ }
return BDModules.get((mod) => { filter(filter: (mod:any) => boolean):any[]{
if(mod.__esModule && ("default" in mod)){ return BDModules.get(filter)
let doesMatch = true }
for(let prop of props){ filterByUniqueProperties(props:(string|number)[]):any{
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false return BDModules.get((mod) => {
} if(mod.__esModule && ("default" in mod)){
if(doesMatch)return true let doesMatch = true
} for(let prop of props){
for(let prop of props){ if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false }
} if(doesMatch)return true
return true }
}) for(let prop of props){
} if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
}
return true
})
}
} }

View File

@ -1,145 +1,187 @@
/** Lightcord Custom */ /** Lightcord Custom */
.lc-tabWrapper { .lc-tabWrapper {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
background: var(--background-floating); background: var(--background-floating);
border: 1px solid var(--deprecated-text-input-border-hover); border: 1px solid var(--deprecated-text-input-border-hover);
border-radius: 5px; border-radius: 5px;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-box-direction: normal; -webkit-box-direction: normal;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
} }
.lc-tabnav { .lc-tabnav {
top: 0; top: 0;
border-bottom: 1px solid var(--deprecated-text-input-border-hover); border-bottom: 1px solid var(--deprecated-text-input-border-hover);
padding: 0 4px; padding: 0 4px;
width: 100%; width: 100%;
-ms-flex-item-align: start; -ms-flex-item-align: start;
align-self: flex-start; align-self: flex-start;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
-webkit-box-pack: start; -webkit-box-pack: start;
-ms-flex-pack: start; -ms-flex-pack: start;
justify-content: flex-start; justify-content: flex-start;
-webkit-box-align: stretch; -webkit-box-align: stretch;
-ms-flex-align: stretch; -ms-flex-align: stretch;
align-items: stretch; align-items: stretch;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
-webkit-box-orient: horizontal; -webkit-box-orient: horizontal;
-webkit-box-direction: normal; -webkit-box-direction: normal;
-ms-flex-direction: row; -ms-flex-direction: row;
flex-direction: row; flex-direction: row;
} }
.lc-tab { .lc-tab {
/*border-radius: 8px;*/ /*border-radius: 8px;*/
overflow: hidden; overflow: hidden;
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
-ms-flex-wrap: wrap; -ms-flex-wrap: wrap;
flex-wrap: wrap; flex-wrap: wrap;
-webkit-box-pack: start; -webkit-box-pack: start;
-ms-flex-pack: start; -ms-flex-pack: start;
justify-content: flex-start; justify-content: flex-start;
-webkit-box-align: stretch; -webkit-box-align: stretch;
-ms-flex-align: stretch; -ms-flex-align: stretch;
align-items: stretch; align-items: stretch;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-box-direction: normal; -webkit-box-direction: normal;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
padding: 40px; padding: 40px;
} }
.theme-dark .lc-tab-box-shadow { .theme-dark .lc-tab-box-shadow {
-webkit-box-shadow: 0 0 20px 2px rgba(4,4,5,.3); -webkit-box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
box-shadow: 0 0 20px 2px rgba(4,4,5,.3); box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
} }
.theme-light .lc-tab-box-shadow { .theme-light .lc-tab-box-shadow {
-webkit-box-shadow: 0 0 5px 2px rgba(4,4,5,.1); -webkit-box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
box-shadow: 0 0 5px 2px rgba(4,4,5,.1); box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
} }
.lc-navItem { .lc-navItem {
padding: 14px 20px; padding: 14px 20px;
position: relative; position: relative;
font-weight: 500; font-weight: 500;
-webkit-transform: color .125s; -webkit-transform: color .125s;
transform: color .125s; transform: color .125s;
cursor: pointer; cursor: pointer;
max-height: 100%; max-height: 100%;
} }
.lc-navItem::after { .lc-navItem::after {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 20px; left: 20px;
right: 20px; right: 20px;
background: #7289da; background: #7289da;
-webkit-box-shadow: 0 -4px 12px 0 #7289da; -webkit-box-shadow: 0 -4px 12px 0 #7289da;
box-shadow: 0 -4px 12px 0 #7289da; box-shadow: 0 -4px 12px 0 #7289da;
content: ""; content: "";
height: 2px; height: 2px;
-webkit-transition: -webkit-transform .125s; -webkit-transition: -webkit-transform .125s;
transition: -webkit-transform .125s; transition: -webkit-transform .125s;
transition: transform .125s; transition: transform .125s;
transition: transform .125s,-webkit-transform .125s; transition: transform .125s,-webkit-transform .125s;
} }
.lc-navItemActive { .lc-navItemActive {
color: var(--interactive-active); color: var(--interactive-active);
} }
.lc-navItemActive::after { .lc-navItemActive::after {
-webkit-transform: none; -webkit-transform: none;
transform: none; transform: none;
} }
.lc-navItemInactive { .lc-navItemInactive {
color: var(--interactive-normal); color: var(--interactive-normal);
} }
.lc-navItemInactive:hover { .lc-navItemInactive:hover {
color: var(--interactive-hover) color: var(--interactive-hover)
} }
.lc-navItemInactive::after { .lc-navItemInactive::after {
-webkit-transform: translateY(16px); -webkit-transform: translateY(16px);
transform: translateY(16px); transform: translateY(16px);
} }
.lc-fadeOverlay { .lc-fadeOverlay {
height: 20%; height: 20%;
left: 0; left: 0;
bottom: 0; bottom: 0;
background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(24,25,28,0)),color-stop(70%,#18191c),to(#18191c)); background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(24,25,28,0)),color-stop(70%,#18191c),to(#18191c));
background-image: linear-gradient(180deg,rgba(24,25,28,0),#18191c 70%,#18191c); background-image: linear-gradient(180deg,rgba(24,25,28,0),#18191c 70%,#18191c);
z-index: 900; z-index: 900;
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
.lc-userPopout { .lc-userPopout {
width: 250px; width: 250px;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
-webkit-box-shadow: 0 0 20px 2px rgba(4,4,5,.3); -webkit-box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
box-shadow: 0 0 20px 2px rgba(4,4,5,.3); box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
-webkit-box-flex: 1; -webkit-box-flex: 1;
-ms-flex-positive: 1; -ms-flex-positive: 1;
flex-grow: 1; flex-grow: 1;
margin: 40px auto; margin: 40px auto;
} }
.lc-link-disabled-span:hover { .lc-link-disabled-span:hover {
cursor: pointer; cursor: pointer;
}
/** Alert Box */
.lc-alert-box {
margin: 20px 0;
padding: 10px;
border-radius: 5px;
font-size: 14px;
font-weight: 300;
line-height: 22px;
}
.lc-alert-box strong {
font-weight: 900
}
.lc-alert-box span {
color: hsla(0,0%,100%,.9);
margin: 0!important
}
.lc-alert-box.lc-alert-box-warn {
background: rgba(250,166,26,.1);
border: 2px solid rgba(250,166,26,.5);
}
.lc-alert-box.lc-alert-box-info {
background: rgba(114,137,218,.1);
border: 2px solid rgba(114,137,218,.5);
}
.lc-alert-box.lc-alert-box-danger {
background: rgba(240,71,71,.1);
border: 2px solid rgba(240,71,71,.5);
}
.lc-alert-box.lc-alert-box-error {
background: rgba(240,71,71,.1);
border: 2px solid rgba(240,71,71,.5);
}
.lc-alert-box.lc-alert-box-success {
background: rgba(67,181,129,.1);
border: 2px solid rgba(67,181,129,.5)
}
.lc-blockquote > div {
margin-bottom: 0!important;
} }