fully functioning

This commit is contained in:
flowerbot 2022-06-30 10:16:32 +10:00
parent 980180189e
commit cf17587f77
9 changed files with 112 additions and 96 deletions

View File

@ -20,14 +20,14 @@
"group": { "default": "Other" }, "group": { "default": "Other" },
"title": { "default": "Palette Picker" }, "title": { "default": "Palette Picker" },
"description": { "default": "Palette Picker description" }, "description": { "default": "Palette Picker description" },
"officeFabricIconFontName": "Page", "officeFabricIconFontName": "Color",
"properties": { "properties": {
"description": "Palette Picker", "description": "Palette Picker",
"fontColor": "white", "fontColor": "white",
"fieldSetHue": [90,280], "fieldSetHue": [90,280],
"fieldSetSat": [45, 75], "fieldSetSat": [45, 75],
"fieldSetLight": [50, 75], "fieldSetLight": [50, 75],
"fieldSetShades": [5] "fieldSetShades": [8]
} }
}] }]
} }

View File

@ -16,8 +16,9 @@ import { PropertyPaneHost } from 'property-pane-portal';
import { update } from '@microsoft/sp-lodash-subset'; import { update } from '@microsoft/sp-lodash-subset';
export interface IPalettePickerWebPartProps { export interface IPalettePickerWebPartProps {
//cssObjectText: string; cssObjectText: string;
//colorObject: any; fontColor: string;
cssObject: any;
} }
@ -25,6 +26,8 @@ export interface IPalettePickerWebPartProps {
export default class PalettePickerWebPart extends BaseClientSideWebPart<IPalettePickerWebPartProps> { export default class PalettePickerWebPart extends BaseClientSideWebPart<IPalettePickerWebPartProps> {
public render(): void { public render(): void {
const mainElement: React.ReactElement<IPalettePickerProps> = React.createElement( const mainElement: React.ReactElement<IPalettePickerProps> = React.createElement(
PalettePicker, PalettePicker,
@ -34,7 +37,9 @@ export default class PalettePickerWebPart extends BaseClientSideWebPart<IPalette
const ppProps = { const ppProps = {
cssObjectText: this.properties["cssObjectText"], cssObjectText: this.properties["cssObjectText"],
context: this.context context: this.context,
cssObject: JSON.parse(this.properties["cssObjectText"]),
fontColor: this.properties.fontColor
} }
const customPropertyPaneProperties = { const customPropertyPaneProperties = {
@ -56,12 +61,13 @@ export default class PalettePickerWebPart extends BaseClientSideWebPart<IPalette
public updateWebPartProperty(property, value) { public updateWebPartProperty(property, value) {
// if(isObj != true) {
update(this.properties, property, () => value); update(this.properties, property, () => value);
// } else {
// update(this.properties, property, () => JSON.stringify(value)); if(property == "cssObject" && value != {}) {
// } // update(this.properties, "cssObjectText", () => ":root {" + Object.entries(value).map(([k, v]) => `${k}:${v}`).join('; ') + "}");
update(this.properties, "cssObjectText", () => JSON.stringify(value));
}
this.render(); this.render();
} }
@ -99,15 +105,7 @@ export default class PalettePickerWebPart extends BaseClientSideWebPart<IPalette
}), }),
PropertyPaneHost('fieldSetDisplay', hostProperties), PropertyPaneHost('fieldSetDisplay', hostProperties),
//TODO: get the text of the object here, or otherwise somehow send the object up the line for use in the web part PropertyPaneHost('cssObjectText', hostProperties),
PropertyPaneTextField('cssObjectText', {
label: "CSS Object",
disabled: false,
multiline: true,
resizable: true
}),
] ]
} }
] ]

View File

