Page Section Navigation updates: SPFx 1.8, comments, additional theme (#819)
* Page Section Navigation updates: SPFx 1.8, comments, additional theme * readme * readme version * final changes for 1.8
This commit is contained in:
parent
cd22efec38
commit
ebc203b7d5
|
@ -5,7 +5,7 @@ Sample web parts allowing to add sections navigation to the SharePoint page.
|
|||
![Navigation configuration](./assets/page-nav.gif)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/drop-1.7.1-green.svg)
|
||||
![drop](https://img.shields.io/badge/drop-1.8.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
|
@ -23,6 +23,7 @@ page-sections-navigation|Alex Terentiev (MVP, [Sharepointalist Inc.](http://www.
|
|||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|February 27, 2019|Initial release
|
||||
1.1|March 22, 2019| Update to SPFx 1.8, additional theme, comments
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,10 +11,10 @@
|
|||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.7.1",
|
||||
"@microsoft/sp-lodash-subset": "1.7.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.7.1",
|
||||
"@microsoft/sp-webpart-base": "1.7.1",
|
||||
"@microsoft/sp-core-library": "1.8.0",
|
||||
"@microsoft/sp-lodash-subset": "1.8.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.8.0",
|
||||
"@microsoft/sp-webpart-base": "1.8.0",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/react": "16.4.2",
|
||||
"@types/react-dom": "16.0.5",
|
||||
|
@ -28,10 +28,11 @@
|
|||
"@types/react": "16.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.7.1",
|
||||
"@microsoft/sp-tslint-rules": "1.7.1",
|
||||
"@microsoft/sp-module-interfaces": "1.7.1",
|
||||
"@microsoft/sp-webpart-workbench": "1.7.1",
|
||||
"@microsoft/sp-build-web": "1.8.0",
|
||||
"@microsoft/sp-tslint-rules": "1.8.0",
|
||||
"@microsoft/sp-module-interfaces": "1.8.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.8.0",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.1.7",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
/**
|
||||
* Anchor interface to be transferred to the "master" web part
|
||||
*/
|
||||
export interface IAnchorItem {
|
||||
/**
|
||||
* Title
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* Unique Id
|
||||
*/
|
||||
uniqueId?: string;
|
||||
//scrollTop?: number;
|
||||
/**
|
||||
* DOM element
|
||||
*/
|
||||
domElement?: HTMLElement;
|
||||
}
|
|
@ -1,3 +1,14 @@
|
|||
/**
|
||||
* Possible positions of the navigation:
|
||||
* - section - inside the section where the web part has been added
|
||||
* - top - on top of page canvas
|
||||
*/
|
||||
export type NavPosition = 'section' | 'top';
|
||||
export type NavTheme = 'light' | 'dark';
|
||||
/**
|
||||
* Possible "themes" for the navigation element
|
||||
*/
|
||||
export type NavTheme = 'light' | 'dark' | 'theme';
|
||||
/**
|
||||
* Navigation alignment
|
||||
*/
|
||||
export type NavAlign = 'flex-start' | 'center' | 'flex-end';
|
|
@ -10,6 +10,7 @@ define([], function () {
|
|||
"ThemeLabel": "Navigation Theme color",
|
||||
"ThemeLight": "Light",
|
||||
"ThemeDark": "Dark",
|
||||
"ThemeTheme": "Theme color",
|
||||
"AlignLabel": "Navigation align",
|
||||
"AlignLeft": "Left",
|
||||
"AlignCenter": "Center",
|
||||
|
|
|
@ -9,6 +9,7 @@ declare interface IPageSectionsNavigationStrings {
|
|||
ThemeLabel: string;
|
||||
ThemeLight: string;
|
||||
ThemeDark: string;
|
||||
ThemeTheme: string;
|
||||
AlignLabel: string;
|
||||
AlignLeft: string;
|
||||
AlignCenter: string;
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
"properties": {
|
||||
"scrollBehavior": "auto",
|
||||
"position": "section",
|
||||
"isDark": false,
|
||||
"align": "left"
|
||||
"align": "left",
|
||||
"theme": "light"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneDropdown,
|
||||
PropertyPaneToggle,
|
||||
PropertyPaneChoiceGroup,
|
||||
PropertyPaneCheckbox,
|
||||
PropertyPaneTextField
|
||||
|
@ -15,12 +14,13 @@ import * as strings from 'PageSectionsNavigationStrings';
|
|||
import { PageSectionsNavigation, IPageSectionsNavigationProps } from './components/PageSectionsNavigation';
|
||||
import { IDynamicDataSource, IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data';
|
||||
import { IAnchorItem } from '../../common/model';
|
||||
import { NavPosition, NavAlign } from '../../common/types';
|
||||
import { NavPosition, NavAlign, NavTheme } from '../../common/types';
|
||||
|
||||
export interface IPageSectionsNavigationWebPartProps {
|
||||
scrollBehavior: ScrollBehavior;
|
||||
position: NavPosition;
|
||||
isDark: boolean;
|
||||
isDark?: boolean;
|
||||
theme: NavTheme;
|
||||
align: NavAlign;
|
||||
showHomeItem: boolean;
|
||||
homeItemText: string;
|
||||
|
@ -28,20 +28,21 @@ export interface IPageSectionsNavigationWebPartProps {
|
|||
}
|
||||
|
||||
export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart<IPageSectionsNavigationWebPartProps> implements IDynamicDataCallables {
|
||||
|
||||
// "Anchor" data sources
|
||||
private _dataSources: IDynamicDataSource[] = [];
|
||||
//private _anchors: IAnchorItem[];
|
||||
|
||||
|
||||
protected onInit(): Promise<void> {
|
||||
const { customCssUrl } = this.properties;
|
||||
|
||||
this._onAnchorChanged = this._onAnchorChanged.bind(this);
|
||||
// getting data sources that have already been added on the page
|
||||
this._initDataSources();
|
||||
// registering for changes in available datasources
|
||||
this.context.dynamicDataProvider.registerAvailableSourcesChanged(this._initDataSources.bind(this, true));
|
||||
|
||||
this._addCustomCss(customCssUrl);
|
||||
|
||||
// registering current web part as a data source
|
||||
this.context.dynamicDataSourceManager.initializeSource(this);
|
||||
|
||||
return super.onInit();
|
||||
|
@ -54,6 +55,7 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
scrollBehavior,
|
||||
position,
|
||||
isDark,
|
||||
theme,
|
||||
align,
|
||||
showHomeItem,
|
||||
homeItemText
|
||||
|
@ -64,22 +66,30 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
anchors: anchors,
|
||||
scrollBehavior: scrollBehavior,
|
||||
position: position,
|
||||
theme: isDark ? 'dark' : 'light',
|
||||
theme: theme ? theme : (isDark ? 'dark' : 'light'),
|
||||
align: align,
|
||||
isEditMode: this.displayMode === DisplayMode.Edit,
|
||||
homeItem: showHomeItem && homeItemText
|
||||
homeItem: showHomeItem ? homeItemText : ''
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* implementation of getPropertyDefinitions from IDynamicDataCallables
|
||||
*/
|
||||
public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> {
|
||||
return [{
|
||||
id: 'position',
|
||||
title: 'position'
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* implementation of getPropertyValue from IDynamicDataCallables
|
||||
* @param propertyId property Id
|
||||
*/
|
||||
public getPropertyValue(propertyId: string): NavPosition {
|
||||
switch (propertyId) {
|
||||
case 'position':
|
||||
|
@ -97,6 +107,14 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Manual handling of changed properties.
|
||||
* If position has been changed we need to notify subscribers
|
||||
* If custom css has been changed we need to add new CSS to the page
|
||||
* @param propertyPath
|
||||
* @param oldValue
|
||||
* @param newValue
|
||||
*/
|
||||
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any) {
|
||||
if (propertyPath === 'position') {
|
||||
this.context.dynamicDataSourceManager.notifyPropertyChanged('position');
|
||||
|
@ -108,7 +126,7 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
if (oldValue) {
|
||||
const oldCssLink = this._getCssLink(oldValue);
|
||||
if (oldCssLink) {
|
||||
oldCssLink.parentElement.removeChild(oldCssLink);
|
||||
oldCssLink.parentElement!.removeChild(oldCssLink);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +136,15 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
const align = this.properties.align || 'left';
|
||||
const {
|
||||
scrollBehavior,
|
||||
position,
|
||||
theme,
|
||||
isDark,
|
||||
showHomeItem,
|
||||
homeItemText,
|
||||
customCssUrl
|
||||
} = this.properties;
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
|
@ -137,7 +164,7 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
key: 'smooth',
|
||||
text: strings.SmoothScrollBehavior
|
||||
}],
|
||||
selectedKey: this.properties.scrollBehavior || 'auto'
|
||||
selectedKey: scrollBehavior || 'auto'
|
||||
}),
|
||||
PropertyPaneDropdown('position', {
|
||||
label: strings.PositionLabel,
|
||||
|
@ -148,13 +175,21 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
key: 'top',
|
||||
text: strings.PositionTop
|
||||
}],
|
||||
selectedKey: this.properties.position || 'top'
|
||||
selectedKey: position || 'top'
|
||||
}),
|
||||
PropertyPaneToggle('isDark', {
|
||||
PropertyPaneDropdown('theme', {
|
||||
label: strings.ThemeLabel,
|
||||
offText: strings.ThemeLight,
|
||||
onText: strings.ThemeDark,
|
||||
checked: !!this.properties.isDark
|
||||
options: [{
|
||||
key: 'light',
|
||||
text: strings.ThemeLight
|
||||
}, {
|
||||
key: 'theme',
|
||||
text: strings.ThemeTheme
|
||||
}, {
|
||||
key: 'dark',
|
||||
text: strings.ThemeDark
|
||||
}],
|
||||
selectedKey: theme ? theme : isDark ? 'dark' : 'light'
|
||||
}),
|
||||
PropertyPaneChoiceGroup('align', {
|
||||
label: strings.AlignLabel,
|
||||
|
@ -183,15 +218,15 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
}),
|
||||
PropertyPaneCheckbox('showHomeItem', {
|
||||
text: strings.HomeNavItemCbxLabel,
|
||||
checked: this.properties.showHomeItem
|
||||
checked: showHomeItem
|
||||
}),
|
||||
PropertyPaneTextField('homeItemText', {
|
||||
label: strings.HomeNavItemTextLabel,
|
||||
value: this.properties.homeItemText || strings.HomeNavItemDefaultText
|
||||
value: homeItemText || strings.HomeNavItemDefaultText
|
||||
}),
|
||||
PropertyPaneTextField('customCssUrl', {
|
||||
label: strings.CustomCSSLabel,
|
||||
value: this.properties.customCssUrl
|
||||
value: customCssUrl
|
||||
})
|
||||
]
|
||||
}
|
||||
|
@ -201,10 +236,16 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes collection of "Anchor" data soures based on collection of existing page's data sources
|
||||
* @param reRender specifies if the web part should be rerendered
|
||||
*/
|
||||
private _initDataSources(reRender?: boolean) {
|
||||
// all data sources on the page
|
||||
const availableDataSources = this.context.dynamicDataProvider.getAvailableSources();
|
||||
|
||||
if (availableDataSources && availableDataSources.length) {
|
||||
// "Ahchor" data sources cached in the web part from prev call
|
||||
const dataSources = this._dataSources;
|
||||
//
|
||||
// removing deleted data sources if any
|
||||
|
@ -234,23 +275,20 @@ export default class PageSectionsNavigationWebPart extends BaseClientSideWebPart
|
|||
if (!dataSources || !dataSources.filter(ds => ds.id === dataSource.id).length) {
|
||||
dataSources.push(dataSource);
|
||||
this.context.dynamicDataProvider.registerPropertyChanged(dataSource.id, 'anchor', this._onAnchorChanged);
|
||||
//this._anchors.push(dataSource.getPropertyValue('anchor') as IAnchorItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: unregister events for deleted data sources
|
||||
|
||||
//this._dataSources = availableDataSources;
|
||||
|
||||
if (reRender) {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when any of anchors has been changed
|
||||
*/
|
||||
private _onAnchorChanged() {
|
||||
this.render();
|
||||
//console.log(ds.getPropertyValue('anchor'));
|
||||
}
|
||||
|
||||
private _addCustomCss(customCssUrl: string) {
|
||||
|
|
|
@ -37,6 +37,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.theme {
|
||||
background: "[theme: themePrimary, default: #0078d4]";
|
||||
border-bottom-color: "[theme:themePrimary, default: #0078d4]";
|
||||
.nav {
|
||||
.navItem {
|
||||
.navItemLink {
|
||||
color: "[theme:white, default: #fff]";
|
||||
|
||||
&:hover {
|
||||
color: "[theme:neutralLighter, default: #f4f4f4]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background: "[theme: neutralDark, default: #212121]";
|
||||
border-bottom-color: "[theme:white, default: #fff]";
|
||||
|
|
|
@ -27,13 +27,18 @@ export interface IPageSectionsNavigationState {
|
|||
|
||||
|
||||
export class PageSectionsNavigation extends React.Component<IPageSectionsNavigationProps, IPageSectionsNavigationState> {
|
||||
|
||||
// layer div to host navigation elements OUTSIDE of normal DOM hierarchy
|
||||
private _layerElement: HTMLElement | undefined;
|
||||
// parent node where the current component should be renderred
|
||||
private _host: Node;
|
||||
// span DOM element that is renderered IN normal DOM hierarchy
|
||||
private _sectionHostSpanRef = React.createRef<HTMLSpanElement>();
|
||||
// first scrollable parent in normal DOM hierarchy. Needed for Home click implementation
|
||||
private _scrollableParent: Element;
|
||||
|
||||
// page canvas DOM element id
|
||||
private readonly _pageCanvasId = 'spPageCanvasContent';
|
||||
// page layout element selector
|
||||
private readonly _pageLayoutSelector = '[class*="layoutWrapper_"]';
|
||||
|
||||
constructor(props: IPageSectionsNavigationProps) {
|
||||
|
@ -51,10 +56,12 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
|
||||
public componentWillUpdate(nextProps: IPageSectionsNavigationProps) {
|
||||
if (nextProps.position !== this.props.position) {
|
||||
// updating layer based on position
|
||||
this._removeLayerElement();
|
||||
this._layerElement = this._getLayerElement(nextProps.position);
|
||||
}
|
||||
else if (!this._layerElement) {
|
||||
// creating layer if not exist
|
||||
this._layerElement = this._getLayerElement();
|
||||
}
|
||||
}
|
||||
|
@ -81,8 +88,11 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
if (theme === 'dark') {
|
||||
rootDivClassNames[styles.dark] = true;
|
||||
}
|
||||
else if (theme === 'theme') {
|
||||
rootDivClassNames[styles.theme] = true;
|
||||
}
|
||||
|
||||
const navItems: JSX.Element[] = this.props.anchors.map((anchor, index) => {
|
||||
const navItems: JSX.Element[] = this.props.anchors.map((anchor) => {
|
||||
return <li className={css(styles.navItem, 'psn-navItem')}>
|
||||
<a className={css(styles.navItemLink, 'psn-navItemLink')} onClick={this._onClick.bind(this, anchor)}>{anchor.title}</a>
|
||||
</li>;
|
||||
|
@ -93,6 +103,9 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
</li>);
|
||||
}
|
||||
|
||||
//
|
||||
// React Portal component is used to render navigation outside of normal div hierarchy
|
||||
//
|
||||
return (
|
||||
<span ref={this._sectionHostSpanRef}>
|
||||
{
|
||||
|
@ -116,6 +129,7 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
}
|
||||
|
||||
private _onHomeClick() {
|
||||
// home click
|
||||
if (!this._scrollableParent) {
|
||||
this._initScrollParent();
|
||||
}
|
||||
|
@ -127,6 +141,7 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
|
||||
private _onClick(anchor: IAnchorItem, index: number) {
|
||||
|
||||
// click on one of anchor's nav items
|
||||
if (anchor.domElement) {
|
||||
anchor.domElement.scrollIntoView({
|
||||
behavior: this.props.scrollBehavior,
|
||||
|
@ -135,6 +150,10 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates layer element to host the navigation outside of normal DOM hierarchy
|
||||
* @param position - current position value
|
||||
*/
|
||||
private _getLayerElement(position?: NavPosition): HTMLElement | undefined {
|
||||
const host = this._getHost(position);
|
||||
|
||||
|
@ -172,11 +191,19 @@ export class PageSectionsNavigation extends React.Component<IPageSectionsNavigat
|
|||
}
|
||||
}
|
||||
|
||||
private _getHost(position: NavPosition): Node | undefined {
|
||||
/**
|
||||
* gets host DOM element based on position property
|
||||
* @param position - current position value
|
||||
*/
|
||||
private _getHost(position?: NavPosition): Node | undefined {
|
||||
|
||||
const navPos = position || this.props.position;
|
||||
|
||||
const doc = getDocument();
|
||||
if (!doc) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let hostNode: Node;
|
||||
|
||||
if (navPos === 'section') {
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Version } from '@microsoft/sp-core-library';
|
|||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField,
|
||||
PropertyPaneCheckbox
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
|
@ -27,8 +26,10 @@ export interface IPageSectionsNavigationAnchorWebPartProps {
|
|||
|
||||
export default class PageSectionsNavigationAnchorWebPart extends BaseClientSideWebPart<IPageSectionsNavigationAnchorWebPartProps> implements IDynamicDataCallables {
|
||||
|
||||
// anchor data object related to the current web part
|
||||
private _anchor: IAnchorItem;
|
||||
private _pageNavDataSource: IDynamicDataSource;
|
||||
// "Master" data source
|
||||
private _pageNavDataSource: IDynamicDataSource | undefined;
|
||||
|
||||
protected onInit(): Promise<void> {
|
||||
|
||||
|
@ -42,8 +43,11 @@ export default class PageSectionsNavigationAnchorWebPart extends BaseClientSideW
|
|||
uniqueId: uniqueId
|
||||
};
|
||||
|
||||
// getting data sources that have already been added on the page
|
||||
this._initDataSource();
|
||||
// registering for changes in available datasources
|
||||
this.context.dynamicDataProvider.registerAvailableSourcesChanged(this._initDataSource.bind(this));
|
||||
// registering current web part as a data source
|
||||
this.context.dynamicDataSourceManager.initializeSource(this);
|
||||
|
||||
if (!uniqueId) {
|
||||
|
@ -65,8 +69,8 @@ export default class PageSectionsNavigationAnchorWebPart extends BaseClientSideW
|
|||
showTitle: showTitle,
|
||||
updateProperty: this._onTitleChanged.bind(this),
|
||||
anchorElRef: (el => {
|
||||
this._anchor.domElement = el; //this.domElement;
|
||||
//this._anchor.scrollTop = this.domElement.scrollTop;
|
||||
// notifying subscribers that the anchor component has been rendered
|
||||
this._anchor.domElement = el;
|
||||
this.context.dynamicDataSourceManager.notifyPropertyChanged('anchor');
|
||||
}),
|
||||
navPosition: position
|
||||
|
@ -77,12 +81,20 @@ export default class PageSectionsNavigationAnchorWebPart extends BaseClientSideW
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* implementation of getPropertyDefinitions from IDynamicDataCallables
|
||||
*/
|
||||
public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> {
|
||||
return [{
|
||||
id: 'anchor',
|
||||
title: 'Anchor'
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* implementation of getPropertyValue from IDynamicDataCallables
|
||||
* @param propertyId property Id
|
||||
*/
|
||||
public getPropertyValue(propertyId: string): IAnchorItem {
|
||||
switch (propertyId) {
|
||||
case 'anchor':
|
||||
|
@ -125,11 +137,19 @@ export default class PageSectionsNavigationAnchorWebPart extends BaseClientSideW
|
|||
|
||||
private _onTitleChanged(title: string) {
|
||||
this._anchor.title = this.properties.title = title;
|
||||
// notifying that web part's title has been changed
|
||||
this.context.dynamicDataSourceManager.notifyPropertyChanged('anchor');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes "master" data source
|
||||
*/
|
||||
private _initDataSource(): void {
|
||||
// all data sources on the page
|
||||
const availableDataSources = this.context.dynamicDataProvider.getAvailableSources();
|
||||
//
|
||||
// searching for "master" data source
|
||||
//
|
||||
let hasPageNavDataSource = false;
|
||||
for (let i = 0, len = availableDataSources.length; i < len; i++) {
|
||||
let dataSource = availableDataSources[i];
|
||||
|
|
|
@ -1,42 +1,45 @@
|
|||
.webPartTitle {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
font-weight: 100;
|
||||
margin-bottom: 11px;
|
||||
color: "[theme:neutralPrimary, default: #333333]";
|
||||
|
||||
@media (min-width: 320px) {
|
||||
font-size: 21px;
|
||||
}
|
||||
&.visible {
|
||||
font-size: 14px;
|
||||
font-weight: 100;
|
||||
margin-bottom: 11px;
|
||||
color: "[theme:neutralPrimary, default: #333333]";
|
||||
|
||||
@media (min-width: 480px) {
|
||||
font-size: 24px;
|
||||
}
|
||||
@media (min-width: 320px) {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
// Edit mode
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
display: block;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
height: 40px;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
text-align: inherit;
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 480px) {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
// View mode
|
||||
span {
|
||||
font-weight: 300;
|
||||
// Edit mode
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
display: block;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
height: 40px;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
text-align: inherit;
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// View mode
|
||||
span {
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
|
||||
.anchorEl {
|
||||
|
|
|
@ -35,7 +35,7 @@ export class PageSectionsNavigationAnchor extends React.Component<IPageSectionsN
|
|||
|
||||
if (displayMode === DisplayMode.Edit || showTitle) {
|
||||
return (
|
||||
<div className={css(styles.webPartTitle, 'psn-anchorTitle')}>
|
||||
<div className={css(styles.webPartTitle, styles.visible, 'psn-anchorTitle')}>
|
||||
<div className={css(anchorElClassNames)} ref={anchorElRef}></div>
|
||||
{
|
||||
displayMode === DisplayMode.Edit
|
||||
|
@ -48,8 +48,13 @@ export class PageSectionsNavigationAnchor extends React.Component<IPageSectionsN
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
else {
|
||||
return (
|
||||
<div className={styles.webPartTitle}>
|
||||
<div className={css(anchorElClassNames)} ref={anchorElRef}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
|
Loading…
Reference in New Issue