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.
import { stat } from "fs"
import { uuidv4 } from "../modules/distant"
import webpackModules from "../modules/webpackModules"
import { remote } from "electron"
import MarginTop from "./margintop"
const keys = {
settingTitle: uuidv4()
}
let formModule
export default class ApiPreview extends React.PureComponent {
constructor(){
super(...arguments)
this.state = {
states: []
}
}
render(){
if(!formModule)formModule = webpackModules.find(e => e.FormSection)
/**
* @type {Function[]}
*/
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])
}).flat())]
return [
<formModule.FormSection tag="h2" title="Lightcord's Api Availlable components">
<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.
</formModule.FormText>
<MarginTop></MarginTop>
<Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => {
remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/Apis")
}} wrapper={false}>
Documentation
</Lightcord.Api.Components.inputs.Button>
</formModule.FormSection>,
allComponents.map(comp => {
let AllPreviews = []
if(comp.AllPreviews)AllPreviews = comp.AllPreviews
let onChange = (tab) => {
setState({
tab
})
}
let setState = (newState) => {
this.setState({
states: [Object.assign(state, newState)].concat(this.state.states.filter(e => e.elem !== comp))
})
}
let state = this.state.states.find(e => e.elem === comp)
if(!state){
state = {
tab: "preview",
elem: comp,
options: {}
}
this.state.states.push(state)
}
let getProps = () => {
let final = {}
AllPreviews.forEach(category => {
final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]
})
Object.keys(state.options).forEach(key => {
final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]
})
return final
}
let renderPreview = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
{React.createElement(comp, getProps())}
</div>
</div>
}
let renderCode = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<window.Lightcord.Api.Components.general.SettingSubTitle>
JSX
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/>
<window.Lightcord.Api.Components.general.SettingSubTitle>
React
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/>
</div>
</div>
}
let getStrForProp = (value, compPath, lang) => {
if(typeof value === "string"){
return value
}else if(typeof value === "boolean"){
return String(value)
}else if(typeof value === "function"){
return value.toString()
}else if(typeof value === "object"){
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
if(compPath === "Lightcord.Api.Components.general.Tabs"){
if(lang === "react"){
return `React.createElement("div", {style: {
marginTop: "20px", marginBottom: "20px"
}},
React.createElement("div", {style: {
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}, className: "lc-tab-box-shadow" },
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
)
)`
}else if(lang === "jsx"){
return `<div style={{
marginTop: "20px", marginBottom: "20px"
}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
</div>
</div>`
}
}
return "Your components here."
}
return JSON.stringify(value, null, " ")
}else if(typeof value === "number"){
return String(value)
}
return String(value)
}
let generateCode = function(lang){ // code formatting is hard
const compName = comp.displayName || comp.name
let categories = Object.keys(window.Lightcord.Api.Components)
const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])
const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`
const props = getProps()
if(lang === "jsx"){
let propStrings = []
let childrenProp = null
Object.keys(props).forEach(key => {
if(key == "children"){
childrenProp = getStrForProp(props[key], compPath, lang)
}else{
let str = key+"="
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += `{${getStrForProp(props[key], compPath, lang)}}`
}
propStrings.push(str)
}
})
let openTag
if(childrenProp){
openTag = `<${compPath} ${propStrings.join(" ")}>`
let closeTag = `</${compPath}>`
return `${openTag}\n ${childrenProp}\n${closeTag}`
}else{
openTag = `<${compPath} ${propStrings.join(" ")}/>`
return openTag
}
}else if(lang === "react"){
let children = props.children || null
delete props.children
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
children = getStrForProp(children, compPath, lang)
}
let propStrings = []
Object.keys(props).forEach(key => {
let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key
let str = visibleKey+": "
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
if(i === 0)return str
return " " + str
}).join("\n")
}
propStrings.push(str)
})
let propObject = "{"
if(propStrings.length){
propStrings.forEach((str, i) => {
let isLast = i === propStrings.length - 1
let isFirst = i === 0
if(!isFirst){
propObject += ","
}
propObject += "\n "
propObject += str
if(isLast){
propObject +="\n}"
}
})
}else{
propObject += "}"
}
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
}
}
return (<div>
<window.Lightcord.Api.Components.general.SettingsTitle>
{comp.displayName || comp.name}
</window.Lightcord.Api.Components.general.SettingsTitle>
{AllPreviews.map(category => {
if(category[0].onClick)return null
if(category[0].text)return null
if(category[0].children)return null
if(category.length === 1)return null
let key = Object.keys(category[0])[0]
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) => {
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(){
}
// Good luck to read my code, Even me can't read it properly.
import { stat } from "fs"
import { uuidv4 } from "../modules/distant"
import webpackModules from "../modules/webpackModules"
import { remote } from "electron"
import MarginTop from "./margintop"
const keys = {
settingTitle: uuidv4()
}
let formModule
export default class ApiPreview extends React.PureComponent {
constructor(){
super(...arguments)
this.state = {
states: []
}
}
render(){
if(!formModule)formModule = webpackModules.find(e => e.FormSection)
/**
* @type {Function[]}
*/
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])
}).flat())]
return [
<formModule.FormSection tag="h2" title="Lightcord's Api Availlable components">
<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.
</formModule.FormText>
<MarginTop></MarginTop>
<Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => {
remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/Apis")
}} wrapper={false}>
Documentation
</Lightcord.Api.Components.inputs.Button>
</formModule.FormSection>,
allComponents.map(comp => {
let AllPreviews = []
if(comp.AllPreviews)AllPreviews = comp.AllPreviews
let onChange = (tab) => {
setState({
tab
})
}
let setState = (newState) => {
this.setState({
states: [Object.assign(state, newState)].concat(this.state.states.filter(e => e.elem !== comp))
})
}
let state = this.state.states.find(e => e.elem === comp)
if(!state){
state = {
tab: "preview",
elem: comp,
options: {}
}
this.state.states.push(state)
}
let getProps = () => {
let final = {}
AllPreviews.forEach(category => {
final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]
})
Object.keys(state.options).forEach(key => {
final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]
})
return final
}
let renderPreview = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
{React.createElement(comp, getProps())}
</div>
</div>
}
let renderCode = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<window.Lightcord.Api.Components.general.SettingSubTitle>
JSX
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/>
<window.Lightcord.Api.Components.general.SettingSubTitle>
React
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/>
</div>
</div>
}
let getStrForProp = (value, compPath, lang) => {
if(typeof value === "string"){
return value
}else if(typeof value === "boolean"){
return String(value)
}else if(typeof value === "function"){
return value.toString()
}else if(typeof value === "object"){
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
if(compPath === "Lightcord.Api.Components.general.Tabs"){
if(lang === "react"){
return `React.createElement("div", {style: {
marginTop: "20px", marginBottom: "20px"
}},
React.createElement("div", {style: {
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}, className: "lc-tab-box-shadow" },
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
)
)`
}else if(lang === "jsx"){
return `<div style={{
marginTop: "20px", marginBottom: "20px"
}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
</div>
</div>`
}
}
return "Your components here."
}
return JSON.stringify(value, null, " ")
}else if(typeof value === "number"){
return String(value)
}
return String(value)
}
let generateCode = function(lang){ // code formatting is hard
const compName = comp.displayName || comp.name
let categories = Object.keys(window.Lightcord.Api.Components)
const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])
const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`
const props = getProps()
if(lang === "jsx"){
let propStrings = []
let childrenProp = null
Object.keys(props).forEach(key => {
if(key == "children"){
childrenProp = getStrForProp(props[key], compPath, lang)
}else{
let str = key+"="
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += `{${getStrForProp(props[key], compPath, lang)}}`
}
propStrings.push(str)
}
})
let openTag
if(childrenProp){
openTag = `<${compPath} ${propStrings.join(" ")}>`
let closeTag = `</${compPath}>`
return `${openTag}\n ${childrenProp}\n${closeTag}`
}else{
openTag = `<${compPath} ${propStrings.join(" ")}/>`
return openTag
}
}else if(lang === "react"){
let children = props.children || null
delete props.children
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
children = getStrForProp(children, compPath, lang)
}
let propStrings = []
Object.keys(props).forEach(key => {
let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key
let str = visibleKey+": "
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
if(i === 0)return str
return " " + str
}).join("\n")
}
propStrings.push(str)
})
let propObject = "{"
if(propStrings.length){
propStrings.forEach((str, i) => {
let isLast = i === propStrings.length - 1
let isFirst = i === 0
if(!isFirst){
propObject += ","
}
propObject += "\n "
propObject += str
if(isLast){
propObject +="\n}"
}
})
}else{
propObject += "}"
}
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
}
}
let help = comp.help || {}
let info = help.info ? <window.Lightcord.Api.Components.general.AlertBox type="info">
{help.info}
</window.Lightcord.Api.Components.general.AlertBox> : null
let warn = help.warn ? <window.Lightcord.Api.Components.general.AlertBox type="warn">
{help.warn}
</window.Lightcord.Api.Components.general.AlertBox> : null
let danger = help.danger ? <window.Lightcord.Api.Components.general.AlertBox type="danger">
{help.danger}
</window.Lightcord.Api.Components.general.AlertBox> : null
let error = help.error ? <window.Lightcord.Api.Components.general.AlertBox type="error">
{help.error}
</window.Lightcord.Api.Components.general.AlertBox> : null
let success = help.success ? <window.Lightcord.Api.Components.general.AlertBox type="success">
{help.success}
</window.Lightcord.Api.Components.general.AlertBox> : null
return (<div>
<window.Lightcord.Api.Components.general.SettingsTitle>
{comp.displayName || comp.name}
</window.Lightcord.Api.Components.general.SettingsTitle>
{info}
{success}
{warn}
{error}
{danger}
{AllPreviews.map(category => {
if(category[0].onClick)return null
if(category[0].text)return null
if(category[0].children)return null
if(category.length === 1)return null
let key = Object.keys(category[0])[0]
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) => {
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 Switch from "./inputs/Switch"
import RadioGroup from "./inputs/RadioGroup"
import TextArea from "./inputs/TextArea"
import TextInput from "./inputs/TextInput"
import Dropdown from "./inputs/Dropdown"
import Title from "./general/Title"
import SettingsTitle from "./general/SettingsTitle"
import Tabs, { Tab } from "./general/Tabs"
import SettingSubTitle from "./general/SettingSubTitle"
import CodeBlock from "./general/CodeBlock"
import cloneNullProto from "../modules/cloneNullProto"
import Tooltip from "./general/Tooltip"
export default cloneNullProto({
inputs: cloneNullProto({
Button: DiscordButton,
Switch: Switch,
Choices: RadioGroup,
RadioGroup: RadioGroup,
TextArea: TextArea,
TextInput: TextInput,
Dropdown: Dropdown
}),
general: cloneNullProto({
Title: Title,
SettingsTitle: SettingsTitle,
SettingSubTitle: SettingSubTitle,
Tabs: Tabs,
CodeBlock: CodeBlock,
Tooltip: Tooltip
})
import DiscordButton from "./inputs/Button"
import Switch from "./inputs/Switch"
import RadioGroup from "./inputs/RadioGroup"
import TextArea from "./inputs/TextArea"
import TextInput from "./inputs/TextInput"
import Dropdown from "./inputs/Dropdown"
import Title from "./general/Title"
import SettingsTitle from "./general/SettingsTitle"
import Tabs, { Tab } from "./general/Tabs"
import SettingSubTitle from "./general/SettingSubTitle"
import CodeBlock from "./general/CodeBlock"
import cloneNullProto from "../modules/cloneNullProto"
import Tooltip from "./general/Tooltip"
import ColorPicker from "./inputs/ColorPicker"
import AlertBox from "./general/AlertBox"
export default cloneNullProto({
inputs: cloneNullProto({
Button: DiscordButton,
Switch: Switch,
Choices: RadioGroup,
RadioGroup: RadioGroup,
TextArea: TextArea,
TextInput: TextInput,
Dropdown: Dropdown,
ColorPicker: ColorPicker
}),
general: cloneNullProto({
Title: Title,
SettingsTitle: SettingsTitle,
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"
type CodeBlockProps = {
language?: string,
content: string
}
let CodeBlockModules
export default class CodeBlock extends React.Component<CodeBlockProps> {
static defaultProps:CodeBlockProps = {
language: "plaintext",
content: ""
}
get modules(){
return CodeBlockModules || (CodeBlockModules = [
WebpackLoader.find(e => e.markup),
WebpackLoader.find(e => e.messageContent),
WebpackLoader.find(e => e.scrollbarGhostHairline),
WebpackLoader.find(e => e.highlight),
WebpackLoader.find(e => e.marginBottom8)
])
}
render(){
let [
messageModule1,
messageModule2,
scrollbarModule1,
hightlightJS,
marginModule1
] = this.modules
const code = this.props.language === "plaintext" ? <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}>
{this.props.content}
</code> : <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}
dangerouslySetInnerHTML={{__html: hightlightJS.highlight(this.props.language, this.props.content).value}} />
return (<div className={`${messageModule1.markup} ${messageModule2.messageContent}`}>
<pre>
{code}
</pre>
<div className={marginModule1.marginBottom8}></div>
</div>)
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([
{
content: "console.log(\"Exemple code\")"
}
])
AllPreviews.push([
{
language: "js"
},
{
language: "plaintext"
},
...CodeBlock.prototype.modules[3].listLanguages().filter(e => e !== "js").map(e => ({language: e}))
])
return AllPreviews
})()
}
}
/**
* TODO: Add margin component
*/
import WebpackLoader from "../../modules/WebpackLoader"
type CodeBlockProps = {
language?: string,
content: string
}
let CodeBlockModules
export default class CodeBlock extends React.Component<CodeBlockProps> {
static defaultProps:CodeBlockProps = {
language: "plaintext",
content: ""
}
get modules(){
return CodeBlockModules || (CodeBlockModules = [
WebpackLoader.find(e => e.markup),
WebpackLoader.find(e => e.messageContent),
WebpackLoader.find(e => e.scrollbarGhostHairline),
WebpackLoader.find(e => e.highlight),
WebpackLoader.find(e => e.marginBottom8)
])
}
render(){
let [
messageModule1,
messageModule2,
scrollbarModule1,
hightlightJS,
marginModule1
] = this.modules
const code = this.props.language === "plaintext" ? <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}>
{this.props.content}
</code> : <code className={`${scrollbarModule1.scrollbarGhostHairline} hljs`}
dangerouslySetInnerHTML={{__html: hightlightJS.highlight(this.props.language, this.props.content).value}} />
return (<div className={`${messageModule1.markup} ${messageModule2.messageContent}`}>
<pre>
{code}
</pre>
<div className={marginModule1.marginBottom8}></div>
</div>)
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([
{
content: "console.log(\"Exemple code\")"
}
])
AllPreviews.push([
{
language: "js"
},
{
language: "plaintext"
},
...CodeBlock.prototype.modules[3].listLanguages().filter(e => e !== "js").map(e => ({language: e}))
])
return 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 WebpackLoader from "../../modules/WebpackLoader"
import { ReactNode, CSSProperties } from "react"
import Utils from "../../modules/Utils"
import unfreeze from "../../modules/Unfreeze"
type DropdownProps = {
className?: string,
error?: string,
options?: {
value: string,
label: string
}[],
valueRenderer?: (data) => ReactNode,
optionRenderer?: (data) => ReactNode,
multiValueRenderer?: (data) => ReactNode
onChange?: (value: string) => void,
value?: string,
disabled?: boolean,
searchable?: boolean,
clearable?: boolean,
styleOverrides?: CSSProperties,
lightThemeColorOverrides?: themeOverride,
darkThemeColorOverrides?: themeOverride,
isMulti?: boolean
}
type themeOverride = {
neutral0: string,
neutral5: string,
neutral10: string,
neutral20: string,
neutral30: string,
primary: string,
primary25: string,
primary50: string,
selectedOptionBackground: string,
text: string,
menuBackground: string,
menuBorder: string,
scrollBarThumb: string,
multiOptionBackground: string
}
let DropdownModules
export default class Dropdown extends React.Component<DropdownProps, {value: string|null}> {
constructor(props:DropdownProps){
super(props)
this.onChange = this.onChange.bind(this)
this.state = {
value: props.value || null
}
}
static defaultProps:DropdownProps = {
className: null,
error: null,
options: [{
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,
optionRenderer: null,
onChange: NOOP,
value: null,
disabled: false,
searchable: false,
clearable: false,
styleOverrides: null,
lightThemeColorOverrides: null,
darkThemeColorOverrides: null,
isMulti: false
}
onChange(value){
this.props.onChange(value)
this.setState({
value: value
})
}
get modules(){
return DropdownModules || (DropdownModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "SelectTempWrapper").default
])
}
render(){
let [
DropdownComponent
] = this.modules
let props = this.props
let returnValue = <DropdownComponent {...props} onChange={this.onChange} value={this.state.value}/>
return returnValue
}
get value(){
return this.state.value
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([{
error: null
}, {
error: "An error occured"
}], [{
options: [
{
value: "option1",
label: "Option 1"
},
{
value: "option2",
label: "Option 2"
},
{
value: "option3",
label: "Option 3"
}
]
}], [{
value: "option1"
}], [{
disabled: false
}, {
disabled: true
}], [{
searchable: true
}, {
searchable: false
}], [{
clearable: true
}, {
clearable: false
}], [{
isMulti: false
}, {
isMulti: true
}])
return AllPreviews
})()
}
}
import NOOP from "../../modules/noop"
import WebpackLoader from "../../modules/WebpackLoader"
import { ReactNode, CSSProperties } from "react"
type DropdownProps = {
className?: string,
error?: string,
options?: {
value: string,
label: string
}[],
valueRenderer?: (data) => ReactNode,
optionRenderer?: (data) => ReactNode,
multiValueRenderer?: (data) => ReactNode
onChange?: (value: string) => void,
value?: string,
disabled?: boolean,
searchable?: boolean,
clearable?: boolean,
styleOverrides?: CSSProperties,
lightThemeColorOverrides?: themeOverride,
darkThemeColorOverrides?: themeOverride,
isMulti?: boolean
}
type themeOverride = {
neutral0: string,
neutral5: string,
neutral10: string,
neutral20: string,
neutral30: string,
primary: string,
primary25: string,
primary50: string,
selectedOptionBackground: string,
text: string,
menuBackground: string,
menuBorder: string,
scrollBarThumb: string,
multiOptionBackground: string
}
let DropdownModules
export default class Dropdown extends React.Component<DropdownProps, {value: string|null}> {
constructor(props:DropdownProps){
super(props)
this.onChange = this.onChange.bind(this)
this.state = {
value: props.value || null
}
}
static defaultProps:DropdownProps = {
className: null,
error: null,
options: [{
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,
optionRenderer: null,
onChange: NOOP,
value: null,
disabled: false,
searchable: false,
clearable: false,
styleOverrides: null,
lightThemeColorOverrides: null,
darkThemeColorOverrides: null,
isMulti: false
}
onChange(value){
this.props.onChange(value)
this.setState({
value: value
})
}
get modules(){
return DropdownModules || (DropdownModules = [
WebpackLoader.find(e => e.default && e.default.displayName === "SelectTempWrapper").default
])
}
render(){
let [
DropdownComponent
] = this.modules
let props = this.props
let returnValue = <DropdownComponent {...props} onChange={this.onChange} value={this.state.value}/>
return returnValue
}
get value(){
return this.state.value
}
static get AllPreviews(){
return AllPreviews || (() => {
AllPreviews = []
AllPreviews.push([{
error: null
}, {
error: "An error occured"
}], [{
options: [
{
value: "option1",
label: "Option 1"
},
{
value: "option2",
label: "Option 2"
},
{
value: "option3",
label: "Option 3"
}
]
}], [{
value: "option1"
}], [{
disabled: false
}, {
disabled: true
}], [{
searchable: true
}, {
searchable: false
}], [{
clearable: true
}, {
clearable: false
}], [{
isMulti: false
}, {
isMulti: true
}])
return AllPreviews
})()
}
}
let AllPreviews

View File

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

View File

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

View File

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

View File

@ -1,23 +1,34 @@
import { ReactElement } from "react";
import ReactDOM = require("react-dom")
import PluginUtilities from "./PluginUtilities";
export default new class Utils {
constructor(){}
ReactToHTMLElement(ReactElement: ReactElement){
const element = document.createElement("div")
ReactDOM.render(ReactElement, element)
return element
}
get PluginUtils(){return PluginUtilities}
getNestedProps(obj:any, path: string){
let segments = path.split(".")
for(let seg of segments){
obj = obj && (seg in obj) ? obj[seg] : undefined
}
return obj
}
import { ReactElement } from "react";
import ReactDOM = require("react-dom")
import PluginUtilities from "./PluginUtilities";
export default new class Utils {
constructor(){}
ReactToHTMLElement(ReactElement: ReactElement){
const element = document.createElement("div")
ReactDOM.render(ReactElement, element)
return element
}
get PluginUtils(){return PluginUtilities}
getNestedProps(obj:any, path: string){
let segments = path.split(".")
for(let seg of segments){
obj = obj && (seg in obj) ? obj[seg] : undefined
}
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
export default new class WebpackLoader {
constructor(){}
get(id: number):any{
return BDModules.get(id)
}
find(filter: (mod:any) => boolean):any{
return BDModules.get(filter)[0]
}
findByUniqueProperties(props:(string|number)[]):any{
return BDModules.get((mod) => {
if(mod.__esModule && ("default" in mod)){
let doesMatch = true
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
}
if(doesMatch)return true
}
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
}
return true
})[0]
}
filter(filter: (mod:any) => boolean):any[]{
return BDModules.get(filter)
}
filterByUniqueProperties(props:(string|number)[]):any{
return BDModules.get((mod) => {
if(mod.__esModule && ("default" in mod)){
let doesMatch = true
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
}
if(doesMatch)return true
}
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
}
return true
})
}
const BDModules = window.BDModules
export default new class WebpackLoader {
constructor(){}
get(id: number):any{
return BDModules.get(id)
}
find(filter: (mod:any) => boolean):any{
let result = BDModules.get(filter)[0]
if(!result){
console.warn(filter, "couldn't find the module.")
}
return result
}
findByUniqueProperties(props:(string|number)[]):any{
return BDModules.get((mod) => {
if(mod.__esModule && ("default" in mod)){
let doesMatch = true
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
}
if(doesMatch)return true
}
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
}
return true
})[0]
}
filter(filter: (mod:any) => boolean):any[]{
return BDModules.get(filter)
}
filterByUniqueProperties(props:(string|number)[]):any{
return BDModules.get((mod) => {
if(mod.__esModule && ("default" in mod)){
let doesMatch = true
for(let prop of props){
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
}
if(doesMatch)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 */
.lc-tabWrapper {
position: relative;
overflow: hidden;
height: 100%;
background: var(--background-floating);
border: 1px solid var(--deprecated-text-input-border-hover);
border-radius: 5px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.lc-tabnav {
top: 0;
border-bottom: 1px solid var(--deprecated-text-input-border-hover);
padding: 0 4px;
width: 100%;
-ms-flex-item-align: start;
align-self: flex-start;
position: relative;
overflow: hidden;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
}
.lc-tab {
/*border-radius: 8px;*/
overflow: hidden;
position: relative;
margin: 0 auto;
width: 100%;
max-width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
padding: 40px;
}
.theme-dark .lc-tab-box-shadow {
-webkit-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 {
-webkit-box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
}
.lc-navItem {
padding: 14px 20px;
position: relative;
font-weight: 500;
-webkit-transform: color .125s;
transform: color .125s;
cursor: pointer;
max-height: 100%;
}
.lc-navItem::after {
position: absolute;
bottom: 0;
left: 20px;
right: 20px;
background: #7289da;
-webkit-box-shadow: 0 -4px 12px 0 #7289da;
box-shadow: 0 -4px 12px 0 #7289da;
content: "";
height: 2px;
-webkit-transition: -webkit-transform .125s;
transition: -webkit-transform .125s;
transition: transform .125s;
transition: transform .125s,-webkit-transform .125s;
}
.lc-navItemActive {
color: var(--interactive-active);
}
.lc-navItemActive::after {
-webkit-transform: none;
transform: none;
}
.lc-navItemInactive {
color: var(--interactive-normal);
}
.lc-navItemInactive:hover {
color: var(--interactive-hover)
}
.lc-navItemInactive::after {
-webkit-transform: translateY(16px);
transform: translateY(16px);
}
.lc-fadeOverlay {
height: 20%;
left: 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: linear-gradient(180deg,rgba(24,25,28,0),#18191c 70%,#18191c);
z-index: 900;
position: absolute;
width: 100%;
}
.lc-userPopout {
width: 250px;
border-radius: 5px;
overflow: hidden;
position: relative;
-webkit-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;
-ms-flex-positive: 1;
flex-grow: 1;
margin: 40px auto;
}
.lc-link-disabled-span:hover {
cursor: pointer;
/** Lightcord Custom */
.lc-tabWrapper {
position: relative;
overflow: hidden;
height: 100%;
background: var(--background-floating);
border: 1px solid var(--deprecated-text-input-border-hover);
border-radius: 5px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.lc-tabnav {
top: 0;
border-bottom: 1px solid var(--deprecated-text-input-border-hover);
padding: 0 4px;
width: 100%;
-ms-flex-item-align: start;
align-self: flex-start;
position: relative;
overflow: hidden;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
}
.lc-tab {
/*border-radius: 8px;*/
overflow: hidden;
position: relative;
margin: 0 auto;
width: 100%;
max-width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
padding: 40px;
}
.theme-dark .lc-tab-box-shadow {
-webkit-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 {
-webkit-box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
}
.lc-navItem {
padding: 14px 20px;
position: relative;
font-weight: 500;
-webkit-transform: color .125s;
transform: color .125s;
cursor: pointer;
max-height: 100%;
}
.lc-navItem::after {
position: absolute;
bottom: 0;
left: 20px;
right: 20px;
background: #7289da;
-webkit-box-shadow: 0 -4px 12px 0 #7289da;
box-shadow: 0 -4px 12px 0 #7289da;
content: "";
height: 2px;
-webkit-transition: -webkit-transform .125s;
transition: -webkit-transform .125s;
transition: transform .125s;
transition: transform .125s,-webkit-transform .125s;
}
.lc-navItemActive {
color: var(--interactive-active);
}
.lc-navItemActive::after {
-webkit-transform: none;
transform: none;
}
.lc-navItemInactive {
color: var(--interactive-normal);
}
.lc-navItemInactive:hover {
color: var(--interactive-hover)
}
.lc-navItemInactive::after {
-webkit-transform: translateY(16px);
transform: translateY(16px);
}
.lc-fadeOverlay {
height: 20%;
left: 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: linear-gradient(180deg,rgba(24,25,28,0),#18191c 70%,#18191c);
z-index: 900;
position: absolute;
width: 100%;
}
.lc-userPopout {
width: 250px;
border-radius: 5px;
overflow: hidden;
position: relative;
-webkit-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;
-ms-flex-positive: 1;
flex-grow: 1;
margin: 40px auto;
}
.lc-link-disabled-span:hover {
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;
}