@ -3,7 +3,8 @@
.CustomPropertyPane { .CustomPropertyPane {
/* PrismJS 1.23.0 /* PrismJS 1.23.0
/* original inspiration used prism for formatting the css, these styles are mostly about that but unused in this solution
https://prismjs.com/download.html#themes=prism-tomorrow&languages=css+css-extras&plugins=line-numbers+inline-color+toolbar+copy-to-clipboard */ https://prismjs.com/download.html#themes=prism-tomorrow&languages=css+css-extras&plugins=line-numbers+inline-color+toolbar+copy-to-clipboard */
/** /**
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
@ -384,4 +385,5 @@ label {
height: 35px; height: 35px;
} }
} }

View File

@ -3,44 +3,23 @@ import { PropertyPanePortal } from 'property-pane-portal';
import { ICustomPropertyPaneProps } from './ICustomPropertyPaneProps'; import { ICustomPropertyPaneProps } from './ICustomPropertyPaneProps';
import styles from './CustomPropertyPane.module.scss'; import styles from './CustomPropertyPane.module.scss';
import { Range } from 'react-range'; import { Range } from 'react-range';
import { composeComponentAs } from 'office-ui-fabric-react'; import { composeComponentAs, TextField } from 'office-ui-fabric-react';
import { Colors } from './Colors'; import { Colors } from './Colors';
import { escape } from '@microsoft/sp-lodash-subset'; //import { escape } from '@microsoft/sp-lodash-subset';
/*
//ORIGINAL CODE
const getCode = (hue, saturation, lightness, shades) => {
let RESULT= "";
try {
const HUE_STEP = (hue[1] - hue[0]) / shades
const LIGHT_STEP = (lightness[1] - lightness[0]) / shades
const SAT_STEP = (saturation[1] - saturation[0]) / shades
RESULT = `:root {\n`
for (let s = 0; s < shades + 1; s++) {
const HUE = Math.floor(hue[1] - s * HUE_STEP)
const LIGHTNESS = Math.floor(lightness[1] - s * LIGHT_STEP)
const SATURATION = Math.floor(saturation[1] - s * SAT_STEP)
RESULT += ` --color-${s +
1}: hsl(${HUE}, ${SATURATION}%, ${LIGHTNESS}%);\n`
}
console.log("RESULT:", RESULT);
}
catch (ex) {}
return (RESULT += '}')
}
*/
//MADE AN OBJECT for 'getcode' export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProps> = (props) => {
//copied and modified to suit from this CodePen by Jhey https://codepen.io/jh3y/pen/rNjbmBQ?editors=0010
const cssObject = (hue, saturation, lightness, shades) => { const cssObject = (hue, saturation, lightness, shades) => {
let obj = {}; let obj = {};
try { try {
const HUE_STEP = (hue[1] - hue[0]) / shades const HUE_STEP = (hue[1] - hue[0]) / shades
const LIGHT_STEP = (lightness[1] - lightness[0]) / shades const LIGHT_STEP = (lightness[1] - lightness[0]) / shades
const SAT_STEP = (saturation[1] - saturation[0]) / shades const SAT_STEP = (saturation[1] - saturation[0]) / shades
//let RESULT = `:root {\n`
for (let s = 0; s < shades + 1; s++) { for (let s = 0; s < shades + 1; s++) {
const HUE = Math.floor(hue[1] - s * HUE_STEP) const HUE = Math.floor(hue[1] - s * HUE_STEP)
const LIGHTNESS = Math.floor(lightness[1] - s * LIGHT_STEP) const LIGHTNESS = Math.floor(lightness[1] - s * LIGHT_STEP)
@ -48,34 +27,20 @@ const getCode = (hue, saturation, lightness, shades) => {
obj[`--color-${s + 1}`] = `hsl(${HUE}, ${SATURATION}%, ${LIGHTNESS}%)`; obj[`--color-${s + 1}`] = `hsl(${HUE}, ${SATURATION}%, ${LIGHTNESS}%)`;
} }
} catch(ex) {console.log("obj problems"); } } catch(ex) {console.log("obj problems"); }
// console.log("RESULT:", RESULT);
//console.log("color obj:", obj); return obj;
return obj; //, JSON.stringify(obj)];// .replace(/['"]+/g, '')];
} }
export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProps> = (props) => {
//const[colorObj, setColorObj] = React.useState({});
const[colorObj, setColorObj] = React.useState({}); const[colorObj, setColorObj] = React.useState({});
React.useEffect(() => { React.useEffect(() => {
try { try {
setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0])); setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0]));
console.log("COBJ:",colorObj);
// props.updateWebPartProperty("cssObjectText", JSON.stringify(colorObj[0]));
// props.updateWebPartProperty("cssObjectText", JSON.stringify(colorObj));
props.updateWebPartProperty("cssObjectText", "some text");
} }
catch(ex) { catch(ex) {
console.log("color issues"); console.log("color issues");
} }
//.replace(/['"]+/g, ''));
// console.log(JSON.stringify(colorObj));//.replace(/['"]+/g, ''));
}, []); // empty array means useEffect only runs once (I think); }, []); // empty array means useEffect only runs once (I think);
@ -94,10 +59,7 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
onChange={(values) => { onChange={(values) => {
props.updateWebPartProperty("fieldSetHue", values); props.updateWebPartProperty("fieldSetHue", values);
setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0])); setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0]));
//props.updateWebPartProperty("cssObjectText", cssStyles(colorObj)); props.updateWebPartProperty("cssObject", colorObj);
console.log(escape(JSON.stringify(colorObj)));
props.updateWebPartProperty("cssObjectText", escape(JSON.stringify(colorObj))); //JSON.stringify(colorObj).replace(/['"]+/g, ''));
}} }}
renderTrack={({ props, children }) => ( renderTrack={({ props, children }) => (
<div <div
@ -136,8 +98,7 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
onChange={(values) => { onChange={(values) => {
props.updateWebPartProperty("fieldSetSat", values); props.updateWebPartProperty("fieldSetSat", values);
setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0])); setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0]));
// props.updateWebPartProperty("cssObjectText", cssStyles(colorObj)); props.updateWebPartProperty("cssObject", colorObj);
// props.updateWebPartProperty("cssObjectText", (JSON.stringify(colorObj)).replace(/['"]+/g, ''));
} }
} }
@ -182,8 +143,8 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
onChange={(values) => { onChange={(values) => {
props.updateWebPartProperty("fieldSetLight", values); props.updateWebPartProperty("fieldSetLight", values);
setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0])); setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0]));
// props.updateWebPartProperty("cssObjectText", cssStyles(colorObj)); props.updateWebPartProperty("cssObject", colorObj);
// props.updateWebPartProperty("cssObjectText", (JSON.stringify(colorObj)).replace(/['"]+/g, ''));
}} }}
renderTrack={({ props, children }) => ( renderTrack={({ props, children }) => (
@ -225,8 +186,8 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
onChange={(values) => { onChange={(values) => {
props.updateWebPartProperty("fieldSetShades", values); props.updateWebPartProperty("fieldSetShades", values);
setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0])); setColorObj(cssObject(props.properties["fieldSetHue"], props.properties["fieldSetSat"],props.properties["fieldSetLight"],props.properties["fieldSetShades"][0]));
// props.updateWebPartProperty("cssObjectText", cssStyles(colorObj)); props.updateWebPartProperty("cssObject", colorObj);
// props.updateWebPartProperty("cssObjectText", (JSON.stringify(colorObj)).replace(/['"]+/g, ''));
}} }}
renderTrack={({ props, children }) => ( renderTrack={({ props, children }) => (
<div <div
@ -255,6 +216,16 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
/> />
</fieldset> </fieldset>
<fieldset data-property="cssObjectText">
<TextField
name="objText"
multiline={true}
disabled={true}
value={props.properties.cssObjectText}
//value= {JSON.stringify(colorObj).replace(/['"]+/g, '')}
></TextField>
</fieldset>
<fieldset data-property="fieldSetDisplay" className={styles.CustomPropertyPane} > <fieldset data-property="fieldSetDisplay" className={styles.CustomPropertyPane} >
<Colors <Colors
colorObject = {colorObj} colorObject = {colorObj}
@ -270,6 +241,7 @@ export const CustomPropertyPane: React.FunctionComponent<ICustomPropertyPaneProp
</div> </div>
</fieldset> </fieldset>
</PropertyPanePortal> </PropertyPanePortal>
); );
}; };

View File

@ -2,5 +2,4 @@ export interface IColorsProps {
colorObject: any; colorObject: any;
fontColor: string; fontColor: string;
context: any; context: any;
// colorObjectString: string;
} }

View File

@ -1,4 +1,6 @@
export interface IPalettePickerProps { export interface IPalettePickerProps {
cssObjectText; cssObjectText;
context; context;
cssObject;
fontColor;
} }

View File

@ -10,7 +10,7 @@
.row { .row {
@include ms-Grid-row; @include ms-Grid-row;
@include ms-fontColor-white; @include ms-fontColor-white;
background-color: $ms-color-themeDark; /* background-color: $ms-color-themeDark; */
padding: 20px; padding: 20px;
} }

View File

@ -1,17 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import styles from './PalettePicker.module.scss'; import styles from './PalettePicker.module.scss';
import { IPalettePickerProps } from './IPalettePickerProps'; import { IPalettePickerProps } from './IPalettePickerProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { Dropdown, DropdownMenuItemType, IDropdownStyles, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; import { Dropdown, DropdownMenuItemType, IDropdownStyles, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
const dropdownStyles: Partial<IDropdownStyles> = {
dropdown: { width: 300
}
};
const options: IDropdownOption[] = [ const options: IDropdownOption[] = [
{ key: 'apple', text: 'Apple' }, { key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' }, { key: 'banana', text: 'Banana' },
@ -22,31 +14,81 @@ const options: IDropdownOption[] = [
{ key: 'lettuce', text: 'Lettuce' } { key: 'lettuce', text: 'Lettuce' }
]; ];
const returnCss = (obj) => {
let newObj = {};
Object.keys(obj).map((key, i) => {
newObj[`.ms-Dropdown-item:nth-of-type(${i+1})`] = { "backgroundColor": obj[key] };
});
return newObj;
}
export default class PalettePicker extends React.Component<IPalettePickerProps, {}> { export default class PalettePicker extends React.Component<IPalettePickerProps, {}> {
public componentDidMount() { constructor(props: IPalettePickerProps) {
// console.log("css:", JSON.parse(this.props.colorObj)); super(props);
}
private dropdownStyles: Partial<IDropdownStyles> = {
root: this.props.cssObject,
label: {color: this.props.fontColor},
/* dropdownItem: {
backgroundColor: 'pink'
}, */
/* dropdownItemsWrapper: {
style: this.props.cssObject ? this.props.cssObject : {},
}, */
dropdownItems: {
selectors: returnCss(this.props.cssObject),
dropdown: { width: 300
}
} }
}
//console.log(props)
public render(): React.ReactElement<IPalettePickerProps> { public render(): React.ReactElement<IPalettePickerProps> {
console.log("styles:", this.dropdownStyles);
console.log("obj", returnCss(this.props.cssObject));
return ( return (
<div className={ styles.palettePicker }> <div style={this.props.cssObject} className={ styles.palettePicker }>
<div className={ styles.container }> <div>
<div className={ styles.row }> <div className={ styles.row } style={{backgroundColor: this.props.cssObject["--color-1"], color: this.props.fontColor}}>
<div className={ styles.column }> <div className={ styles.column }>
<span className={ styles.title }>Welcome to SharePoint!</span> <span className={ styles.title } style={{color: this.props.fontColor}}>Here's a Palette Picker for you!</span>
<p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p> <p className={ styles.subTitle } style={{color: this.props.fontColor}}>Allow users to select a color palette for your web part.</p>
<Dropdown placeholder="Select an option" label="Basic uncontrolled example" options={options} styles={dropdownStyles} /> <div style={{height: 'auto', minHeight: '20px', backgroundColor: this.props.fontColor}}>
{Object.keys(this.props.cssObject).map((key,i) =>{
<a href="https://aka.ms/spfx" className={ styles.button }> return <div style={{backgroundColor: this.props.cssObject[key], height:'10px', width: '10px', display: 'inline-block', borderRadius: '50%', left: 0, top: 0 }}></div>
<span className={ styles.label }>Learn more</span> })}
</div>
<Dropdown placeholder="Select an option" label="Color your dropdown options .." options={options} styles={this.dropdownStyles} />
<div>
</div>
<a href="https://aka.ms/spfx" className={ styles.button } style={{backgroundColor: this.props.cssObject["--color-3"], color: this.props.fontColor}}>
<span className={ styles.label } style={{color: this.props.fontColor}}>Learn more</span>
</a> </a>
<pre style={{font: 'courier', backgroundColor: this.props.cssObject["--color-5"], color: this.props.fontColor}}> {JSON.stringify(this.props.cssObject, null, 4)}</pre>
</div> </div>
</div> </div>
</div> </div>

View File

@ -25,7 +25,8 @@
"es5", "es5",
"dom", "dom",
"es2015.collection", "es2015.collection",
"es2015.promise" "es2015.promise",
"es2017.object"
] ]
}, },
"include": [ "include": [